MPLAB HarmonyでタイマーとUSART(UART)を使う

Use timer and USART with MPLAB Harmony
 
PIC32開発向けのフレームワークであるMPLAB Harmonyでは、ドライバーをフレームワーク設定から導入すれば、少しのコードで処理を実装できます。以前のレジスタ処理によるプログラミングでは個別の紹介をしましたが、Harmonyフレームワークによるプログラミングでは記事の内容が薄くなってしまうので、今回はタイマーとUSART(UARTの上位互換にあたる)の使い方を一度に紹介します。

まずはフレームワークオプションのタブより「Harmony Framework Configration→Drivers→Timer」より「タイマードライバを使用(Use Timer Driver)?」にチェックを入れて、値を設定します。「Driver Implementation」が「STATIC」であれば、タイマーを初期化するルーチンが自動でプログラムに組み込まれます。「DYNAMIC」の場合は、サンプルコードのようにタイマーを初期化するルーチンを自前で用意して、任意の場所で実行する必要があります。
tmrinit.c
DRV_HANDLE timer1 = NULL;
DRV_TMR_INIT    prop;
prop.moduleInit.value = SYS_MODULE_POWER_RUN_FULL;
prop.tmrId            = TMR_ID_1;
prop.clockSource      = DRV_TMR_CLKSOURCE_INTERNAL;
prop.prescale         = TMR_PRESCALE_VALUE_256;
prop.interruptSource  = INT_SOURCE_TIMER_1;
prop.mode             = DRV_TMR_OPERATION_MODE_16_BIT;
prop.asyncWriteEnable = false;

SYS_MODULE_OBJ obj = DRV_TMR_Initialize(DRV_TMR_INDEX_0, (SYS_MODULE_INIT*)&prop );
if(obj != SYS_MODULE_OBJ_INVALID){
  PLIB_TMR_Period16BitSet(TMR_ID_1, 7812);
  timer1 = DRV_TMR_Open(DRV_TMR_INDEX_1, (SYS_MODULE_INIT*)&prop);
}
Timer Periodの値はPRxのレジスターと同義なので、この数値の計算方法は「タイマー1によるLチカ」をご参照ください。複数のタイマーを使用したいのなら「Numer of Timer Driver Instances」の数を増やします。
続いてTimer項目の下にある「USART→USARTドライバを使用(Use USART Driver)?」にチェックを入れます。「Read\Write Model Support」にチェックを入れるとマルチバイトの読み書き(DRV_USART_Read/DRV_USART_Write)の関数が使えるようになります。
ピン設定でU1RX/U1TXの入出力先の指定もお忘れなく。
こちらはプログラム例です。この例では1秒ごと(割り込みは100ms間隔で発生する)にASCII文字列を送信しています。
system_interrupt.c
#include "system/common/sys_common.h"
#include "app.h"
#include "system_definitions.h"

void __ISR(_TIMER_1_VECTOR, ipl4AUTO) IntHandlerDrvTmrInstance0(void)
{
    OnTimer1(); // app.hに「void OnTimer1();」の宣言も記述しておくこと
    
    // 割り込みフラグをリセット
    PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_TIMER_1);
}
app.c
#include "app.h"
#include <stdio.h>

void APP_Initialize ( void )
{
    __XC_UART = 1; //stdioのUART出力先を1に指定するマクロ
    DRV_TMR0_Start(); // タイマーの開始
}

void APP_Tasks ( void )
{
}

int tmr1count = 0;

void OnTimer1()
{
    tmr1count++;
    if(tmr1count >= 10){
        DRV_USART_CLIENT_STATUS state = DRV_USART0_ClientStatus();
        if(state == DRV_USART_CLIENT_STATUS_READY) {
		   // USARTが使用可能なら文字列(ASCII配列)を送る
           DRV_USART0_Write("Hello ", 6);
           printf("world!\n");
        }
        
        tmr1count = 0;
    }
}
2018/10/07