はじめに
前回の記事の続編です。前回は _CP0_GET_COUNT() という関数を使って CP0 レジスタの内容を数えて delay を作成しながら、MPLAB X IDE 6.20 上で PIC32MX230F064B で LEDを点滅させるということをしました。
今回は CP0 ではなく、タイマー割り込みを使った LED点滅を試みます。使用するのは TIMER2 としました。
評価回路と使ったソフトウェア
ハードウェア(評価回路)は前回と全く同じです。
ソフトウェアのインストールなども前回の記事に書いてあるので合わせて参照してください。
タイマーについて
次のドキュメントを参考にしてください。
LED点滅周期について
先に言っておきますが、今回は、1秒ごとに点滅を繰り返すのではなく0.5秒ごとに点滅を繰り返すように設定します。内部クロック(PBCLK)の周波数、分周設定およびタイマーカウンタレジスタが 16bit までというのが制限となって、オーバーフローにより1秒分のカウントができませんでした...(泣)。内部クロック(PBCLK)をさらに下げれば、1秒ごとの点滅も実現できますので、やってみてください。
MPLAB X IDE の作業手順
- ウィザードでプロジェクトを作成する
- プロジェクトプロパティの設定
上記は前回と手順は同じで、プロジェクト名は新しい名前にしてください。手順は前回の記事を参照してください。
MCC の設定
割り込み処理とタイマーを使用するので、MCC (Code Configurator) は前回と少し異なります。
タイマーは PBCLK をクロック源とした構成にします。前回は PBCLK は設定していませんでした。
クロック構成の設定
クロックの構成(下半分) は下図のようにします。緑の枠部分が、新しい設定です。分周器の分周比率も設定します。PBCLKは 24MHzとします。よって SYSCLK (48MHz) を 2分周 (DIV_2) すればいいですね。今回の実装ではこの PBCLK をタイマー2 の源泉にします。
ピン設定
前回と同じく RB15 のみ GPIO の出力設定にします。
タイマー2 機能の追加
これは新規作業です。タイマー2 の設定と割り込みでも使う宣言を MCC 上で設定します。
- Device Resource から TMR2 (=タイマー2) の機能を Project Graph に追加します。具体的には、Libraries⇒Harmony⇒Peripherals⇒TMR⇒TMR2 と降りていき、緑の「+」ボタンをクリックすることで、それを Project Graph に登録します。
- Project Graph の TMR2 をクリックすると右に タイマー2 に関する設定項目が表示されます。下図のように設定します。
- Enable Interrupts? : タイマー2のカウンターが規定値になったら割り込みを発生させるので、"チェック" にします。
- Select Prescaler : タイマー2のカウンターは PBCLK を源泉にしていますが、カウンターに入れる前に 1/256 にします。PBCLK が 256発 入ったら タイマー2のカウンタが 1増える、ということです。
- 32-bit Timer Mode ~ : タイマー2 は 16bit カウンタですが、タイマー3のカウンタと連結することで 32bit のカウンタにすることができます。今回は、連結しないので separate 16bit timer にします。
- Select Timer Clock Source : PBCLKを源泉にするので Internal Peripheral clock にします。
- Time : 500 millisecond (=0.5秒) にします。割り込みがかかる間隔です。仮に 1秒に設定すると、Period Register の値が 65535 を超えてしまいます。
- Stop in Idle Mode bit: idle mode でも割り込みは発生し続けたいので "Continue ~" にします。
割り込み設定の確認
Project Graph の plugin: で Interrupt Configuration を選択すると、割り込み設定表が表示されます。
先ほど、タイマー2を割り込みで使う、と TMR2の設定でチェックを入れたので、割り込み表でも USE にチェックが入っています。割り込み優先順位をここで設定できますが、今回は他の割り込みは使っていないので、優先順位=1 のままとします。
MCCの設定をもとにコードを生成
以上で設定は終わりましたので、コード生成します。作業は前回と同じで [Generate] ボタンを押します。
MCCで設定を変えたら都度 コード生成しなおして設定を C++ コードに反映させるようにしてください。この時、今まで書いていたコード部分は原則残りますので、心配はいらないです。
メインプログラム
"Project" タブのSource Files -> main.c だけでなく、前回よりも多くのソースファイルが生成されています。とくに plib_tmr2.c の内容は一度目を通しておいてください。タイマー設定、割り込みに関する必要な関数を用意してくれているので、それを使って main.c にインプリメントしていくのが MPLAB/MCC/Harmony のお作法なんだと思います。
前回同様に main.c に Lチカに必要なコードを書き足していきます。前回のコードが残っていると思いますが、消してください。
ちなみに、出自が不明な関数名を選択して、右クリックメニューで Navigate を選択すると、ソースコードやヘッダファイルの定義場所を示してくれます。
main.c
main.c には下のように、toggle_led() という RB15ピンの出力を反転する関数と、タイマー2の割り込みがかかると、呼び出す関数を設定する TMR2_CallbackRegister(~) と、タイマー2 の動作を開始する TMR2_Start() を書き足します。
static void toggle_led ( uint32_t status )
{
PORTBbits.RB15 = ! PORTBbits.RB15;
}
int main ( void )
{
/* Initialize all modules */
SYS_Initialize ( NULL );
TMR2_CallbackRegister( (TMR_CALLBACK) toggle_led, (uintptr_t) NULL );
TMR2_Start();
while ( true )
{
/* Maintain state machines of all polled MPLAB Harmony modules. */
SYS_Tasks ( );
}
/* Execution should not come here during normal operation */
return ( EXIT_FAILURE );
}
whileループ内に書き足した この2つの関数は、MCC/Harmony によって用意された plib_tmr2.c というファイル内で定義されています。TMR2_CallbackRegister () は、割り込みがかかった時に呼び出す関数 (= toggle_led ) と それに引き渡す内容 (context) をあらかじめ登録しておくイメージになります。
ちなみに、SYS_Tasks() は相変わらず、空っぽです。
PIC32MX へ書き込み
手順は前回と同じです。0.5秒間隔で、点灯・消灯を繰り返すのが確認できました。
動作としては、通常は while ループ内をぐるぐる回っているだけなのですが、タイマー2のカウンタが規定値になると割り込みがかかり、TMR2_CallbackRegister() であらかじめ登録した関数 (=toggle_led()) を実行して、LED点滅をするという動きになっています。
まとめ
今回は、MPLAB X IDE 6.20 上で タイマー設定・割り込みの作業を習得すべく、コードを書き直してLED点滅をさせました。 MCC や Harmony の生成コードがほとんどない状態なので、見通しよく PIC32MX の書き込みまで至ることができました。