タイマー割込みを使ってLEDを点滅させます
〔PICの動かせ方入門に戻る〕
配線したLEDを、PICのタイマー機能(Timer1/2/3/4/5)を使って約1秒毎に点滅させます。
Timer1/2/3/4/5は16ビットタイマーモジュールですが、
Timer2とTimer3、Timer4とTimer5、を組み合わせれば32ビットタイマーとして動作します。
Timer1〜Timer5共に操作方法は同じで、"PRx"のタイマ周期レジスタに設定した値までカウントしたら
割り込み発生です。
《配線図》
左が実態配線図です、電源は3.3V。
アナログ専用電圧AVDD(28番)/AVSS(27番)は
VDD(13番)/VSS(8・19番)と同じ電源に接続している
内蔵のレギュレータ用にVCAP端子(20番)に、10uFの
コンデンサーを取付けVSSに落とす必要が有ります。
(10uF 6.3V以上のタンタルコンデンサーか、
10V以上のセラミックコンデンサと書いて有る)
1番ピンはMCLR専用なのでリセット回路を取付けないのなら1K-10KΩ抵抗でVDDに接続します。
後はLEDを点滅させるので、RB4(11
番)端子に抵抗470Ωを介してLEDを繋いでいます。
《タイマー1》
タイマーのPIC24E用日本語リファレンスマニュアルはこちらを参照下さい。
Timer1はセカンダリクロック端子に外部オシレータ32KHzを取り付けて動作させる事も可能ですので、
リアルタイムクロック (RTC) アプリケーション向けに使えます。
割込み発生タイミング
TIMER1/2/3/4/5はTMR1/2/3/4/5(16ビット)のレジスターを0からカウントアップして行きます、
設定されたPR1/2/3/4/5の周期レジスター値と比較して一致したら、割込みを発生させます。
(一致したら0に戻り、再カウントアップ)
ワンカウントの時間は?
PICの命令サイクルクロック周波数(FCY) とプリスケーラ設定値できまります。
・ 例えばFCY=60MHz(FOSC/2)でプリスケーラ設定値が 64 なら
(1/FCY) x プリスケーラ設定値
(1 / 60MHz) x 64 = 1.066us → これがワンカウントの時間です。
9376までカウントアップさせると1.066x9376=10000.44us(10ms)なので
1秒なら、割り込み(ワンカウント)を100回数えればよさそうです。
なのでPRxのタイマー周期レジスタPRx = 9376 - 1 で設定します。
TIMER1の使い方は次の順番で行います
@ タイマー制御レジスターの設定を行います
T1CON = 0b0000000000100000 ;
赤色数字部分でプリスケーラの設定を行います。
00 = 1:1 01 = 1:8 10 = 1:64 11 = 1:256
緑色数字部分で外部クロックの入力同期選択を行います。
0 = 同期させない 1 = 外部クロック入力を内部クロックに同期させる
青色数字部分でクロック源の選択を行います。
0 = 内部クロック(FCY)を選択 1 = 外部クロック(立ち上がりエッジ)を選択
A 16ビット周期レジスター(PR1)の設定を行います
TMR1を何カウントアップさせるかの設定です、
PR1=9375 とした場合は、9376カウントしたら割込み発生します。
B TMR1カウントアップレジスターの初期化を行います
TMR1 = 0 ;
C 割込み機能を許可します
_T1IE = 1 ; // タイマー1割り込みを許可する
_T1IP = 6 ; // タイマー1割込み優先レベル(0-7)を設定する
_T1IF = 0 ; // タイマー1割込みフラグをクリアする
優先レベル0は割り込みが発生しません、1-7を指定、数値の多い方が高優先。
D 全体割り込みの許可をします
_IPL = 0 ; // CPUの割込み優先レベルを設定(優先レベル0以上を許可)
_GIE = 1 ; // 全割り込み処理を許可する
"_IPL"に設定した数値以上が割り込みを発生します。
"_IPL = 4"とした場合は、"_T1IP = 5"なら割り込みが発生します。
E タイマー1をスタートさせます
T1CONbits.TON = 1 ; // タイマー1開始
割込み関数の書き方例
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void)
{
Count++ ; // 割込み発生の回数をインクリメントする
if (Count >= 100) { // 割込みを100回数えると約1秒
Count = 0 ;
}
_T1IF = 0 ; // タイマー1割込みフラグクリア
}
※ 割り込み処理の記述方法は、PIC24Fでの記述例ですがこちらのサイト(picfun)を参照しましょう。
"MPLAB C30"での記述ですが、XC16でも動作します。
TIMER1のサンプルプログラムはこちらからダウンロードして下さい。
《タイマー2・3・4・5》
Timer3/5はアナログ(A/D)モジュールの変換タイミングをトリガー出来ます。
操作はTimer1と基本同じです、以下ではTimer2での説明となります。
タイマー制御レジスターの設定
T2CON = 0b0000000000100000 ;
赤色数字部分でプリスケーラの設定を行います。
00 = 1:1 01 = 1:8 10 = 1:64 11 = 1:256
水色数字部分でTimerxモード選択を行います。
0 = 16ビットタイマーとする 1 = 32ビットタイマーとする
青色数字部分でクロック源の選択を行います。
0 = 内部クロック(FCY)を選択 1 = 外部クロック(立ち上がりエッジ)を選択
TIMER2のサンプルプログラムはこちらからダウンロードして下さい。
《32ビットタイマー》
Timer2とTimer3 、Timer4とTimer5、を組み合わせれば32ビットタイマーとして動作しまが、
ここでは、Timer2とTimer3を使った説明となります。
1秒カウントの設定は?
例えばFCY=60MHz(FOSC/2)でプリスケーラ設定値が 64 なら
(1 / 60MHz) x 64 = 1.066us → これがワンカウントの時間です。
937559までカウントアップさせると1.0666*937559=1000000.42us(1秒)です。
(32ビットも有るので1回の割り込みで1秒が出来ますね)
なのでタイマー周期レジスタPR2(LSW)/PR3(HSW) = 937559 - 1 で設定します。
937558(0xE4E56)なので、PR3 = 0x000E、PR2 = 0x4E56 と設定すれば良いでしょう。
TMRxカウントアップレジスターは?
TMR2とTMR3レジスターペアでなく、TMR2 と TMR3HLDレジスターペアとなります。
書き込む順番は、TMR3HLDにセットした後、TMR2にセットします、TMR2にセットすると自動的に
TMR3HLDからTMR3に転送されるらしい。(読出しは逆の手順です)
レジスターの設定例
// タイマー2/3の設定(32ビット動作)
T2CON = 0b0000000000101000 ; // プリスケーラカウント値 1:64、内部クロック(FCY)で使用、32ビット動作
TMR3HLD = 0 ;
TMR2 = 0 ; // タイマーのカウンターを初期化する
PR3 = 0x000E ; // 周期レジスタH
PR2 = 0x4E56 ; // 周期レジスタL 約1秒(937558)
_T3IE = 1 ; // タイマー割り込みを許可する
_T3IP = 6 ; // タイマー割込み優先レベル(0-7)を設定する
_T3IF = 0 ; // タイマー割込みフラグをクリアする
T2CONbits.TON = 1 ; // タイマー開始
割込み関数の書き方例
void __attribute__((interrupt, no_auto_psv)) _T3Interrupt(void)
{
_T3IF = 0 ; // タイマー2割込みフラグクリア
}
※ って感じでタイマー3の割り込みを使います。
32ビットのサンプルプログラムはこちらからダウンロードして下さい。
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2015 Shigehiro Kimura All Rights Reserved.