2013.12.30
前へ
次へ
ホームページトップへ戻る

復活!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

前へ
次へ
ホームページトップへ戻る