H8マイコンの学習をしています。
LEDを一定時間ごとに点滅させるためにタイマ割込を使用して時間稼ぎ処理を行おうとしました。
1ms毎の割込でグローバル変数をインクリメントし、メインループ内でグローバル変数が一定値以上になるまで無限ループする処理を作成しました。
しかし、メインループの数値チェックの無限ループが終了せずLEDが点滅しません。
原因についてお知恵を拝借できないでしょうか。
何卒よろしくお願いいたします。
以下は環境およびコードです。
マイコン:H8/36109(H8/H300 Tinyシリーズ)
使用ツール:HEW4, E8a
(main.c)
#include "iodefine.h"
volatile unsigned int cnt; //グローバル変数
void main(void)
{
cnt = 0;
while(cnt < 1000); //ここで無限ループのまま(補足も参照)
IO.PDR2.BIT.B0 = IO.PDR2.BIT.B0; //ここにブレークをかけても引っ掛らない
}
(intprg.c)
#include <machine.h>
#include "iodefine.h"
extern volatile unsigned int cnt;
#pragma section IntPRG
(略)
// vector 22 Timer V
__interrupt(vect=22) void INT_TimerV(void)
{
cnt++; //(補足参照)
TV.TCSRV.BIT.CMFA = 0; //コンペアマッチフラグクリア
}
(hwsetup.c)
void HardwareSetup(void)
{
IO.PCR2 = 0xff; //出力ポート
//タイマVの設定
TV.TCRV0.BYTE = 0x4b; /* CMFA有効, コンペアマッチAでクリア, φ/128 = 125kHz */
TV.TCRV1.BYTE = 0x01; /* 外部入力禁止 */
TV.TCORA = 125; /* 1ms */
TV.TCSRV.BYTE = 0x00; /* フラグクリア, 出力禁止 */
}
(補足)
割込動作内でブレークをかけるとブレークがかかり、そこからステップ実行するとグローバル変数が変化していることを確認しました。
同様に、メインループの数値チェック無限ループでブレークをかけ、条件を満たすようにグローバル変数を手動で書き換えステップ実行すると無限ループを脱出しました。
No.4ベストアンサー
- 回答日時:
1.割り込みが本当に掛かっているかのチェック
メイン関数ではなく、割り込みでLEDを点滅させます。
割り込み毎にLED出力を反転させればいいが、オシロが無いと観測出来ない。
割り込みプログラムを工夫して肉眼で分かる周期で反転させるようにする。
2.それが出来たら、割り込み処理の中でグローバル変数をインクリメントする。
グローバル変数が1000以上だったら点灯、2000以上だったら消灯すると共にゼロクリア。
初めから1と2を同時に行っても良いでしょう。
3.ここまで出来てから、メイン関数で点滅する事を考える。
この回答への補足
早速の御回答ありがとうございます。
一応、インクリメントした値を割込内でI/Oに出力する方法でI/Oが全点灯することは目視確認していましたが、オシロによる測定は行っていませんでした。来週にオシロを使用する機会があるのでそこで確認してみようと思います。
それまでは(2)の事項をやってみようと思います。
(2)の事項ですがH8/36109ではうまくいきませんでした。H8/3048ではうまくいったのですが。
そこで、基本設定含め最初から確認することにしました。よって、ここで一旦質問を打ち切らせていただきます。
ありがとうございました。
No.5
- 回答日時:
お疲れ様です。
cntの宣言ですが、[volatile]はついていますでしょうか?
もしかすると、これが原因かも。。
この回答への補足
早速の御回答ありがとうございます。
"main.c"の先頭部で以下のように宣言していますが何か間違っているのでしょうか?
volatile unsigned int cnt; //グローバル変数
No.3
- 回答日時:
回答2の補足説明です。
main関数のwhileは
「ループの先頭でcnt < 10001 なら無限ループに入れ」
と解釈されています。
プログラマの意図が違うならそれなりのコーディングを
すべきです。
この回答への補足
申し訳ありません。こちらの記載ミスです。
実際のプログラムは以下のとおり、メインループが組み込まれています。
ご迷惑をおかけしました。
void main(void)
{
while(1)
{
cnt = 0;
while(cnt < 1000); //ここで無限ループのまま(補足も参照)
IO.PDR2.BIT.B0 = IO.PDR2.BIT.B0;
}
}
No.2
- 回答日時:
デバッガーを使える環境のようですから mainのwhile 部分の
アセンブラ表示を貼り付けてもらえると検討のしようがあるん
ですが。
while(1) {
if (cnt > 1000) break;
}
にすれば抜けて来ると思われます。
この回答への補足
早速の御回答ありがとうございます。
ご指摘頂いたように修正しましたが、抜けてくれませんでした
質問事項のアセンブラ表示は以下のとおりです。
"//"の行はCのコード、"[xxxxxx]"は逆アセンブリアドレスです。
グローバル変数「cnt」のアドレスは 0xFFE400 、タイマ割込ステータス(TV.TCSRV.BYTE)のアドレスは0xFFFFA1、I/O出力(IO.PDR2.BYTE)のアドレスは 0xFFFFD5 です。
(main.c)
// void main(void)
// {
// while(1)
[00082E] BAR @_main:8
// cnt = 0;
[000816]_main SUB.W R0,R0
[000818] MOV.W R0,@_cnt:24
// while(cnt < 1000);
[00081E] MOV.W @_cnt24,R0
[000824] CMP.W #H'03E8, R0
[000828] BCS @H'081E:8
// IO.PDR2.BIT.B0 = IO.PDR2.BIT.B0;
[00082A] BNOT #0,@H'FFFFD5:8
[00082E] BAR @_main:8
// }
(intprg.c)
// __interrupt(vect=22) void INT_TimerV(void)
[000434]_INT_TimerV MOV.W R1,@-ER7
[000436] MOV.L ER0,@-ER7
// {
// cnt++;
[00043A] MOV.L #H'00FFE400, ER0
[000440] MOV.W @ER0,R1
[000442] INC.W #1,R1
[000444] MOV.W R1,@ER0
// TV.TCSRV.BIT.CMFA = 0;
[000446] BCLR #6,@H'FFFFA1:8
// }
[00044A] MOV.L @ER7+,ER0
[00044E] MOV.W @ER7+,R1
[000450] RET
指摘していただいたとおりに修正した後のアセンブラ表示は以下のとおりです。
(main.c)
// void main(void)
// {
// while(1)
[00082E] BAR @_main:8
// cnt = 0;
[000816]_main SUB.W R0,R0
[000818] MOV.W R0,@_cnt:24
// while(1)
// {
// if(cnt > 1000) { break; }
[00081E] MOV.W @_cnt24,R0
[000824] CMP.W #H'03E8, R0
[000828] BLS @H'081E:8
// }
// IO.PDR2.BIT.B0 = IO.PDR2.BIT.B0;
[00082A] BNOT #0,@H'FFFFD5:8
[00082E] BAR @_main:8
// }
(intprg.c)変更前とアドレス含めてすべて同じなので省略します。
No.1
- 回答日時:
専門家とは言っても、H8やHEWは使ったことが無くあまり詳しくないので
一般論ですが、、、
割り込みコンテキストで値をいじるcntにアクセスするとき
割り込み禁止にしておく必要はないですか?
void main(void)
{
/* 割り込み禁止 */
cnt = 0;
/* 割り込み許可 */
while(1) {
/* 割り込み禁止 */
if (cnt >= 1000) break;
/* 割り込み許可 */
}
/* 割り込み許可 */
IO.PDR2.BIT.B0 = IO.PDR2.BIT.B0;
}
これが原因でもタイマのクリアが本当に1ms周期で処理能力が追いついているなら、
無限ループを抜けないってことは無いと思いますが設定はあってますか?
この回答への補足
早速の御回答ありがとうございます。
プログラムを以下のように修正しましたが、無限ループを抜けませんでした。
void main(void)
{
set_imask_ccr((_UBYTE)1)/* 割り込み禁止 */
cnt = 0;
set_imask_ccr((_UBYTE)0)//* 割り込み許可 */
while(1) {
set_imask_ccr((_UBYTE)1)//* 割り込み禁止 */
if (cnt >= 1000) break;
set_imask_ccr((_UBYTE)0)//* 割り込み許可 */
}
set_imask_ccr((_UBYTE)0)/* 割り込み許可 */
IO.PDR2.BIT.B0 = IO.PDR2.BIT.B0;
}
割込の方でも先頭に割込禁止処理、終端に割込許可処理を追加してあります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの問題です。至急教えてください。 /***から***/の部分をプログラミングにしてほし 1 2022/10/13 11:48
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- JavaScript カラーミーショップのsectionループ内で、[引数][戻り値]ありの関数的な処理を行いたいです。 1 2022/05/07 19:39
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分 1 2022/07/19 17:03
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 malloc関数を使ってください!お願いします! 最 1 2022/07/21 09:28
- C言語・C++・C# 至急お願いします。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分母 3 2022/07/19 17:09
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# 至急教えてください!プログラミングの問題です。 割られる整数と割る整数を受け取って、商と余りを出力す 3 2022/07/05 10:23
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Amazonfireタブレットにわから...
-
プリントスクリーンの自動化
-
PICのPIN変化割り込みに...
-
H8マイコンでの割り込み(シリ...
-
ATtiny2313でsleep_mode()関数...
-
マイコンの割り込みについて教...
-
電車のドアの前での並び方
-
ウォッチドッグタイマ(WDT)の...
-
電車で待機列の割り込みについ...
-
volatileについて
-
割り込み中に例外異常
-
H8マイコンで割り込みが任意の...
-
MIDIファイルについて
-
順番待ちで並んでいる時、割り...
-
【組込み】割り込み中のstatic...
-
(H8マイコン)タイマ割込で変更...
-
Excelでタイマーの一時停止する...
-
ショッピング
-
電車乗車時、並んでいるのに割...
-
Macターミナルで実行中のプログ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
インバウンドで迷惑している人...
-
pic 複数の割り込み関数 切り分...
-
スーパーのレジで並んでいたら...
-
ショッピング
-
Excelでタイマーの一時停止する...
-
電車で待機列の割り込みについ...
-
CPUの処理量を減らすコーデ...
-
C言語でPICマイコン開発
-
【組込み】割り込み中のstatic...
-
Amazonfireタブレットにわから...
-
マイコン C言語 割り込み処理...
-
USB機器からのデータ受信による...
-
一定時間操作がなかったら、と...
-
VB.net 割り込みの禁止
-
ウォッチドッグタイマ(WDT)の...
-
電車乗車時、並んでいるのに割...
-
USJでの割り込み
-
VB6でSendKeyを利用したTab移動...
-
PICでのプログラムによるチャタ...
-
割り込み中に例外異常
おすすめ情報