PICマイコン(PIC12F675)のタイマー1の設定と使い方

組み込みエンジニア

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

マイコンのソフト開発を行っているとタイマー機能をよく使用します。タイマーのカウントに初期値をセットすることで任意の時間でタイムアップするタイマを作ることができます。タイマーの設定についての考え方について説明しています。

本記事のタイマー1は以下ではTMR1と表記します。タイマー0の使い方についても同様の考え方で使用することができます。タイマー0(TMR0)を使っている例としては下記記事があります。

PICマイコン(PIC12F675)を使ってブザーを鳴らす方法

PIC12F675を使ってマイコンの動きを勉強するためにPIC12F675の機能でできることについてまとめています。

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

PICマイコン(PIC12F675)の初期化

マイコンのタイマーを使用するにあたっては内部クロックと動作クロックの関係を押さえておく必要があります。PICマイコンにおいてPIC12F675はミドルレンジのマイコンであり動作クロックについて以下の記述があります。

4MHzの内部クロックを使用しているとき4つのオシレータ周期(パルス)で1つの命令となることがデータシートに記述されています。これより通常の実行命令は1usになります。

これをイメージで示すと以下の通りになります。

PIC12F675の動作クロック
PIC12F675の動作クロック

タイマーを使用する際に設定するプリスケーラは、動作クロックを分周する比率を設定して使用します。また、初期値を決めてからタイマーを起動することによって任意のタイマーを作ることができます。

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

PIC12F675のTMR1の説明
PIC12F675のTMR1の説明

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

動作クロックに対してプリスケーラで分周するため1:4を選択すると動作クロック4つ分でカウント値が1つ増えます。カウントが増える時間が4倍になるのでオーバーフローまでの時間が4倍になります。

プリスケーラが1:1の場合について考えてみます。動作クロックが1usでカウントが0から65535まで進むので65536カウント目にオーバーフローします。初期値を設定しない場合はタイマーがオーバーフローするまでの時間は65.536[ms]になります。

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

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

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

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

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

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

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

例のように、50msを基準にして様々なタイマーを作ることができます。50msをベースを200msベースにしてもよいと思います。ただし、ベースタイマーの間隔(分解能)が小さくなるほど割り込みが増えることになるのでマイコンのスペックに合わせて最適な値を決める必要があります。

TMR1の設定の考え方

引用:PIC12F675のデータシート(TIMER1 BLOCK DIAGRAM)
引用:PIC12F675のデータシート(TIMER1 BLOCK DIAGRAM)

PIC12F675のTMR1設定と使用方法について考えていきます。TMR1設定するために必要なレジスタはブロック図で把握することができます。

ブロック図にある信号名についてレジスタの設定を行うことでTMR1が動作します。最終的にSet Flag bit TIMR1IF on Overflowに進めるようにレジスタをセットします。

左下の部分についてはクロックの設定ですが、内部クロックの4MHzを選択しているのでプリスケーラを考えるのみで問題ありません。またPICマイコンをスリープ状態にすることは想定していないことから右下のSLEEP Inputも除外できます。

T1CONレジスタを確認するとブロック図に関係のある設定が記載されています。

引用:PIC12F675のデータシート(T1CONレジスタ)
引用:PIC12F675のデータシート(T1CONレジスタ)

bit0で1にするとTMR1が許可になりスタートします。初期値を設定する前は0にしてストップしておきます。bit1は外部クロックを使用しないので0になります。

bit2はbit1の内容とリンクしておりbit1に0をセットしているので無視されます。bit3は内部クロックを使用しているてCLKOUTピンにより出力するときに使用するものです。使用しないので0をセットします。

bit5-4はプリスケーラです。1:1のまま使用すると動作クロックが1usなので1カウントで1usとなります。1:2では1カウントで2us、1:4で1カウント4us、1:8で8usとなりオーバーフローまでの経過時間が長くなります。

bit6はbit1が0のときは無視されるので0になります。これらの設定を見てみるとT1CONレジスタは0x00になります。

TMR1を実装する

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

GP0とGP2を操作してLED1とLED2が点灯/消灯するようにタイマを実装します。SW1を押すとLED3が点灯するようにします。

TMR1の初期化とLEDの点灯/消灯

//タイマー1初期化
T1CON = 0x00;
TMR1H = 0x3C;//タイマ初期化
TMR1L = 0xB0;//タイマ初期化
TMR1IF = 0;//割り込みクリア 
TMR1ON = 1;//タイマ1ON
//タイマー1初期化 END

