PICでmillis()関数の様に、
プログラム起動時からの時間カウントを行う

〔標準関数の使い方とサブルーチンサンプル集に戻る〕


Arduinoには標準関数でmillis()が有ります、これは、 プログラムの実行を開始した時から現在までの時間をミリ秒単位で返す関数ですが、 PICでこれと似た様な事をさせる方法を記述しておきます。

それはPICのタイマー0を利用して1ms毎に割り込みを発生させカウントするだけです。
なのでぇ、時刻は少しずつズレて行きます、時計代わりは無理ですよ、RTCを使って下さい。

タイマー0の設定として、
PICの周波数は8MHz 、プリスケーラ設定値 1:8 、カウントは250までカウントさせると1msです。
ワンカウントの時間は、
((1/システムクロック周波数) x 4) x プリスケーラ設定値
なので ((1 / 8MHz) x 4) x 8 = 4μs だから 250回カウントですね。

タイマー0の使い方は12F675での記述ですが他のPICでも同じと思えるのでこちらを参考にして下さい。

(これ以下のプログラムはMPLAB(R) XC8 C Compile V1.00コンパイラ仕様にて記述しています)
[時間カウント関数:millis]
(以下をコピー&ペーストしてファイル名millis.cで保存しましょう)
----millis.c-----------------------------------------------------
// プログラム起動時からの時間カウントを行うライブラリ
// "unsigned long"宣言です、4,294,967,295ms(2の32乗 - 1)までカウントしたら0に戻り再カウント。
#include <xc.h>
#include "millis.h"

// タイマー0割込みの処理(1ms毎に割込み発生)
void millisInter( void )
{
     if (TMR0IF == 1) {       // タイマー0の割込み発生か?
          TMR0   = T0COUT ;   // タイマー0の初期化
          TMR0IF = 0 ;        // タイマー0割込フラグをリセット
          milliCount++ ;      // 割込み発生の回数をカウントする
     }
}
// Timer0を使用する為の初期化処理(Foscは8MHzで計算)
void millisStart( void )
{
     milliCount = 0 ;         // 割込み発生の回数カウンターを0にする
     OPTION_REG = 0b00000010 ;// 内部クロック(Fosc/4)でTIMER0を使用、プリスケーラカウント値 1:8
     TMR0   = T0COUT ;        // タイマー0の初期化(250カウントさせる)
     TMR0IF = 0 ;             // タイマー0割込フラグ(T0IF)を0にする
     TMR0IE = 1 ;             // タイマー0割込み(T0IE)を許可する
     GIE    = 1 ;             // 全割込み処理を許可する
}
-----------------------------------------------------------------
(以下をコピー&ペーストしてファイル名millis.hで保存しましょう)
----millis.h-----------------------------------------------------
// プログラム起動時からの時間カウントを行うライブラリのインクルードファイル
#ifndef _MILLIS_H_
#define _MILLIS_H_

#define T0COUT 6              // タイマー0用カウントの初期値(256 - 250 = 6)

unsigned long milliCount ;    // タイマー0の割り込みカウンタ(1ms毎に割込み発生)

void millisInter( void ) ;
void millisStart( void ) ;

#endif
-----------------------------------------------------------------
下記サンプルプログラムはPIC16F1827での使用例です。
RB4(10番ピン)に接続したLEDを約1秒毎に点滅させるサンプルです。
尚、LEDの接続方法はこちらを参考にして下さい。
-----------------------------------------------------------------
#include <xc.h>
#include "millis.h"

// コンフィギュレーション1の設定
// CLKOUTピンをRA6ピンで使用する(CLKOUTEN_OFF):内部クロックを使用する(FOSC_INTOSC)
// 外部クロック監視しない(FCMEN_OFF):外部・内部クロックの切替えでの起動はなし(IESO_OFF)
// 電源電圧降下常時監視機能ON(BOREN_ON):電源ONから64ms後にプログラムを開始する(PWRTEN_ON)
// ウオッチドッグタイマー無し(WDTE_OFF):
// 外部リセット信号は使用せずにデジタル入力(RA5)ピンとする(MCLRE_OFF)
// プログラムメモリーを保護しない(CP_OFF):データメモリーを保護しない(CPD_OFF)
__CONFIG(CLKOUTEN_OFF & FOSC_INTOSC & FCMEN_OFF & IESO_OFF & BOREN_ON &
         PWRTE_ON & WDTE_OFF & MCLRE_OFF & CP_OFF & CPD_OFF) ;
// コンフィギュレーション2の設定
// 動作クロックを32MHzでは動作させない(PLLEN_OFF)
// スタックがオーバフローやアンダーフローしたらリセットをする(STVREN_ON)
// 低電圧プログラミング機能使用しない(LVP_OFF)
// Flashメモリーを保護しない(WRT_OFF):電源電圧降下常時監視電圧(2.5V)設定(BORV_HI)
__CONFIG(PLLEN_OFF & STVREN_ON & WRT_OFF & BORV_HI & LVP_OFF) ;

// 割込みの処理(この割込み処理は必ず記述する事)
void interrupt InterTimer( void )
{
     millisInter() ;          // Timer0割込み処理(millis関数用)
}
// メインの処理
void main()
{
     int  f ;
     unsigned long x ;

     OSCCON = 0b01110010 ;    // 内部クロックは8MHzとする
     ANSELA = 0b00000000 ;    // AN0-AN4は使用しない全てデジタルI/Oとする
     ANSELB = 0b00000000 ;    // AN5-AN11は使用しない全てデジタルI/Oとする
     TRISA  = 0b00000000 ;    // ピン(RA)は全て出力に割当てる(RA5は入力のみとなる)
     TRISB  = 0b00000000 ;    // ピン(RB)は全て出力に割当てる
     PORTA  = 0b00000000 ;    // RA出力ピンの初期化(全てLOWにする)
     PORTB  = 0b00000000 ;    // RB出力ピンの初期化(全てLOWにする)

     f = 0 ;
     millisStart() ;          // 時間カウント開始

     x = milliCount ;
     while(1) {
          // 現在の時刻と前に読んだ時刻を比較する
          if ( (milliCount-x) >= 1000 ) { // 1秒以上たったか?
               if (f == 0) f = 1 ;        // ON
               else        f = 0 ;        // OFF
               RB4 = f ;                  // RB4のLEDに出力する
               x = milliCount ;           // 時刻を読直す
          }
     }
}
-----------------------------------------------------------------
現在の時間を知るには上サンプルの様にmilliCount変数を参照するだけです。
約50日間でオーバーフローし、ゼロに戻ります、でぇ、また再カウントするだけです。
また、このサンプルはオーバーフローを考慮していないのでオーバーフロー時はうまく動作しないでしょう。 50日後の話だけどね!




【きむ茶工房ガレージハウス】
Copyright (C) 2006-2012 Shigehiro Kimura All Rights Reserved.