前回は割り込みの基本ということでINTCONレジスタを扱う基本の割り込みを扱った。8ビットタイマーで20ミリ秒単位の割り込みを発生させるためには1:128の分周が必要なのでカウントタイミングは128マイクロ秒単位となる。
一方、PIC12F675には16ビットタイマーも含まれているのでプリスケールナシで65.536ミリ秒まで計測できる。これなら精度は128倍になるはずだ。そこで、今回は16ビットタイマーにも手を出してみよう。
そうなるとPIC12F675の英文マニュアルを読まないといけない。8ビットタイマーと16ビットタイマーの違いはカウンタが2倍になるだけでなく、プリスケーラも1:1、2、4、8の切り替えになり、割り込みの設定、割り込みの確認が別のレジスタになる。
今まではINTCONレジスタだけ相手にしていればよかったのだが、INTCONのPEIEをセットしたうえで(もちろんGIEもセットしないと割り込みがかからない)、PIE1レジスタの該当ビット(16ビットタイマーは第0ビットのTMR1E)も立てる必要がある。古いPICのタイマーが8ビットのみで、機能を増やした結果このようになったようだ。今回のシリーズは複数の割り込みを同時に扱わないのだが、仮に扱う場合はフラグを順にチェックする必要がある。
ソースを変更して、今度は割り込みルーチンの冒頭にブレークポイントを設定してみるとたしかに精度は上がっているが、たまに1マイクロ秒ずれることがある。割り込みは各命令の実行後に判断され、ジャンプ系命令は2サイクル必要となるのだは、これが「ずれ」の原因となるようだ。
また、プリスケーラなしでひたすらカウンターが動いているので割り込みルーチンに入ってもタイマーはインクリメントを続ける。最初に与えた値と割り込みルーチンの冒頭で与える値が異なるのは、再セットまでの時間差を考慮したものだ。先の1サイクルずれる問題もあわせて、ズレをなくすにはタイマーを読み出して引き算を行って再セットするのがよいのだが、別にそこまで対処する必要なないので、ここではこのまま使おう。
なお、サンプルプログラムではサーボを動かすルーチンも書き直して、2つのサーボを扱えるように拡張している。また、サーボのパラメーターをレジスタに確保してある。
;
; RCサーボの制御テスト 16bit timer version
;
▼▼ |
LIST P=PIC12F675 |
▼▼ |
INCLUDE "P12F675.INC" |
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF &_MCLRE_OFF |
;
;
;
▼▼ RC1POS |
EQU |
20H |
RC2POSEQU 21H |
▼▼ COUNT |
EQU |
|
22H |
▼▼ WBUF |
EQU |
|
23H |
SBUFEQU24H |
▼▼ |
ORG |
|
0 |
▼▼ |
GOTO |
MAIN |
▼▼ |
ORG |
|
4 |
GOTOINTMAIN |
MAIN
▼▼ |
CLRWDT |
|
|
|
; 割り込み関連初期化 |
▼▼ |
CALL |
3FFh |
|
; 内蔵オシレーター調整 |
▼▼ |
MOVWF |
OSCCAL |
▼▼ |
BCF |
|
STATUS,RP0 |
▼▼ |
MOVLW |
B'00000001' |
; TMR1 1:1 |
▼▼ |
MOVWF |
T1CON |
▼▼ |
MOVLW |
B'11000000' |
; GIE & PEIE |
▼▼ |
MOVWF |
INTCON |
▼▼ |
BSF |
|
STATUS,RP0 |
▼▼ |
MOVLW |
B'10000001' |
; EEIE & TMR1IE |
▼▼ |
MOVWF |
PIE1 |
▼▼ |
BCF |
|
STATUS,RP0 |
▼▼ |
MOVLW |
0F0H |
|
; タイマ初期化 20ms |
▼▼ |
MOVWF |
TMR1L |
▼▼ |
MOVLW |
0B1H |
MOVWFTMR1H |
;
▼▼ CLRF |
GPIO |
▼▼ |
MOVLW |
07h |
▼▼ |
MOVWF |
CMCON |
▼▼ |
BSF |
|
STATUS,RP0 ; Bank 1 へ切替 |
▼▼ |
CLRF |
TRISIO |
▼▼ |
CLRF |
ANSEL |
BCFSTATUS,RP0 ; Bank 0 へ戻る |
;
▼▼ |
MOVLW |
080H |
|
; フェイルセーフ |
▼▼ |
MOVWF |
RC1POS |
MOVWFRC2POS |
LP
▼▼ |
NOP |
▼▼ |
NOP |
▼▼ |
NOP |
▼▼ |
NOP |
GOTO LP |
INTMAIN
▼▼ |
MOVWF |
WBUF |
|
; レジスタ類退避 |
▼▼ |
SWAPF |
STATUS,W |
▼▼ |
BCF |
|
STATUS,RP0 |
MOVWFSBUF |
;
▼▼ |
MOVLW |
0ECH |
|
; タイマー再セット |
▼▼ |
MOVWF |
TMR1L |
▼▼ |
MOVLW |
0B1H |
▼▼ |
MOVWF |
TMR1H |
BCFPIR1,TMR1IF |
;
RC1SET
▼▼ |
MOVF |
RC1POS,W |
|
; サーボ1のデータを送る |
▼▼ BTFSC |
STATUS,Z |
|
; データが0なら送らない |
▼▼ GOTO |
RC2SET |
|
|
; 中心値128 1-128-255 |
▼▼ |
BSF |
|
GPIO,GPIO4 |
▼▼ ; |
NOP |
▼▼ |
MOVLW |
0F6H |
MOVWFCOUNT |
INTLP1
▼▼ |
NOP |
▼▼ |
DECFSZ |
COUNT,F |
▼▼ |
GOTO |
INTLP1 |
▼▼ |
MOVF |
RC1POS,W |
MOVWFCOUNT |
INTLP2
▼▼ |
NOP |
▼▼ |
DECFSZ |
COUNT,F |
▼▼ |
GOTO |
INTLP2 |
BCFGPIO,GPIO4 |
RC2SET
▼▼ |
MOVF |
RC2POS,W |
|
; サーボ2のデータを送る |
▼▼ |
BTFSC |
STATUS,Z |
|
; データが0なら送らない |
▼▼ |
GOTO |
RCSETE |
|
|
; 中心値128 1-128-255 |
▼▼ |
BSF |
|
GPIO,GPIO5 |
▼▼ ; |
NOP |
▼▼ |
MOVLW |
0F6H |
MOVWFCOUNT |
INTLP3
▼▼ |
NOP |
▼▼ |
DECFSZ |
COUNT,F |
▼▼ |
GOTO |
INTLP3 |
▼▼ |
MOVF |
RC2POS,W |
MOVWFCOUNT |
INTLP4
▼▼ |
NOP |
▼▼ |
DECFSZ |
COUNT,F |
▼▼ |
GOTO |
INTLP4 |
BCFGPIO,GPIO5 |
RCSETE
;
▼▼ |
SWAPF |
SBUF,W |
|
; レジスタ類復帰 |
▼▼ |
MOVWF |
STATUS |
▼▼ |
SWAPF |
WBUF,F |
▼▼ |
SWAPF |
WBUF,W |
▼▼ |
BSF |
|
INTCON,GIE |
; 割り込み再許可 |
RETFIE |
前回と同様、割り込みルーチンの冒頭にブレークポイントを設定してデバッガを動かせば、正しく20マイクロ秒毎に実行されていることが分かるように、精度が向上していることを確認できる。ただし、実用面においてはRCサーボの信号間隔をここまで厳密にする必要はない
Copyright © ITmedia, Inc. All Rights Reserved.