MPLAB X IDE 6.20 を使って PIC32MX230F064B で Lチカしてみた (タイマー割り込み)

# はじめに
前回の記事の続編です。前回は _CP0_GET_COUNT() という関数を使って CP0 レジスタの内容を数えて delay を作成しながら、MPLAB X IDE 6.20 上で PIC32MX230F064B で LEDを点滅させるということをしました。

* [(前回の記事): MPLAB X IDE 6.20 を使って PIC32MX230F064B で Lチカしてみた](https://qiita.com/cvp-swat/items/5562d1aab1b0e6a6f994)

今回は CP0 ではなく、タイマー割り込みを使った LED点滅を試みます。使用するのは TIMER2 としました。

## 評価回路と使ったソフトウェア
ハードウェア(評価回路)は前回と全く同じです。
ソフトウェアのインストールなども前回の記事に書いてあるので合わせて参照してください。

![sch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513938/5411d3c6-4e82-9193-e211-44dfae8da569.png)

## タイマーについて
次のドキュメントを参考にしてください。

## 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 の源泉にします。

![clk1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513938/593a9dc1-bb12-72dd-73d3-7663e3e1fa76.png)

### ピン設定
前回と同じく RB15 のみ GPIO の出力設定にします。

### タイマー2 機能の追加
これは新規作業です。タイマー2　の設定と割り込みでも使う宣言を MCC 上で設定します。
1. Device Resource から TMR2 (=タイマー2) の機能を Project Graph に追加します。具体的には、Libraries⇒Harmony⇒Peripherals⇒TMR⇒TMR2 と降りていき、緑の「＋」ボタンをクリックすることで、それを Project Graph に登録します。 
2. Project Graph の TMR2 をクリックすると右に タイマー2 に関する設定項目が表示されます。下図のように設定します。

![int1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513938/03fe2e34-bcbd-1173-136c-2100fd7e7362.png)

* Enable Interrupts? : タイマー２のカウンターが規定値になったら割り込みを発生させるので、"チェック" にします。
* Select Prescaler : タイマー２のカウンターは PBCLK を源泉にしていますが、カウンターに入れる前に 1/256 にします。PBCLK が 256発 入ったら タイマー2のカウンタが 1増える、ということです。
* 32-bit Timer Mode ～ : タイマー2 は 16bit カウンタですが、タイマー３のカウンタと連結することで 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 を選択すると、割り込み設定表が表示されます。
![int3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513938/24ccc207-be56-1f95-5f68-a497d91f505f.png)

先ほど、タイマー２を割り込みで使う、と TMR2の設定でチェックを入れたので、割り込み表でも USE にチェックが入っています。割り込み優先順位をここで設定できますが、今回は他の割り込みは使っていないので、優先順位=1 のままとします。
![int2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513938/e8dc1c27-b72f-637f-250b-f0ba11a609b6.png)

### MCCの設定をもとにコードを生成
以上で設定は終わりましたので、コード生成します。作業は前回と同じで [Generate] ボタンを押します。

![set7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513938/6cde19a6-c2b5-42c4-b1f8-b46bdfdf212b.png)

MCCで設定を変えたら都度 コード生成しなおして設定を C++ コードに反映させるようにしてください。この時、今まで書いていたコード部分は原則残りますので、心配はいらないです。

# メインプログラム
"Project" タブのSource Files -> main.c だけでなく、前回よりも多くのソースファイルが生成されています。とくに plib_tmr2.c の内容は一度目を通しておいてください。タイマー設定、割り込みに関する必要な関数を用意してくれているので、それを使って main.c にインプリメントしていくのが MPLAB/MCC/Harmony のお作法なんだと思います。

![int4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513938/b8b662d4-0f0b-7ceb-17f6-d87094ab966e.png)

前回同様に main.c に Lチカに必要なコードを書き足していきます。前回のコードが残っていると思いますが、消してください。

ちなみに、出自が不明な関数名を選択して、右クリックメニューで Navigate を選択すると、ソースコードやヘッダファイルの定義場所を示してくれます。

### main.c

main.c には下のように、toggle_led() という RB15ピンの出力を反転する関数と、タイマー2の割り込みがかかると、呼び出す関数を設定する TMR2_CallbackRegister(～) と、タイマー2 の動作を開始する TMR2_Start() を書き足します。

```main.c
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 の書き込みまで至ることができました。