復活!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
前へ
次へ
ホームページトップへ戻る