- ベストアンサー
PICの割り込み機能とは?プログラミングでの実装方法を教えてください。
- PIC16F84Aを使用して、C言語でプログラムを作成し、LEDの点灯・消灯を制御しています。
- 割り込みを実装することで、RA1の入力によってLEDの点灯を5秒後に自動的に消灯させることができます。
- 現在のプログラムは割り込みがうまく機能せず、5秒後に点灯してしまう問題があります。解決方法を教えてください。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
>消えている状態でRA1に入力を入れたときなぜか5秒後に点灯してしまいます。 点灯するでしょうね。そういうプログラムになってますから。 >・RA1に入力があったときLEDが点灯しているなら5秒後にLEDを消灯。 >・RA0に入力があったときRB0につないであるLEDが消灯しているならLEDを点灯。 RA1に入力があり、5秒後にLEDを消灯した次の瞬間に、RA0に入力があったら「LEDが消灯しているのでLEDを点灯」する事になります。 こういう場合には、普通 ・入力ポートに変化があったら割り込みがかかる ・タイマーにより割り込みがかかる と言うハード構成にします。 セオリーは「メインでポートを監視する為の無限ループを組まない事」です。 つまり >どれもすべて動作を終えて、あとはwhile(1)で割り込みを待つだけ というプログラムにするのが常道なのです。 なので、ネットでさがすと、そういうプログラムばかり見付かる筈です。 以下のような作り方をしましょう。 グローバル変数は「直前のRA0の状態」と「秒カウンタ」と「LEDの状態」を用意します。 int 直前のRA0の状態; int 秒カウンタ; int LEDの状態; main() { ハードの初期化; 直前のRA0の状態=0; 秒カウンタ=0; LEDの状態=0; 割り込み許可; while(1) {;} } void interrupt isr(void) { if (直前のRA0の状態 != 今のRA0) { 直前のRA0の状態 = 今のRA0; if (RA0==1) { LED点灯; LEDの状態=1; 秒カウンタ=0;//RA1の入力後の5秒間にRA0が変化したらチャラにする } else { LED消灯; LEDの状態=0; 秒カウンタ=0;//RA1の入力後の5秒間にRA0が変化したらチャラにする } if (秒カウンタ==0) {//通常時 if ((LEDの状態==0) && (RA1==1)) {//消灯時はRA1は無視 秒カウンタ++;//5秒待ち状態に入る } } else {//5秒待ち状態に入っている時 秒カウンタ++; if (秒カウンタ>=500) {//1ミリ秒×500=5秒 LED消灯; LEDの状態=0;//LEDを消す 秒カウンタ=0;//5秒待ち状態から通常状態に戻る } } 割り込みを再許可する } 割り込み間隔を1ミリ秒にしているのは、チャタリング防止の意味も兼ねていて、エッジノイズやパルスなど、1ミリ秒より短い変化は拾いません。
その他の回答 (1)
- chie65536
- ベストアンサー率41% (2512/6032)
訂正 if ((LEDの状態==0) && (RA1==1)) {//消灯時はRA1は無視 は if ((LEDの状態==1) && (RA1==1)) {//消灯時はRA1は無視 の間違い
補足
お早いご回答ありがとうございます。 >セオリーは「メインでポートを監視する為の無限ループを組まない事」です。 >つまり >>どれもすべて動作を終えて、あとは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つ足りなかったのでおそらくここだと思います。 という感じになっています。