【カウンタとして使う】
PICのタイマーは入力として内部クロック信号以外に、外部からの
パルス信号を使うことも 出来ます。
その入力ピンが、RA4(T0CKI)です。 これを使うと、外部信号の
カウントをすることが出来、人数カウンターや、周波数カウンターなど
を作ることが出来ます。
ここではまず、易しい人数や事象のカウンタを作る方法の紹介と、
比較的難しい周波数カウンタとして動作させる方法の両方を紹介し
ます。
【PICのカウンタの内部構成】
実際のPICの内部カウンタの構成は下図のようになっています。
ここでRTE,RTS,PSAという信号は内部の切替制御信号で、OPTION
レジスタで指定します。 一度指定すればそのまま電源が切れる
まで、つまりRESETがかかるまでは保持されます。
ここで各々の意味を説明します。
・RTS:入力切替
カウンタへの入力信号を内部クロックにするか、外部信号にするか
の指定で、カウンタとして使う時には外部とします。
・RTE:エッジ切替
入力信号の立上がりか立下がりどちらのエッジでカウントアップを
するかを指定します。 信号が入った時にカウントアップするので
立ち上がりエッジとしておきます。
・PSA:プリスケーラ切替
プリスケーラカウンタを使うか使わないかを指定します。プリスケー
ラはカウンタTMR0の前段に付くカウンタで、高速に動作することが
できます。 その代わり、プリスケーラはプログラムで読み出すこと
が出来ないので一つづつのカウント表示は出来なくなります。
つまり、プリスケーラを8カウント動作と指定すると、8カウント単位
でしか表現できないことになります。プリスケーラは8ビットカウンタ
となっているので、最大256カウントのプリスケールが出来ます。
プリスケールの動作指定はOPTINレジスタのPS0,1,2の3ビットで行
います。 2,4,8,16,32,64,128,256の8通りのプリスケール値が指定で
きます。
・TMR0:カウンタ本体
内部カウンタ本体で、8ビットのカウンタです。従ってこれだけだと
256カウントが最大値ということになります。
プリスケーラの最大と合せて16ビットつまり65,535カウントが最大
値となります。
カウンタへの条件設定などした時には常にTMR0はゼロクリアされ
ます。またカウンタがオーバーフローした時にはオーバーフローフラ
グとしてINTCONレジスタ内のT0IFビットが"1"となります。
また割込みを許可していればこの時点で割込みが発生します。
このT0IFビットはプログラムでCLEARするまで1のままを保持します。
従って、オーバーフロー処理でこれを0 CLEARしないと次のオーバー
フローが分からなくなります。
【カウンタの性能】
PICの内部カウンタ動作がどれほど高速に動作するかは、規格表から
下記の様になります。前提はクロックは10MHzとします。
結論からいうと、プリスケーラ無しの時は、最大2.3MHz プリスケーラ
付きの時は、最大18MHzとなります。
TMR0カウンタ本体 : 最小パルス幅=(クロックサイクル)+20nsec =420nsec周期=2.38MHz
プリスケーラ本体 : 最小パルス幅=50nsec(電源5V)
=20MHz
プリスケーラとTMR0の組み合わせの時
: 最小パルス幅=((クロックサイクル)+40nsec)/(プリスケーラ値)
プリスケーラ値毎に計算すると
=440/2=220nsec=4.54MHz
=440/4=110nsec=9.09MHz
=440/8= 55nsec=18.1MHz(最大動作値)
=440/16=27.5nsec=36.3MHZ>20MHz
【事象カウンタとする】
まずカウンタの動作モードを設定するための初期設定から始めます。
【初期設定ルーチン】
BSF STATUS,RP0 ;Set page 1
MOVLW 0E8H ;set to no prescale
MOVWF OPTION_REG ;OPTION register set
BCF STATUS,RP0 ;Set Page 0
CLRF TMR0 ;Clear TMR0
[OPTIONレジスタの設定]
RBPU 1 :PORTBのPullUp =なし
INTEDGE 1 :INT割込み信号のエッジ =立ち上がり
RTS 1 :入力の選択 =RA4ピン指定
RTE 0 :TMR0のカウントエッジ =立ち上がり
PSA 1 :プリスケーラ有無 =無し
PS1〜3 0 :プリスケーラ値 =無指定
次にカウンタ結果を読込む方法です。
TMR0だけだと8ビットカウンタですので256カウントが最大カウント数
です。しかし、オーバーフローフラグがあるので、これを使えばプログラ
ムでオーバーフローフラグを常に監視することでカウンターのバイト数
を任意に拡張することが出来ます。
下記例はBYTE0,1の2バイトのカウンターとなります。
【オーバーフローフラグの監視ルーチン】
LOOP BTFSS INTCON,T0IF ;get overflow flag
GOTO SKIP ;goto not overflow
BCF INTCON,T0IF ;reset T0IF
MOVLW 1 ;count up data
GOTO NEXT
SKIP NOP ;dumy NOP
NOP
MOVLW 0 ;not count up data
NEXT ADDWF BYTE1,F ;BYTE1+T0IF
MOVF TMR0,W ;get TMR0
MOVWF BYTE0 ;set to BYTE0
GOTO LOOP
【周波数カウンタとする】
「一定時間(例えば100msec)だけ外部信号のカウントをする。」という
ことが出来れば、周波数カウンタとなります。 従って、外部にゲート回路
を設け、一定時間をPICのソフトウェアで作りこのゲートの開け閉めを制御
します。
しかし、難しいのは、この一定時間を作っている間でも、周波数カウントは
一緒に間断なく継続しているように、ソフトウェアを動かさなければなけれ
ばならないところです。
【カウンタ動作ルーチン】
カウント結果をBYTE1〜2の3バイトに格納する。プリスケーラ無しの
設定で前項の初期設定と同じ設定とする。100msecの一定時間だけ
カウントするためゲートの空いている時間をプログラムステップ数で
制御する。外部ゲートの制御はPORTBのRB0で行っている。
MESURE CLRF TMR0 ;counter reset
BSF PORTB,0 ;open GATE
CLRF OVRFLW ;reset overflow flag
CALL LOOP ;(249996+2steps)
NOP ;dumy NOP (249999steps)
BCF PORTB,0 ;close GATE(250000steps)
MOVF TMR0,W ;get TMR0
MOVWF BYTE0 ;set to BYTE0
RETURN
;オーバーフロー監視、カウントアップ
;一定時間の確保(100msec)
LOOP MOVLW 08DH ;loop counter 141
MOVWF LPCNT1
MESLP1 MOVLW 088H ;set counter 136
MOVWF LPCNT2 ;set counter
MESLP2 BTFSS INTCON,T0IF ;13 steps loop
GOTO DUMY1
BCF INTCON,T0IF ;reset T0IF
MOVLW 1 ;カウントアップ
GOTO NEXT
DUMY1 NOP ;dumy NOP
NOP ;同じステップ数にするため
MOVLW 0 ;カウントアップ無し
NEXT ADDWF BYTE1,F ;BYTE1+T0IF
RLF BYTE1,W ;carry to d0
ANDLW 1 ;mask
ADDWF BYTE2,F ;BYTE2+Carry
DECFSZ LPCNT2,F ;check loop end
GOTO MESLP2 ;loop
NOP
MESLP3 DECFSZ LPCNT1,F ;(13*LPCNT2+5)*LPCNT1
GOTO MESLP1 ;(13*136+5)*141=249993-1
RETURN ;+2=249994
さて次ぎは液晶表示器との接続とその制御ソフトについてです。