復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります!
[第533回]
●Timer1
前回からの続きです。
今回はテーブル参照について説明する予定だったのですが、お話の順序として、その前にTimer1の動作について簡単に整理しておきたいと思います。
Timer1の動作については[第529回]で説明をしています。
8ビットレジスタTMR1HとTMR1Lをつないで16ビットレジスタとして使います。
TMR1Hが上位8ビットでTMR1Lが下位8ビットです。
PICはクセのあるICでときどき設計者の意図を量りかねて戸惑ってしまうことがあります。
[第529回]でも書きましたがTimer1はカウントアップ動作をします。
TMR1HとTMR1Lに設定した初期値からスタートしてカウントアップし、FFFFになって次にカウントオーバーして0000になるときに割込みが発生するというのですが、そうするとTMR1H、TMR1Lに設定する値は、必要なカウント値を0000から引いた値を計算して与えなければなりません。
きわめて面倒ですし、プログラム中にしっかりコメントを残しておかないと後からプログラムを読んでも理解できなくなってしまう恐れがあります。
通常のTimer1のカウントアップモードには大きな欠点があります。
初期値を設定したTMR1H、TMR1Lレジスタそのものがカウントアップされるために、0000になって割込みが発生したときに、一旦カウントを停止させて初期値をリロードしなければならず、そこでどうしてもわずかなタイムラグが発生してしまいます。
たとえばZ8S180の内蔵タイマーモジュールでは初期値はリロードレジスタに入れられていて、カウントダウンして0000になったとき、自動的にカウンタにリロードレジスタから初期値が再ロードされるようになっています。
そうあるべきでありましょう。
実はPIC16F887の場合Timer1にはオプション機能があります。
ECCPモジュールを使ったcompareモードを利用すると、カウントアップモードですけれどZ8S180の場合のカウントダウン&リロードと同じような働きをさせることができます。
その場合CCPRxH、CCPRxLレジスタに目的値を入れておき、0000からカウントスタートした後TMR1H、TMR1LとCCPRxH、CCPRxLの値が一致すると割込みが発生し、同時にTMR1H、TMR1Lが0000にクリアされます。
[出典]Microchip Technology Inc. PIC16F882〜887Data Sheet
しかし、そのあたりのことに深入りをしますと、また抜け出せなくなってしまいますから、それについてはこの辺までとしておきます。
とにかくそういうことですので、Timer1を使うためには初期値をTMR1H、TMR1Lに設定しなければなりません。
サンプルプログラムでは、その初期値の設定はTimer1割込みプログラムで行なっています。
そこのところは前回説明をしましたが、下に再掲いたします。
movlw 1 xorwf PORTE,f;pulse out bcf T1CON,0;stop T1 movf t1Hdata,w movwf TMR1H movf t1Ldata,w movwf TMR1L movlw 1 movwf T1CON;start T1 |
割込みプログラムでは、t1Hdataとt1Ldataを読んでその値をそれぞれTMR1HとTMR1Lに入れています。
そしてそのt1Hdataとt1Ldataには、メインプログラムでテーブル参照を使って値を入れています。
下のリストはメインプログラムの中心部分です(プログラム全体のリストは[第516回]にあります)。
loop clrf cntr clrf udmk loop1 movlw 0a;=10 movwf limit loop2 bsf PORTE,2 movf cntr,w call Htable movwf t1Hdata movf cntr,w call Ltable movwf t1Ldata call t25ms bcf PORTE,2 call t25ms btfsc udmk,0 goto downcount incf cntr,f decfsz limit,f goto loop2 ;set downcount incf udmk,f decf cntr,f goto loop1 downcount decf cntr,f decfsz limit,f goto loop2 goto loop ; |
上のリストの中の、
movf cntr,w
call Htable
movwf t1Hdata
movf cntr,w
call Ltable
movwf t1Ldata
というところです。
cntrがテーブル参照のキーに使われています。
cntrは0から始まって順に+1されていき9までの値がセットされます。
9までいくとまた0に戻って繰り返します。
その間にメインプログラムはTimer1の動きとは別個にPORTEのビット2から20Hzのパルス(H=25ms、L=25ms)を出力します。
この25msは命令の実行時間を利用したソフトウェアタイマーによって作り出しています。
; ;timer ; t1ms movlw 0fa;=250 movwf tcntr0 t1mslp clrwdt;1 decfsz tcntr0,f;1 goto t1mslp;2 return ; t25ms movlw 19;=25 movwf tcntr1 t25mslp call t1ms decfsz tcntr1,f goto t25mslp return ; |
サンプルプログラムはCPUクロック4MHzを内蔵クロックモジュールによって得ています。
各命令はその1/4のクロックをもとにして実行されます。
ですから1命令クロックは1MHzになります。
PICの大抵の命令は1命令クロックですがgotoなどの命令は2命令クロックです。
t1mslpは一回のループが4クロックですから4μSで一回実行されます。
tcntr0に250をセットして、t1mslpを250回ループすると、実行時間は1mSになります。
厳密に言うと、tcntr0に値をセットするところや、return命令も実行時間に含まれますから、正確な1mSではありませんが、このサンプルプログラムのような用例の場合、実用上はそれで十分です(内蔵クロックモジュールによるCPUクロックそのものが水晶発振のような正確なクロックではありません)。
今回はテーブル参照について説明をする予定だったのですが、そこまでいけませんでした。
次回はなんとか説明にこぎつけると思います。
ワンボードマイコンでCP/Mを![第533回]
2013.12.30upload
前へ
次へ
ホームページトップへ戻る