PICでもっと遊ぶその2「高精度割り込みとAD変換でサーボを動かす」夏でも楽しい工作教室(1/2 ページ)

» 2005年07月15日 12時54分 公開
[小林哲雄,ITmedia]

(ムダに?)精度アップ!16ビットタイマーを使う

 前回は割り込みの基本ということで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
 
 ORG10
 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
 
 END

前回と同様、割り込みルーチンの冒頭にブレークポイントを設定してデバッガを動かせば、正しく20マイクロ秒毎に実行されていることが分かるように、精度が向上していることを確認できる。ただし、実用面においてはRCサーボの信号間隔をここまで厳密にする必要はない

アナログ入力で(やっと)サーボを動かす

       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

最新トピックスPR

過去記事カレンダー