TMR1を動作させ50msでタイムアウト(オーバーフロー)させるための初期設定を示しています。プリスケーラは1:1とするため1カウント当たり1usになります。これがオーバーフローするまでに65536回カウントすることになるので初期値を設定しない場合は65.5msのタイマになります。

初期値としてTMR1HとTMR1Lにそれぞれ0x3C/0xB0(2バイトデータで15536)をセットすることでオーバーフローまでのカウント数が50000になるため50msのタイマになります。

オーバーフロー時のフラグであるTMR1IFクリア(0をセット)しておきます。初期値が完了したのでTMR1を動作するためにT1CONレジスタ内のTMR1ONに1をセットするとTMR1が動作開始します。

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

while(1){
    if( TMR1IF == 1){
        TMR1IF = 0;     //オーバーフローフラグをクリア
        TMR1ON = 0;     //タイマ1OFF
        TMR1H = 0x3C;   //タイマ初期化
        TMR1L = 0xB0;   //タイマ初期化
        TMR1ON = 1;     //タイマ1ON
      
        if( ++cnt >= 5){  //5回オーバーフロー後にGPIOを変更
            cnt = 0;
            GPIO0 = ~GPIO0; //ロジックを反転して代入
            GPIO2 = ~GPIO2; //ロジックを反転して代入
        }   
    }
        
    if( GPIO3 == 1){    //GP3がHレベルか
        GPIO5 = 1;  //Hアクティブ(LED3点灯)
    }
    else{
        GPIO5 = 0;
    }
}

無限ループでTMR1がオーバーフローしたことを確認して5回オーバフローしたことを確認してLEDの点灯消灯を切り替えます。

TMR1が起動し50ms経過するとTMR1がオーバーフローしTMR1IFがセットされます。次のTMR1カウントが50msになるようにTMR1HとTMR1Lに初期値を入れます。この時TMR1のカウントが更新されないように一旦停止しています。

変数cntにオーバーフローした回数をカウントし5回以上になった場合は250ms経過したことになるので、GP0とGP2のロジックを反転して代入することでDO制御を行いLEDの点灯/消灯となります。

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

上のソフトには、弱点があります。メイン関数(while(1))の処理が増えて重たくなった時のを考えるとイメージしやすいと思います。

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

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

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

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

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

ソースコード全体

以下のソースコードはコンパイルして動作確認をしております。チェックはしておりますがコメントなど細かな部分で間違っている可能性があります。参考としてお使いいただければと思います。

// CONFIG
#pragma config FOSC = INTRCIO   
#pragma config WDTE = OFF      
#pragma config PWRTE = OFF    
#pragma config MCLRE = OFF    
#pragma config BOREN = OFF    
#pragma config CP = OFF   
#pragma config CPD = OFF  

#include <xc.h>
//--------------定数定義----------------------------
#define _XTAL_FREQ	4000000
//--------------変数定義----------------------------
char    cnt;

void main(void) {
    //各種初期化    
    ADCON0 = 0x00;  //ADC使用しない 
    ANSEL = 0x00;   //アナログモードは使用しない
    CMCON = 0x07;   //コンパレータ使用しない
    TRISIO = 0x08;  //GP3はDI・その他はDO
    GPIO = 0x00;    //ポートの設定 1:High 0:Low
    //タイマー1初期化
    T1CON = 0x00;
    TMR1H = 0x3C;//タイマ初期化
    TMR1L = 0xB0;//タイマ初期化
    TMR1IF = 0;//割り込みクリア 
    TMR1ON = 1;//タイマ1ON
    //タイマー1初期化 END
    cnt = 0;
    //各種初期化 END
    
    while(1){
        if( TMR1IF == 1){
            TMR1IF = 0;     //オーバーフローフラグをクリア
            TMR1ON = 0;     //タイマ1OFF
            TMR1H = 0x3C;   //タイマ初期化
            TMR1L = 0xB0;   //タイマ初期化
            TMR1ON = 1;     //タイマ1ON
      
            if( ++cnt >= 5){  //5回オーバーフロー後にGPIOを変更
                cnt = 0;
                GPIO0 = ~GPIO0; //ロジックを反転して代入
                GPIO2 = ~GPIO2; //ロジックを反転して代入
            }   
        }
        
        if( GPIO3 == 1){    //GP3がHレベルか
            GPIO5 = 1;  //Hアクティブ(LED3点灯)
        }
        else{
            GPIO5 = 0;
        }
    }
}
//---------------------end file----------------------------

関連リンク

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

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

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

テックジム-将来のためにプログラミングを学ぶ

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

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