現在電子工作をしており、それに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ヶ月ぐらいやってますがうまくいきません。
良ければご回答をお願いします。
No.1ベストアンサー
- 回答日時:
>消えている状態で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つ足りなかったのでおそらくここだと思います。
という感じになっています。
No.2
- 回答日時:
訂正
if ((LEDの状態==0) && (RA1==1)) {//消灯時はRA1は無視
は
if ((LEDの状態==1) && (RA1==1)) {//消灯時はRA1は無視
の間違い
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 電気・ガス・水道 電気工事に詳しい方 5 2022/07/28 12:47
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- その他(法律) 自動車の点灯義務について 6 2023/02/24 15:01
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- 照明・ライト 懐中電灯は、スイッチを一回押すとランタン用のLEDが点いて、もう一回押すと懐中電灯用の別のLED電球 1 2023/04/05 20:18
- その他(パソコン・周辺機器) USB端子間に挟んで使う、スイッチのような物は売られていますか。 3 2022/08/25 22:26
- 照明・ライト ワークランプの故障について 1 2022/07/11 17:37
- C言語・C++・C# 大量のデータを読み込んで表示する速度を改善したい 8 2023/05/07 13:29
- その他(教育・科学・学問) センサー(Cds)を用いたLEDの点灯回路で周囲が暗くなるとLEDが消灯する回路の動作説明ができる方 3 2022/11/20 18:22
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スーパーのレジで並んでいたら...
-
CPUの処理量を減らすコーデ...
-
PICでタイマー割込み(mikroC V...
-
C言語について(PWM)
-
PICの割り込み機能
-
割り込み処理のシミュレート
-
picタイマ0割り込みについて
-
電車で待機列の割り込みについ...
-
PICで既定の時間数ループを...
-
割り込みについて
-
割り込みの衝突
-
音声ファイル再生時のフリーズ
-
アセンブラのタイマー割り込み
-
ショッピング
-
H8マイコンで割り込みが任意の...
-
順番待ちで並んでいる時、割り...
-
VB6でSendKeyを利用したTab移動...
-
駅のトイレでナイチンに邪魔さ...
-
Macターミナルで実行中のプログ...
-
緯度、経度の 10進法と 60進法...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
インバウンドで迷惑している人...
-
pic 複数の割り込み関数 切り分...
-
スーパーのレジで並んでいたら...
-
ショッピング
-
Excelでタイマーの一時停止する...
-
電車で待機列の割り込みについ...
-
CPUの処理量を減らすコーデ...
-
C言語でPICマイコン開発
-
【組込み】割り込み中のstatic...
-
Amazonfireタブレットにわから...
-
マイコン C言語 割り込み処理...
-
USB機器からのデータ受信による...
-
一定時間操作がなかったら、と...
-
VB.net 割り込みの禁止
-
ウォッチドッグタイマ(WDT)の...
-
電車乗車時、並んでいるのに割...
-
USJでの割り込み
-
VB6でSendKeyを利用したTab移動...
-
PICでのプログラムによるチャタ...
-
割り込み中に例外異常
おすすめ情報