PICマイコン(PIC16F1827)のTMR1割り込みの設定

組み込みエンジニア

こんにちは、ENGかぴです。

マイコンのソフトを開発は割り込み使用します。PIC16F1827において割り込みを使用すると発生時に関数がコールされますが割り込み要因を判別して処理する必要があります。TMR1のオーバーフローを割り込みを使って動作確認します。

割り込みを使用せずにTMR1で使用したい場合は下記記事を参考にしてください。

PICマイコン(PIC16F1827)のタイマー1の使い方

割り込みの考え方と注意事項については下記を参考にしてください。

PICマイコン(PIC12F675)の割り込みの考え方と注意事項

TMR1割り込みの設定

PIC16F1827では割り込み機能を許可する設定と各ペリフェラルの割り込みを許可することで該当する割り込みを使用することができます。

割り込みに使用するレジスタ

TMR1のオーバーフローを割り込みを使用する場合はINTCONレジスタとPIE1レジスタを操作する必要があります。

引用:PIC16F1827のデータシート(INTCONレジスタ)
引用:PIC16F1827のデータシート(INTCONレジスタ)

INTCONレジスタではbit7のGIEビットをセットすると割り込み機能が許可されます。INTCONレジスタに無い割り込みを使用する場合はPEIEビットをセットします。

引用:PIC16F1827のデータシート(PIE1レジスタ)
引用:PIC16F1827のデータシート(PIE1レジスタ)

TMR1に関する割り込みの設定はPIE1レジスタで設定を行います。TMR1のオーバーフロー割り込みを使用するためTMR1IEビットをセットします。

割り込みを使用する場合はINTCONレジスタのGIEビットを必ずセットする必要があります。

TMR1と割り込みの設定

PIC16F1827のTMR1の設定をMCCを使って行います。MCCについては下記記事にまとめています。

MPLAB Code Configurator(MCC)の追加と使い方

最初に共通事項であるSystem Moduleの設定を行います。MPLAB X IDEを起動しMCCのアイコンをクリックしてMCCを有効にします。

System Module設定(MCC)
System Module設定(MCC)

内部クロックを使用するためINTOSCを選択しています。Intemal Clockは4MHz(任意でも良い)を選択しています。クロックを高速にするほど消費電流が増えてしまいます。

TMR1はDevice Resources内のPeripherals欄のTimerを選択しTMR1をクリックして追加します。

TMR1と割り込み設定(MCC)
TMR1と割り込み設定(MCC)

TMR1のオーバーフロー割り込みを使用する場合はEnable Timer Interruptをチェックします。TMR1を200ms毎にオーバーフローさせるためプリスケーラを1:8にしてTimer Periodに200msを入力しています。

Interrupt Moduleでの確認
Interrupt Moduleでの確認

TMR1でEnable Timer Interruptにチェックを入れるとProject Resources内のInterrupt ModuleにTMR1の割り込みベクターが設定されます。この画面では特に設定は不要ですがPeripheralとGlobal Interruptsを許可する必要があることを通知しています。

割り込みの処理を確認

MCCが作成したTMR1及び割り込みについて確認します。割り込みの処理はinterrupt_manager.cにソースコードがあります。

void __interrupt() INTERRUPT_InterruptManager (void)
{
    // interrupt handler
    if(INTCONbits.PEIE == 1)
    {
        if(PIE1bits.TMR1IE == 1 && PIR1bits.TMR1IF == 1)
        {
            TMR1_ISR();
        } 
        else
        {
            //Unhandled Interrupt
        }
    }      
    else
    {
        //Unhandled Interrupt
    }
}

割り込みが発生するとINTERRUPT_InterrutManger()がコールされます。PIC16F1827においては割り込み関数が共通であるため割り込み要因によって処理を分岐させる必要があります。

今回はTMR1オーバーフロー割り込みのみなのでTMR1の割り込み要因を判断するTMR1IEとTMR1IFによる分岐のみとなっています。TMR1がオーバーフローするとTMR1_ISR()をコールします。処理の内容はTMR1_ISR()はtmr1.cで確認できます。

void TMR1_ISR(void)
{
    // Clear the TMR1 interrupt flag
    PIR1bits.TMR1IF = 0;
    TMR1_WriteTimer(timer1ReloadVal);

    if(TMR1_InterruptHandler)
    {
        TMR1_InterruptHandler();
    }
}

