アプリ版:「スタンプのみでお礼する」機能のリリースについて

ATmega168とWinAVRで割り込みのプログラミングをしています。
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER1_OVF_vect)
{
TCNT1 = 65500;
PORTC ^= 0x02;
}
int main()
{
int i;
DDRC = 0x07;
PORTC ^= 0x01;
TCCR1B = 0x00;
TCNT1 = 65500;
TIMSK1 = _BV(TOIE1);
TCCR1B = 0x05;
sei();
while (1) {
PORTC ^= 0x04;
for(i=0;i=500;i++){}
}
}
上記のプログラムを組んでみたのですが。while文に入ってfor文に少し入ってからISRの処理が始まるのですが。ISRの処理が終わってから又for文の処理に戻ろうとしません。なのでPORTC0x04の点滅が起こりません。PORTC0x04の点滅もしながらPORTC0x02の点滅もしたいのですがどうすれば良いのでしょうか?

A 回答 (6件)

>回答ありがとうございます。

プログラムの確認はWinAVRのシュミレーションで確認しました。

シミュレータ上でデバッガで停止させて確認したと認識よろしいですか?
なぜ、mainに戻っていないと確信を得たか教えてください。

>あと割り込みと言うのはmain()文を中心に処理するが割り込みの条件がはいったならばmain文の処理をいったん停止し、割り込みの内容を優先する。割り込みの処理が終了したらmain文の処理に戻っていくという認識をしているのですが合っているのでしょうか?

main文だとmain関数の中だけ見たいですが、割り込み処理以外の部分でプログラムが走っている場合は、どこの処理中でも割り込み信号が発生した瞬間に処理を中断して割り込み処理終了後に続きの処理に戻ります。
割り込む命令の単位はマシン語1命令の単位でありC言語の文の単位では有りません。

>メインでPORTCを変更する間は割り込みを禁止してください。
cil();
PORTC ^= 0x04;
sei();

ここらを参考に↓
http://avrwiki.jpn.ph/wiki.cgi?page=Getting+Star …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
それはプログラム的に言うと
int main(){
  ・
  ・
while (1) {
cil();
PORTC ^= 0x04;
sei();
for(i=0;i=500;i++){}
}
}
こういうことで良いんでしょうか?
うまくいきません。

お礼日時:2009/05/29 18:33

>F11を押すとプログラムが一つずつ進んでいくのでそれを見ていると


>ISRに入った後main文に戻らずにISR文の中でずっとループしていました。

ループ構造を持たないISRの中でループするのは変だと思いません?
それは、割り込みタイマがステップ実行中(F11)でも無関係にカウントダウンしてオーバーフローしてるんじゃないでしょうか?なので割り込みを抜けると直ぐ再度割り込んでいるんじゃ?
割り込みのデバッグはF11で実行しないで下さい。必ずブレーク設定して調べたい命令の所で止めましょう。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。

お礼日時:2009/06/15 18:31

R32Cさんの指摘まで基本的すぎて見落としてましたが、このコードは確実に無限ループします。


>for(i=0;i=500;i++){}
>}
i=500は代入文で条件式では無いので常に真でループから抜けることが出来ません。つまり無限ループです。

>シミュレータ上でデバッガで停止させて確認したと認識よろしいですか?
>なぜ、mainに戻っていないと確信を得たか教えてください。

こちらは答えてもらえないんでしょうか?
デバッガがちゃんと使えたら無限ループしていることは直ぐに確認できたのに勿体無いですね。
    • good
    • 0
この回答へのお礼

i=500になったら終了と言うことではなかったのですね。
シュミレータはデバッガと言うよりビルド&ランをしていました。
F11を押すとプログラムが一つずつ進んでいくのでそれを見ていると
ISRに入った後main文に戻らずにISR文の中でずっとループしていました。

お礼日時:2009/05/30 06:42

>for(i=0;i=500;i++){}


無限ループしているのでは?
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
for文を抜けるとwhile文で戻ってまたportにいきますよね。
それがいかないんです。だからiが500に成ったら自動的に上に戻るはずなんですけどね。まだ良くわかっていません。

お礼日時:2009/05/29 18:23

プログラムを見る限りは正常に動作するとは思えません。



PORTC ^= 0x04;
はアセンブラ1命令に置き換えれませんよね?
(1)レジスタ←PORTC
(2)レジスタ←レジスタ XOR 0x04
(3)レジスタ→PORTC
となるはずですので(1)~(3)の間のどこかで割り込む可能性が出てきます。もし(2)で割り込んだらPORTCの書き換えが割り込み中で行われるので(2)の時点でレジスタが保持している値と実際のPORTCの値が違う可能性かが出てきます。

>上記のプログラムを組んでみたのですが。while文に入ってfor文に少し入ってからISRの処理が始まるのですが。ISRの処理が終わってから又for文の処理に戻ろうとしません。

これはどのようにして確認しましたか?
LEDの点滅以外のデバッガ等で確認しましたか?

>なのでPORTC0x04の点滅が起こりません。PORTC0x04の点滅もしながらPORTC0x02の点滅もしたいのですがどうすれば良いのでしょうか?

メインでPORTCを変更する間は割り込みを禁止してください。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。プログラムの確認はWinAVRのシュミレーションで確認しました。
あと割り込みと言うのはmain()文を中心に処理するが割り込みの条件がはいったならばmain文の処理をいったん停止し、割り込みの内容を優先する。割り込みの処理が終了したらmain文の処理に戻っていくという認識をしているのですが合っているのでしょうか?

お礼日時:2009/05/28 17:26

こんにちは。


ええと、多分ですが、関数ISRが割り込みハンドラとしてコンパイルされていないため、正しくリターンできていないのではないでしょうか。
割り込みハンドラとしてのコンパイルの仕方は、コンパイラのマニュアル等を見てください。
あと、蛇足ですが、PORTCをメインルーチンと割り込みの両方から変更していますが、メインルーチンで変更する間は割り込み禁止にするとかしないと、動きがおかしくなると思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
割り込み禁止とはcil();のことでしょうか?
具体的にどこに入れれば良いのでしょうか?
ソースで示していただけると大変うれしいです。
どうか、よろしくお願いします。

お礼日時:2009/05/28 17:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!