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

組み込みエンジニア

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

PICマイコンにはタイマー機能があり16ビットタイマとしてTMR1があります。TMR1の初期値を調整することで任意のタイミングでオーバーフローするタイマを作ることができます。MCCを使用してTMR1を実装する方法をまとめています。

タイマー1(TMR1)の考え方

PICマイコン(8ビットマイコン)のTMR1の使い方について説明します。TMR1は初期値からスタートして16ビットの最大値である0xFFFF(65535)を超えるとオーバーフローして時間経過を通知します。

PIC16F1827のTMR1の説明
PIC16F1827のTMR1の説明

動作クロックに対してTMR1の動作を管理するClock Sourceを選択します。内部のクロック使用するためFOSCもしくはFOSC/4を選択します。

TMR1のプリスケーラー(Prescaler)はClock Sourceが生成したパルスを分周します。1:2を選択するとClock Sourceの2パルス分でTMR1のカウントを+1します。

Clock SourceをFOSC/4、プリスケーラが1:2の場合について考えてみます。TMR1のカウントが+1されるタイミングがClock Sourceとプリスケーラによって決まるため1カウント当たり2us経過します。

初期値を設定しない場合は65535カウントを超えるとオーバーフローするため132.072msになります。任意のタイミングでオーバーフローさせるためには初期値を設定します。

例として100[ms]でオーバーフローするタイマーを考えてみます。オーバーフローするまでのカウント値は0xFFFFで変わらないため初期値を変更してオーバーフローまでの時間を作ることになります。

50msでオーバーフローするタイマの説明図

初期値は簡単な対比で計算できます。カウント1つで2usなので100ms(100000us)を作るためのカウント値は2:100000 = 1 : Xになります。

Xは50000になるので初期値は65536から50000を引いた15536になります。

この100msをベースタイマーとして考えて各種のタイマーを構成の例を上げます。

例1)200msタイマで管理したい場合
100msのタイマーのオーバーフローが2回発生すると200ms経過したことになります。

例2)1000msタイマーで管理した場合
100msのタイマーのオーバーフローが10回発生すると1000ms経過したことになります。

TMR1のオーバーフロー割り込みを使用している場合ベースタイマーの間隔(分解能)が小さくなるほど割り込みが増えるためマイコンのスペックに合わせて最適な値を決める必要があります。

TMR1の設定を実装する

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

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

TMR1をMCCで設定する

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

TMR1の設定(MCC)
TMR1の設定(MCC)

Timer Clock内でクロックに関する設定を行います。Clock Sourceは内部クロックを使用しているためFOSC(FOSC/4)を指定します。PrescalerはClock Sourceに対してTMR1のカウントアップする分周比を指定します。

Prescaler下のチェックはFOSC(FOSC/4)を選択している場合レジスタ設定に反映されますが仕様上無視されます。

Timer PeriodはTMR1がオーバーフローするタイミングを設定します。指定の仕方は2通りありますがmsで指定する方が分かりやすいためお勧めです。

例では初期値カウント値を計算して②に指定してオーバーフローまでのタイミングを指定しています。②に16進数で指定するとCalculated Periodが100msになっています。

動作確認用の回路

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にワーニングで通知されます。

TMR1を使ったタイマ管理

TMR1を使用してLEDを点灯/消灯させるためにタイマ管理を行います。MCCが生成したmain.cのwhile(1)部分にmainApp()関数を追加しています。

void mainApp(void){
    
    if(TMR1_HasOverflowOccured() ){
        PIR1bits.TMR1IF = 0; //TMR1オーバーフロ時にセットされるクリアが必要
        TMR1_StopTimer(); //タイマを一時停止
        TMR1_Reload(); //タイマの初期値を設定する
        TMR1_StartTimer(); //タイマの動作開始
            
        if( ++cnt >= 2 ){
            cnt = 0;
            IO_RA7_Toggle();
            IO_RB6_Toggle();
        }
    }
        
    if( IO_RB0_GetValue()){
        IO_RA3_SetLow();
    }else{
        IO_RA3_SetHigh();
    } 
}

MCCが生成した関数を使用してTMR1に関する設定をしています。TMR1に関する処理はtmr1.cで確認できます。以下に使用した関数についてまとめています。

関数内容
TMR1_HasOverflowOccured()TMR1IFの状態を確認する。TMR1がオーバーフローするとTMR1IFがセットさせる。TMR1IFをユーザーでクリアする必要がある。
TMR1_StopTimer()TMR1のカウントを停止する。
TMR1_Reload()TMR1のカウント値にTMR1_Initialize()で設定した初期値をセットする。
TMR1_StartTimer()TMR1のカウントをスタートする。
TMR1関係で使用した関数(MCCが生成)

TMR1がオーバーフローしてタイムアップすると初期値をセットしなおし再びTMR1のカウントをスタートします。

TMR1IFフラグは1のままクリアしない場合、動作が完了しているとみなして次回以降の動作が一時的に待機になるのでTMR1IFフラグがセットされていることを確認した後はクリアする必要があります。

オーバーフローまでに100ms経過し、2回オーバーフローしたときにRA7とRA6のDOの出力を反転させているため200ms毎にLEDが点灯/消灯します。

英会話を教師の質で選ぶなら【QQEnglish】の無料体験レッスンの申込

メイン関数内でオーバーフローの確認を行う問題点

メイン関数(while(1))の処理が増えて重たくなった時に問題となる場合があります。処理が少ない間はmain関数を1周する時間は短いため問題になりませんが、ソフトを追加していくにつれてメイン関数(while(1))の1周当たりの時間が長くなってしまいます。

タイマーのタイミングが動作に影響を与えるようなシステムではメイン関数でのタイマーのオーバーフローの確認は採用しないほうが良いと言えます。

タイマーのタイミングの精度を求めたいのなら割り込みが処理を使用することを検討したほうが良いでしょう。

割り込み内でLEDを点灯消灯させてもよいですが割り込みの頻度が多くなればメイン関数に戻りにくくなるなどバランスをとった使い方をする必要があります。割り込みの考え方と注意事項については下記記事を参考にしてください。

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

関連リンク

関連リンクではPIC16F1827を使ってマイコンの基本動作を確認するために動作確認したことについてまとめています。

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

テックジム|ゼロからはじめるPython入門講座の申込

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

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