PIC−USBIO using BASIC
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
USBインターフェースを内蔵したPICを使ってWindowsパソコンで外部回路を制御するための各種I/O基板の製作記事です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
[第93回]
●PICUSBIO−03(42)Timer1(24)COMPAREモード(5)テストプログラム(4)
前回はCOMPAREモードの最後のテスト(CCP1CONのbit3−bit0=1011)で割り込み条件が成立したときにTimer1がリセットされるはずなのにそれよりも1カウント多くカウントしてしまうらしいという現象がおきました。
それは本来そういう仕組みになっているのかそれとも何かほかの理由でそういう現象がおきるのか、そこのところを確認してみたいと思います。
まずは事実を確認するためにプログラムを実行しているときのTimer1の値を読み込んでそれをPRINTしてみることにしました。
66行を追加しました。
これでTMR1Lの値が画面に表示されます。
プログラムを実行しました。
TMR1Lの値が連続して表示されるようになりました。
カウントアップされるまでの表示回数を数えてみました。
最初の0の期間は入力パルスの途中からカウントすることになりますから少ない回数でカウントアップしていますがそのほかのカウント値では46回か47回でカウントアップしています。
今回のテストの目的とは関係ありませんが試しに計算をしてみました。
入力パルスの周期は約700msecですから700/46≒15(msec)です。
今回のプログラムで60行から90行までのループが1回実行されるのに約15msecかかっています。
その間にUSB(HID形式)で何回かPICと通信していますからそのくらいの時間はかかってしまいます。
それはそれとして、上の結果を見ますとやっぱりTimer1は10までしっかりカウントしています。
Timer1が10までカウントして、そのあと(Special Event Triggerによって)リセットされて0に戻るまでの表示回数もほかのカウント値のときと同じ46回です。
あれっ?
カウント10ですぐにリセットされていませんね。
表示回数から見て前回のオシロでの観測結果が正しいことがわかります。
ドキュメントではCCPR1の値とTimer1の値が一致するとSpecial Event Triggerによって「そのときに」Timer1がリセットされる、と読めるのですが、前回と今回のテストではTimer1の値はその次の1カウントをしたタイミングでリセットされるように見えます。
どういうことなのでしょう。
そこのところをもう少し追求してみました。
Special Event Triggerがどのタイミングで実行されるのかを確かめることはできませんが、その「引き金」になるはずのCCP1割り込みはCCP1IFが1になることで確認することができるはずです。
そこでプログラムを下のように変更してみました。
75行を追加しました。
CCP1IF(PIR1のbit2)が1になったらそこで”break”と表示してTMR1LとPIR1の値を表示したあとstopコマンドでプログラムを途中終了します。
何度も書いていることですがBASICインタプリタだからこそ、こういうことがこんなにも簡単にできてしまうのです。
超便利です。
プログラムを実行しました。
おお。
CCP1IFはTMR1Lが10になったときに1になっているようです。
プログラムはそこで実行を中止しましたがPICの側ではカウントはまだ続いています。
ダイレクトモードでprint文を実行してその時点でのTMR1Lの値を表示させてみたところ6が表示されました。
おそらくTimer1が10をカウントしたあと次の入力パルスの立ち上がり時点でクリアされてカウントを続けているのだということが推測できます。
本当にその推測通りなのかどうか、そこのところをもう少ししつこく追及してみます。
さらにプログラムを変更しました。
76行と77行を追加しました。
さきほどのプログラムでは”break”とTMR1Lの値とPIR1の値を表示してそこでプログラムを終了しました。
今回はそのあと続けてTMR1Lの値の表示を続けます。
TMR1Lの値が10ではなくなったらそこで実行を中止します。
今回の追加によって80行と90行は実行されなくなります。
PORTCの出力は行なわれなくなりますが今回のプログラム変更の目的としてはPORTCの出力を確認する必要はありませんからそういうことで構いませんでしょう。
プログラムを実行しました。
上で推測しましたようにPIR1=4(CCP1IF=1)になったあともTimer1はカウント値を保持したままカウント状態を維持していて(おそらくは)次のパルスの入力によって0クリアされるらしいことが見て取れます。
うむむ。
まだ推測の域をでませんねえ。
それでは「次のパルス」が入力されなかったらどうなるでしょうか?
それを簡単に確かめることはちょっと難しいのですがとにかくやってみました。
あらかじめ左側のコマンドプロンプトで
picout INTCON,0
まで入力してその位置にカーソルを置いたままにしておいて右側のプログラムを実行しました。
右側のプログラムの実行を開始したあと左側のコマンドプロンプトに戻っていつでも[Enter]が押せるようにしてそこでスタンバイしました。
そして右側のコマンドプロンプトでbreakと表示された直後に[Enter]キーを押しました。
なんともアナログですなあ(オジイはそんなもんです)。
予測していた通りTimer1の値は10のままクリアされずそのままの表示が続きました。
これでTimer1が0クリアされるためには次のパルスが入力される必要があることがはっきりしました。
なぜこういう仕組みになっているのか本当のところはわからないままですが、実用上はTimer1のカウント上限値をCCPR1にセットするときにその値−1をセットするようにすることで正しく対処できると思います。
とそこまで書いてきて、そういうことかもしれない、とひとつの解釈を思いつきました。
そういうことではないかも知れませんが、納得がいくひとつの解釈です。
下の上側の図がその解釈を図で示したものです。
それに対して下側の図は私が今まで考えていた解釈を図にしたものです。
両方ともカウント0の期間があってそこからカウントが始まります。
上側ではカウント10の期間の次にカウント0の期間があります。
下側ではカウント10は一瞬で終わりすぐにカウント0の期間になります。
まあ考え方ですけれど、確かにこうして図にしてみると上側の図のほうが無理が無いようにも思えます。
結果として上側では11カウントで繰り返すのに対して下側では10カウントで繰り返すことになります。
PICのCOMPAREモードでは上側の図の動作になっています。
PIC−USBIO using BASIC[第93回]
2022.11.8upload
前へ
次へ
ホームページトップへ戻る