16F88/16F84Aでの割り込みは試された方もいらっしゃると思います。ここでは、12F683の割り込みに挑戦します。
■割り込みとは・・・
久しぶりの休日、機嫌良く電子工作に励んでいると、「ちょっとこれ手伝って」「こっちをお願い!」・・・もちろん、最優先で実行しなくてはなりません。ようやく落ち着くと、「これもやって欲しいんだけど」 どんなにはんだ付けに集中していても、呼ばれればいつでも最優先です。
メインに動いているプログラムに対してなんらかのタイミングで別の処理を行うことを「割り込み」といいます。割り込み要求が入ると、メイン・プログラムに優先して実行されます。この割り込み処理があることで、PICの能力は飛躍的に向上していますが、一番わかりにくい部分であると思います。
PICでもいくつかの割り込みが用意されています。ここでは、よく使うタイマ割り込みを使います。
■割り込みとは・・・
久しぶりの休日、機嫌良く電子工作に励んでいると、「ちょっとこれ手伝って」「こっちをお願い!」・・・もちろん、最優先で実行しなくてはなりません。ようやく落ち着くと、「これもやって欲しいんだけど」 どんなにはんだ付けに集中していても、呼ばれればいつでも最優先です。
メインに動いているプログラムに対してなんらかのタイミングで別の処理を行うことを「割り込み」といいます。割り込み要求が入ると、メイン・プログラムに優先して実行されます。この割り込み処理があることで、PICの能力は飛躍的に向上していますが、一番わかりにくい部分であると思います。
PICでもいくつかの割り込みが用意されています。ここでは、よく使うタイマ割り込みを使います。
■割り込み間隔
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);//timer1初期化
T1_INTERNAL:クロックは内部クロックを使う指定です。
T1_DIV_8:プリスケーラ値を8にします。
内部クロックは8MHzで駆動しています。
1/8MHz=0.125μs:1パルスの時間
内部ではこの4倍の時間(式の×4倍)がかかるので、
0.125μs×4=0.5μs:
PIC内部にあるプリスケーラ=分周器はパルス・カウントを指定の回数積算してから出力する働きがあります。プリスケーラが8とすると、8回パルスをカウントして「1回」とすることになります。したがって、
0.5μs×8=4μs
これをtimer1でカウントして250msにするには、
250ms/4μs=62500回
となるので、timer1で62500カウントして割り込みをかければ、250msを得ることができます。timer1は16ビットの逆算カウンタなので、
65535-62500+1=3036
がtimer1にセットする初期値となります。+1するのは0の分があるからです。
■割り込みのまとめ
16ビット・タイマtimer1で250msを得るための割り込み間隔の計算方法は・・・・
1/クロック周波数×4倍×プリスケーラの値×(65535-タイマ初期値+1)
クロック周波数:8MHz
プリスケーラ値:8
タイマ初期値:3036
の場合は、
1/8(MHz)*4*8*3036=250ms
となり、250msごとに割り込みがかかります。
■割り込みを利用したプログラミング
#INT_timer1 //timer1割り込み処理を使うときはまずこれを書きます
alart(){ //この部分の関数名はなんでもよいのでつけます
set_timer1(3036); //タイマ初期値です:
led_sts=0x01-led_sts;//250msの間隔で割り込みが入ると実行します。led_stsには0x01と0x00が交互に入ります。
LED=led_sts;//従って、LEDは250msの間隔で点滅します。
}
}
■割り込みの許可
実際のプログラミングでは、割り込みを許可しないと割り込みは発生しません。
enable_interrupts(INT_TIMER1);//割り込み許可
enable_interrupts(GLOBAL);//すべての割り込みを許可
以上を記述すると割り込み動作を開始します。
なお、割り込みは停止することもできます。
disable_interrupts(INT_TIMER1);
割り込みが発生するとメイン・プログラムは動作を一時停止して、割り込み処理を優先します。割り込み処理が長くかかるとメイン・プログラムの動作に支障がきたす場合は、割り込みを停止することも必要になります。
プリスケーラの倍率とタイマ初期値を組み合わせて時間を設定するため、割り込み処理はなかなかやっかいですが、理解すると応用範囲は無限大です。頭の体操と考えて取り組んでください。
説明をよく読んで穴埋めに挑戦してください。
■課題4
LEDを起動時に500msで3回点滅後、割り込みを使い250msで点滅する。
// 赤外線2ch送信機TX2-006P 課題4
// 割り込み
// 起動時500msで3回点滅後、割り込みを使い250msで点滅する。
// ex4-006p.c PIC12F683用
#include<12f683.h>
#DEVICE ADC=10 //A-Dコンバータを10bitで使用
//10bit=2^10=0~1023
#fuses INTRC_IO,NOWDT,PUT,NOPROTECT,NOMCLR
//ウオッチドック・タイマなし、パワーアップ・タイマ使用
//プロテクトなし、MCLRなし
#use delay(CLOCK=8000000) //8MHz駆動
#byte GP=5//GPポート使用
#bit IROUT=GP.5//赤外線LED
#bit LED=GP.4//LED
#bit SW=GP.3//ジョイスティック付属スイッチ
// A-Dコンバータ割り当て
//ch0:スロットル
//ch1:エルロン
//ch2:10kΩ半固定抵抗
#define ON 1
#define OFF 0
#define HI 1
#define LOW 0
int led_sts;
// 0.5*10^-6*8*(65535-3036+1)=250ms
#int_timer1//割り込み関数定義
alart()//250msごとに割り込みを発生する
{
set_timer1((その1));
led_sts=(その2);
LED=(その3);
}
//メイン・ルーチン
void main()
{
int i;
set_tris_a(0x0f);//GP0~GP4入力、GP5出力
setup_oscillator(OSC_8MHz);
setup_timer_1((その4));//250msごとの割り込み
set_timer1((その5));//timer1初期値
IROUT=OFF;
LED=OFF;
led_sts=0;
for(i=0;i<3;i++){
LED=ON;
delay_ms(500);
LED=OFF;
delay_ms(500);
}
enable_interrupts((その6));//割り込み許可
enable_interrupts((その7));//割り込み全体許可
while(1){
//プログラムが終了しないように、実行し続けます。
}
}
■正解
(その1)3036 (その2)0x01-led_sts (その3)led_sts (その4)T1_INTERNAL | T1_DIV_BY_8 (その5)3036 (その6)INT_TIMER1 (その7)GLOBAL
課題4のC言語ソース・ファイルとHEXファイルはこちらからダウンロードできます【ex4_006p.lzh】
長野県飯田工業高校 竹内浩一

PICマイコンでつくるインドア・プレーン
みんなで作ろうインドア・プレーン