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に関連する人気のQ&A

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

このQ&Aと関連する良く見られている質問

QH8マイコンでの割り込み(シリアルポート入力で)

マイコン:AKI H8/3048F
開発環境:GCC Developer Lite
マイコンとパソコンをRS-232Cケーブルでつないでいます。

ハイパーターミナルを使用して、マイコンを制御したいと考えております。
それで、パソコンのキーボードから入力があった時だけ、割り込みを実行したいです。
割り込みが無い場合は、パソコンでマイコンを制御することができたのですが、割り込みを追加したら、うまくいかなくなりました。

アセンブラを使用せずに、C言語だけでプログラムを完成させたいと思っています。

SCI1からの割り込み処理をするには、どの様にしたらよいのでしょうか?

どうか、お願いいたします。

Aベストアンサー

>void int_rxi1(void) 
>{
>  DI;  /*ここで他のプログラムの割り込みを禁止*/
>      /*割り込みで実行させたいプログラム*/
>  EI;  /*割り込み許可にしてプログラムを終了*/
>}

I.割込み処理ルーチンではDI,EIを行ってはいけません。
 以下に示すように割込みの禁止はハードウェアがやってくれます。
 割込み禁止解除は割込み処理が終了したとき実行されるRTE命令で
行われます。
------------ H8/3048ハードウェアマニュアル --------------------
4.1.2 例外処理の動作
例外処理は、各例外処理要因により起動されます。
トラップ命令および割り込み例外処理は、次のように動作します。
(1) プログラムカウンタ(PC)とコンディションコードレジスタ(CCR)をスタックに退避しま
す。
(2) CCRの割り込みマスクビットを1にセットします。
(3) 起動要因に対応するベクタアドレスを生成し、そのベクタアドレスの内容が示す番地からプ
ログラムの実行が開始されます。
【注】リセット例外処理の場合は上記(2)、(3)の動作を行います。
-------------------------------------------------------------------
II.割込み処理関数には#pragma interrupt を付けます。
#pragma interrupt
void int_rxi1(void)
{

}
 なお、#pragma と関数宣言の間にコメントを入れてはいけません。
 一種のおまじないです。

III. 割込み処理関数では少なくとも以下の2つを実行する。
 (1)SCI1.RDRを適切な場所に保存
 (2)SCI1.SCR.BIT.RDFをクリア

 デバッガを使えるなら、割込み処理の入り口で止めて動作を
確認して下さい。

>void int_rxi1(void) 
>{
>  DI;  /*ここで他のプログラムの割り込みを禁止*/
>      /*割り込みで実行させたいプログラム*/
>  EI;  /*割り込み許可にしてプログラムを終了*/
>}

I.割込み処理ルーチンではDI,EIを行ってはいけません。
 以下に示すように割込みの禁止はハードウェアがやってくれます。
 割込み禁止解除は割込み処理が終了したとき実行されるRTE命令で
行われます。
------------ H8/3048ハードウェアマニュアル --------------------
4.1.2 例外処理の動作
例外処...続きを読む

Qteratrermを使ったデータの送信について

teratermで
16進数で下記の5バイトを送信したいのですが、どうすればいいでしょうか。

\x85\x02\x00\x01\x86

VTウィンドウにキーボードで直接打ち込むと、一文字ごとに送信されているようで、うまく行きませんでした。

Aベストアンサー

送信したい文字列を書いたファイルを作成してください。

teratrerm メニューの「ファイル(F)」-「ファイル送信(S)」を選び、作成したファイルを選択してください。
このとき作成したファイルの内容がバイナリーの場合送信ファイル選択画面のオプションで「バイナリー(B)」にチェック入れてください。

>16進数で下記の5バイトを送信したいのですが、どうすればいいでしょうか。
たぶんバイナリーだとおもいますのでファイルはバイナリーエディターで作成してください。

注)これは日本語化したteratermでの説明です


人気Q&Aランキング

おすすめ情報