質問
PICの割り込み機能
- 投稿日時:2008/01/07 13:01

現在電子工作をしており、それに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ヶ月ぐらいやってますがうまくいきません。
良ければご回答をお願いします。
回答 (2件)
- 最新から表示
- 回答順に表示
- ベストアンサーのみ表示
No.2
- 回答日時:2008/01/07 14:28
訂正
if ((LEDの状態==0) && (RA1==1)) {//消灯時はRA1は無視
は
if ((LEDの状態==1) && (RA1==1)) {//消灯時はRA1は無視
の間違い
- 質問者のみ
- この回答にお礼をつける
No.1ベストアンサー20pt
- 回答日時:2008/01/07 14:24
>消えている状態で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ミリ秒より短い変化は拾いません。
この回答への補足
お早いご回答ありがとうございます。
>セオリーは「メインでポートを監視する為の無限ループを組まない事」です。
>つまり
>>どれもすべて動作を終えて、あとは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つ足りなかったのでおそらくここだと思います。
という感じになっています。
- 質問者のみ
- この回答にお礼をつける
このQ&Aを見た人はこんなQ&Aも見ています
注目の記事
ストレスをふっとばす!五月病撃退法
コレって五月病?治療するにはどうすればいいの?連休明けに気をつけたい五月病の撃退法を教えます!
このQ&Aを見た人がよく見るQ&A
このカテゴリで人気のQ&Aランキング
- 4Visual Studio Expressは無料?
- 5sleep()関数について
- 6構造体の初期化方法について
- 7C言語とC++ の違いについて(オブジ...
- 8C++とVC++の違いについて
- 9三角関数の記述の仕方
- 10int main()、void main()、void mai...
- 11stdin,stdoutについて
- 12セマフォとmutexの違いは?
- 13C ファイル出力で、フォルダがない...
- 14size_t
- 15C++ OpenCV Mat CvMat Ipl
- 16C言語 exitの使い方
- 17C言語で簡単なゲームを作る方法
- 18windows.hがincludeされない
- 19c言語でできること
- 20HANDLEとHWNDの違いについて





