前回は内部のクロックを外部出力するCLKREFモジュールを練習しました。今回は外部からクロックを入力して数えてみます。PIC16F18855はタイマ(カウンタ)が充実、0から6まで7本もあります。今回はそのうちのTIMER0を使って外部クロックをカウント、周期的にタイマ0割り込みを発生させてみます。
※『PIC三昧』PIC関係の記事総目次はこちら
※作業はMicroChip社の統合開発環境 MPLAB X IDEと、その上で走るコンフィギュレーションツールMCC Classic を使用して行っています。ターゲット・マイコンはPIC16F18855です。
PIC16Fのタイマ
PIC16Fは、周辺回路によっては24ビットのタイマを備えているものもありますが、TIMERという本流のお名前を冠する周辺回路については8ビットと16ビットの2種類です。他のマイコンが8ビットタイマを2つ連結すると16ビットになる、とかいろいろオペレーションモードが複雑ななか、PIC16Fは単純明快、
-
- 偶数番号のタイマは8ビット
- 奇数番号のタイマは16ビット
ということみたいです。その例外はTIMER0で、8ビットか16ビットか選択可能と。いろいろ使えるってことかい。
MCC Classicでの設定
いつものようにMCC Classicで設定していきます。Timerを開くと7個のタイマが並んでいるのでTMR0のところの右+記号をクリックしてプロジェクト・リソースに加えます。
Timer0の設定画面が以下に。今回入力した部分に黄色のマーカを重ねてます。デフォルトでは外部クロックの周波数は100kHzだったのですが、ゆったりと実験したい、ということで10kHzに落としてます。ここは「想定値」なのでハードの制御にはかかわりないですが、右側のTimer Periodの計算に関係するのにキチンと入力しておきます。そしてTimer Periodは8ビットフルスケールを使うということで25.6ms設定。そして割り込みをイネーブルです。
端子設定が以下に。Timerへのクロック入力はPortAの4番です(2023年11月16日追記:PA4をクロック入力に使ったのは良くなかったデス。使用したボードでは抵抗を介してポテンショメータに接続されてる端子でした。気づきませなんだ。オオボケ。今回は動きましたが、他の端子に避けた方が無難。)PortBの0番を割り込みハンドラ内で操作して割り込み発生を外部でモニタするつもりです。またPortAの0番は例によってソフトウエアループの吉例Lチカ用です。
実機実験用のコード
MCCが自動生成してくれた main.c ファイル内に書き加えたコードは以下のとおりです。自前のTIMER0用割り込みハンドラ関数を定義しその中でRB0を操作。それとは別にmain()関数内で初期設定後は、吉例Lチカです。
volatile int flag=0; void myTMR0_InterruptHandler(void){ flag = ~flag; if (flag) { RB0 = 1; } else { RB0 = 0; } } void main(void) { SYSTEM_Initialize(); TMR0_SetInterruptHandler(myTMR0_InterruptHandler); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); TMR0_StartTimer(); while (1) { RA0 = 1; __delay_ms(1000); RA0 = 0; __delay_ms(1000); } }
実機で確認
実機実験の様子が以下に。白のワイヤが外部クロック入力で、黄のワイヤが割り込み確認用の出力(オシロ端子との間に330Ω挿入)です。
以下の黄色C1は、入力クロック信号10kHzです。青色C2は割り込みハンドラ内で操作されているRB0端子の立ち上がりを捕まえてます。
上記では青色C2の周波数が見えないので時間範囲を広げたものが以下に。C1入力は予定通りの10kHz、C2の割り込みハンドラから報告されている周波数は19.533Hzです。
TIMER0の割り込み周期は10kHzの256カウントなので25.6ms。周波数としては39.06Hzです。それを割り込みハンドラ内でトグルしているので、外から見えるC2の周波数は半分の 19.53Hz の筈。予定通りよな。