PICで電飾 割り込み処理 その3 タイマ1の設定方法
呼び出し呪文と周期のパラメータ
3種類のタイマ機能のうち、前回はタイマ0を使ってみたので、今度は同じ作業をタイマ1を使ってやってみましょう。
今回も一番下にプログラムを載せておきます。やっていることは前回と全く同じです。
1)赤字がタイマ1を使うのに必要なところです。呪文と同じようなものなのでコピペして使ってください。一応意味は//以降に書いています。
2)水色の背景のところが、割り込みの周期を決めるパラメータです。
タイマ1でも3つの要素で周期が決まります。
①クロック数
②プリスケール
③TMR1初期値
ここでも20ミリ秒ごとに割り込み処理をすることにして、計算は「PICとは」に頼りましょう。
フォームのプリスケール(赤丸)と、TMR1初期値(緑丸)をいじって、タイマ周期を20ミリ秒にします。
このとき、緑丸の数字は、直接入力せずに、かならずフォームについている数字のボタン(緑の枠)のところを押して上下させてください。
今度はきっちりタイマ周期を20ミリ秒に出来ましたね(オレンジの矢印)。タイマ1の方がタイマ0より緻密にコントロールできるということのようです。ではこれらのパラメータを書き込みましょう。
①クロック数の設定
クロック数の設定はタイマ0と同じにしておきます。
OSCCON = 0b01110010 ;//①内部クロック8MHz
②プリスケールの設定
②のプリスケールの設定は、T1CONというレジスタの下から5.6桁目の数字を変えることで設定します。
T1CON=0b00110000;//②プリスケール値8
プリスケールの値は8でした。これをレジスタの入れるときは下の表に従って、
11を水色の背景のところに入れるわけです。
③TMR1初期値
③のTMR1初期値がちょっと厄介です。これは、フォームの計算では60536と出てきましたが、そのままの数字では使えません。
1)60536という10進数の数値を16進数に直す
2)できた16進数の数字を上2桁と下2桁に分けて、TMR1HとTMR1Lに代入する
というめんどくさい作業が必要なのです。
10進数を16進数に直すのは、エクセルの関数でも出来ますし、そういう電卓フォームを提供してくださるWebページで計算するのも一手です。お勧めはカシオのページ。
60536を入れると、 16進数でそれはEC78だと教えてくれます。これを上2桁のECと下2桁の78に分けます。
16進数のECと78を10進数にもう一度直すと236と120になります。
あー行ったり来たりめんどくさい…。あれ?これって、
もうすでにここに計算してくれてあるやん。
というわけで、タイマー1初期値はフォームが計算してくれるTMR1H:TMR1Lの数値を引いてきて
TMR1H=236;//③タイマ1初期値1
TMR1L=120;//③タイマ1初期値2
こう書けばいいわけです。
自分でTMR1初期値を10進で計算し、16進に直して…の作業はうんざりですが、このページのフォームを使えばあっという間。
他のどんな本やwebページ見たってこんな初心者に優しいツール、提供してくれません。
いやほんと、このページ、素晴らしいっ…!ありがたいっ…!
というわけでプログラムです。コピペしてビルドと書き込みをやってみてください。うまく動くでしょうか?確認してみてください。(動作自体は前回と全く同じなんですけど・・・。)
#include <xc.h>
#define _XTAL_FREQ 8000000
//コンフィグ設定
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
#pragma config WRT = OFF
#pragma config PLLEN = OFF
#pragma config STVREN = ON
#pragma config BORV = HI
#pragma config LVP = OFF
int Event=0;
void main(void)
{
//特殊レジスタの設定
OSCCON = 0b01110010 ;//①内部クロック8MHz
ANSELA = 0b00000000 ;//RAの足をすべてデジタルI/Oとして使う
ANSELB = 0b00000000 ;//RBの足をすべてデジタルI/Oとして使う
OPTION_REG = 0b00000000 ;//内部プルアップ抵抗を使う
TRISA = 0b00000000 ;//RAの足はすべて出力に使う
TRISB = 0b00001100 ;//RBの足のうちRB2,RB3を入力に使う
WPUB = 0b00001100 ;//RB2,3に内部プルアップ抵抗をつなぐ
PORTA = 0b00000000 ;//RAの初期値はすべてゼロ
PORTB = 0b00000000 ;//RBの初期値はすべてゼロ
// タイマー1設定
T1CON=0b00110000;//②プリスケーラ値8
TMR1H=236;//③タイマ1初期値1
TMR1L=120;//③タイマ1初期値2
TMR1IF=0;//タイマ1割り込みフラグ0にする
TMR1IE=1;//タイマ1割り込み許可
TMR1ON=1;//タイマ1スタート
PEIE=1;//周辺割り込み許可
GIE=1;//全体割り込み許可
while(1)
{
if (Event==0)//平常時
{
RB6=1; RB7=0;//RB6点灯、RB7消灯
__delay_ms(1000); //1秒待つ
RB6=0; RB7=1;//RB6消灯、RB7点灯
__delay_ms(1000);//1秒待つ
}
if (Event==1)//イベント時
{
RA1=1;//RA1を点灯
RB6=0; RB7=0;//翼端灯消灯
__delay_ms(5000);//5秒まつ
RA1=0;//RA1を消灯
Event=0;//イベント終了
}
}
}
void __interrupt() xxx(void)
{
if(TMR1IF)//タイマ1による呼び出し
{
TMR1H=236;//タイマ1初期値にもどす
TMR1L=120;//タイマ1初期値にもどす
if(RB3==0 && Event==0)//もしRB3が押されていて、イベントが起きていなかったら
{
Event=1;//イベントフラグ立てる
}
TMR1IF=0;//タイマ1による割り込みリセット
}
}