※ ChatGPTを利用し、要約された質問です(原文:PICの割り込み機能)
PICの割り込み機能とは?プログラミングでの実装方法を教えてください。
このQ&Aのポイント
PIC16F84Aを使用して、C言語でプログラムを作成し、LEDの点灯・消灯を制御しています。
割り込みを実装することで、RA1の入力によってLEDの点灯を5秒後に自動的に消灯させることができます。
現在のプログラムは割り込みがうまく機能せず、5秒後に点灯してしまう問題があります。解決方法を教えてください。
現在電子工作をしており、それにPIC16F84Aを使っています。
正直アセンブリはよくわからないので、C言語でプログラムを作っています。
コンパイラはPICCLITEで、LEDの点灯・消灯に関するプログラムです。
機能としては
・RA0に入力があったときRB0につないであるLEDが消灯しているならLEDを点灯。
・RA0に入力があったときRB0につないであるLEDが点灯しているならLEDを消灯。
・RA1に入力があったときLEDが点灯しているなら5秒後にLEDを消灯。
というものを目指しています。
1つ目、2つ目の項目はif文で簡単に実現できましたが、割り込みがうまくいかず、
消えている状態でRA1に入力を入れたときなぜか5秒後に点灯してしまいます。
だからRB0の出力を逆にしてみたんですがうまくいかず・・・。
ハード的には、RB0には反対側から5Vをかけ、
RB0=0の時は点灯
RB0=1の時は消灯
としています。
またセラロックは10MHzのものを使用しています。
現在のプログラムとしては
#include "pic.h"
#define XTAL_FREQ 10MHZ
#define MHZ*1000
void DelayUs(unsigned char cnt){ //時間待ち関数
unsigned char i;
i=(cnt)/(12MHZ/(XTAL_FREQ))|1;
while(--i!=0) continue;
}
void DelayMs(unsigned int cnt){ //時間待ち関数
unsigned char i;
do{
i=4;
do{
DelayUs(250);
}while(--i);
}while(--cnt);
}
int cnt,SW;
//SWが0なら消灯
//SWが1なら点灯
void interrupt isr(void){ //割り込み関数
if(T0IF==1){
T0IF=0;
cnt--;
}
if(cnt==0){
RB0=1; //消灯
SW=0;
cnt=190;
T0IE=0;
GIE=0;
}
}
main()
{
TRISA=0xFF; //入出力設定
TRISB=0x00;
PORTA=0x00;
PORTB=0x00;
SW=0;
OPTION=0x87; //プリスケーラの設定
TMR0=0x00;
T0IF=0;
T0IE=1;
cnt=190;
while(1){
if(RA0==1){
DelayMs(60); //チャタリング防止
if(RA0==1){
if(SW==0){
RB0=0;
SW=1;
}
else{
RB0=1;
SW=0;
}
}
}
if(RA1==1){
DelayMs(60); //チャタリング防止
if(RA1==1 && SW==1){
TMR0=0;
T0IF=0;
T0IE=1; //割り込み許可
GIE=1; //全体割り込み許可
}
}
}
}
インターネット上での割り込みのプログラムをいくつか見てみたのですが、
どれもすべて動作を終えて、あとはwhile(1)で割り込みを待つだけ
というプログラムばかりでした。
僕のは基本的にRA0の入力によってLEDを点灯・消灯させつつ
RA1の入力で割り込みを開始。
5秒後に消えたら割り込みを禁止する。
という仕様にしたいのですが・・・・・・。
1ヶ月ぐらいやってますがうまくいきません。
良ければご回答をお願いします。
補足
お早いご回答ありがとうございます。 >セオリーは「メインでポートを監視する為の無限ループを組まない事」です。 >つまり >>どれもすべて動作を終えて、あとはwhile(1)で割り込みを待つだけ >というプログラムにするのが常道なのです。 そーだったんですか・・・・。 とりあえず、このプログラムの通りやってみました、が、 なかなかうまくいきません(汗 最初にRA0につながれているスイッチを押したらそのままLEDがつきっぱなしになっちゃって・・・。 スイッチを押している間消えています。 あと割り込みもうまくいかなかったです・・・。 なかなか消えてくれません。 とりあえずプログラムは #include "pic.h" int a; //直前のRA0の状態 int cnt; //秒カウンタ int LED; //LEDの状態 main() { /*初期化始まり TRISA=0xFF; TRISB=0x00; PORTA=0x00; PORTB=0x00; a=0; cnt=0; LED=0; */初期化終わり OPTION=0x87; //割り込みの設定 TMR0=0x00; T0IF=0; T0IE=1; //割り込み許可 GIE=1; //全体割り込み許可 while(1) {;} } void interrupt isr(void) { if (a != RA0) { a = RA0; if (RA0==1) { RB0=0; LED=1; cnt=0; //RA1の入力後の5秒間にRA0が変化したらチャラにする } else { RB0=1; LED=0; cnt=0; //RA1の入力後の5秒間にRA0が変化したらチャラにする } } //※1 if (cnt==0) { //通常時 if ((LED==1) && (RA1==1)) { //消灯時はRA1は無視 cnt++; //5秒待ち状態に入る } } else { //5秒待ち状態に入っている時 cnt++; if (cnt>=500) { //1ミリ秒×500=5秒 RB0=1; LED=0; //LEDを消す cnt=0; //5秒待ち状態から通常状態に戻る } } T0IE=1; //割り込みを再許可する GIE=1; } ※1…カッコが1つ足りなかったのでおそらくここだと思います。 という感じになっています。