割り込み要因の判定を行った後TMRIFをクリアしています。その後TMR1_WritTimer()でタイマ値の初期値を書き込んでいます。TMR1_InterruptHandlerはコールバックする関数を登録しておくことでユーザーが実装した関数を呼び出すことができます。

void TMR1_SetInterruptHandler(void (* InterruptHandler)(void)){
    TMR1_InterruptHandler = InterruptHandler;
}
//ユーザー関数TMR1_INTを登録する場合の例
TMR1_SetInterruptHandler(TMR1_INT);

main.c内のwhile(1)に入る前にコールする関数を指定します。TMR1がオーバーフローした場合にユーザー関数であるTMR1_INT()をコールさせるための実装例を示しています。

TMR1オーバーフロー割り込みを実装

MCCが作成した関数をmain.cに組み込んでTMR1オーバーフロー割り込みの効果を確認します。delay_ms()で数秒間をソフトウェアウェイトを置いている場合でも割り込みによってDOを操作してLEDを点灯/消灯させます。

動作確認用の回路

TMR1の動作確認用の回路
TMR1の動作確認用の回路

LED1とLED2はHアクティブとLアクティブのハード構成にしているためRA7とPB6をHIGHにしても反対の動きになります。SW1を押したときLED3が点灯するようにします。

RB0はウィークプルアップしているため信号レベルが浮くことはありません。SW1を押すとLED3が点灯し押さない場合はLED3が消灯するようにします。ピン設定は以下の通りです。

PIC16F1827のピン設定(MCC)
PIC16F1827のピン設定(MCC)

PB0はINPUTでウィークプルアップ(WPU)設定しています。WPUを有効にするためにはRegistersのnWPUENをenabledにする必要があります。

Easy SetupでWPUにチェックするのみでは有効にならないので注意が必要です。Notificationsにワーニングで通知されます。

初期化とユーザー関数を実装

main.cに割り込みを実装する手順は以下の通りになります。

  1. INTERRUPT_GlobalInterruptEnable()のコメントを外す
  2. INTERRUPT_PeripheralInterruptEnable()のコメントを外す
  3. TMR1_SetInterruptHandler(関数名)に割り込み発生時にコールする関数を指定
  4. ユーザー関数を実装する
#include "mcc_generated_files/mcc.h"

/* 関数プロトタイプ宣言 */
void mainApp(void);     //メイン関数内での処理
void TMR1_INT(void);    //タイマー1割り込みでの処理

void main(void)
{
    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable(); //GIEをセット
    INTERRUPT_PeripheralInterruptEnable(); //PEIEをセット
    TMR1_SetInterruptHandler(TMR1_INT); //TMR1割り込み時にコールする関数を指定

    while (1)
    {
        mainApp();
    }
}
/* main処理  */
void mainApp(void){
   
    if( IO_RB0_GetValue()){ //DIによる判断
        IO_RA3_SetLow(); //RA3をLOW
    }else{
        IO_RA3_SetHigh(); //RA3をHIGH
        __delay_ms(10000); //10秒間ソフトウェアウェイト
    } 
}
/* TMR1オーバーフロー割り込みでの処理  */
void TMR1_INT(void){  
 
    IO_RA7_Toggle(); //RA7の出力を反転
    IO_RB6_Toggle(); //RB6の出力を反転
}

main.cの実装例を示しています。while(1)に入る前に初期化処理を行っています。割り込み許可のコメントを外すと割り込みが有効になります。TMR1オーバーフロー割り込みが発生するとTMR1_INTがコールされるようにしています。

mainApp()内においてSW1を押すことでRB0のDIがLOWになるとRA3を操作することでLED3を点灯させ__delay_ms(10000)によって10秒間ソフトウェアウェイトとなります。

割り込みが有効なのでソフトウェアウェイトの間でも割り込み処理に遷移するためLED1、LED2が点灯/消灯します。

関連リンク

PICマイコンを使ってマイコンのレジスタの設定やMPLAB X IDEのプラグインであるMCCを使用して動作確認したことについてまとめています。

PICマイコン(PIC12F675)で実現できる機能と解説リンクまとめ

PICマイコン(PIC16F1827)で実現できる機能と解説リンクまとめ

Code Camp完全オンラインのプログラミング個人レッスン【無料体験】

最後まで、読んでいただきありがとうございました。

タイトルとURLをコピーしました