H8マイコンで割り込みしよう [RX&SH&H8]
ちょっと間が空いてしまいましたが、割り込み処理をやってみます。割り込みの無いマイコンなんて、、、フッ!。
割り込みの実現の仕方について、通常の記述と(今回)、デバックモニタでの割り込みの実現方法(次回)の両方を解説します。
それでは今まで作業をしてきたsampleワークスペースを開きます。
もしHEWの画面が図の様に前回のプロジェクト名が太字になっていた場合は、始めに作成したプロジェクトを選択し、右クリックで「アクティブプロジェクトに設定」を行います。
左のペインの中の「intprg.c」をダブルクリックしてエディットWindowに「intprg.c」を開きます。
まずファイルの先頭付近、machine.hをインクルードしている直後にiodefine.hもインクルードしておきます。
#include "iodefine.h"
次に55行目付近の修正を行います。
// vector 19 Timer A Overflow
とコメントされている行の下に関数があります。今回はこのTimer Aを使って定周期で割り込みを発生させ、やっぱりLEDをチカチカさせます。
これだけです。
関数の中身の最初の行は、割り込みコントローラのフラグbitをクリアしています。これを行わないと次の割り込みが発生しなくなります割り込み処理から抜けてもまた割り込みが発生してしまい、それが永久に続くのでお忘れ無く。
次の行が実際にLEDをチカチカさせている処理です。最初にmain関数の中に記述した物をここに持って来ただけです。
次にmain関数にはどういった記述を行っているのか紹介します。
これまた簡単な内容ですが、IOポートやTimer Aの初期化を行って、割り込みをイネーブルし、最後は無限ループに入っているだけです。
このボードのCPUクロックは20MHzとなっています。TimerAをインターバルタイマーとして使用すると、TA.TMA.BIT.CKSIで選ばれた分周比でCPUクロックが分周され、次に続くカウンターで分周されたクロックを256個数えられます。
実際には0~255まで数えるのですが、TimerAは255から0に戻る時(8bitカウンターがオーバーフローする時)、割り込みがイネーブルされていた場合、割り込みを発生します。
結局20000000÷8192÷256≒9.5Hzで割り込みが発生する事となり、LEDの点滅周期は≒210msとなります。
ビルドを行い、FDTを使ってターゲットに書き込みを行います。
書き込みモードを解除して通常の動作モードに切り替えてみると、LEDがチカチカ点滅しているのを見る事が出来ると思います。
これでダサい?ソフトウエアループを使ったLEDチカチカから、割り込みを使ったスマートなLEDチカチカ(笑)にステップアップできました。
おっと、肝心な事を書き忘れていました。
__interrupt(vect=19) void INT_TimerA(void)
と記述されていますが、最初の__interruptはこの関数が割り込み処理である事を示し、続くvect=19はベクター番号を指定しています。
割り込みベクターはROMの0番地から始まる領域に書く事が決まっており、0番地がベクター番号0となっています。ベクター番号19と書く事でコンパイラは自動的にROMの書き込みアドレス(H8/Tinyの場合は19×2)を計算する事が可能となり、実際にそのアドレスの位置に割り込み関数のアドレスを埋め込みます。
後ろの型の宣言は通常のC言語の関数そのものの宣言です。
割り込みの実現の仕方について、通常の記述と(今回)、デバックモニタでの割り込みの実現方法(次回)の両方を解説します。
それでは今まで作業をしてきたsampleワークスペースを開きます。
もしHEWの画面が図の様に前回のプロジェクト名が太字になっていた場合は、始めに作成したプロジェクトを選択し、右クリックで「アクティブプロジェクトに設定」を行います。
左のペインの中の「intprg.c」をダブルクリックしてエディットWindowに「intprg.c」を開きます。
まずファイルの先頭付近、machine.hをインクルードしている直後にiodefine.hもインクルードしておきます。
#include "iodefine.h"
次に55行目付近の修正を行います。
// vector 19 Timer A Overflow
とコメントされている行の下に関数があります。今回はこのTimer Aを使って定周期で割り込みを発生させ、やっぱりLEDをチカチカさせます。
__interrupt(vect=19) void INT_TimerA(void) { IRR1.BIT.IRRTA = 0; /*割込み条件のクリア*/ IO.PDR8.BIT.B0 ^= 1; /*LEDチカチカ*/ }
これだけです。
関数の中身の最初の行は、割り込みコントローラのフラグbitをクリアしています。
次の行が実際にLEDをチカチカさせている処理です。最初にmain関数の中に記述した物をここに持って来ただけです。
次にmain関数にはどういった記述を行っているのか紹介します。
void main(void) { /*LEDが接続されているポートを出力に切り替える*/ IO.PCR8 = 0x01; /*0000 0001 ポート8入出力*/ /*TAの初期化 インターバルタイマーとして使用する*/ TA.TMA.BIT.CKSI = 0; /*CPUクロックを1/8192する*/ IENR1.BIT.IENTA = 1; /*TA割り込みを許可*/ while( 1 ) ; }
これまた簡単な内容ですが、IOポートやTimer Aの初期化を行って、割り込みをイネーブルし、最後は無限ループに入っているだけです。
このボードのCPUクロックは20MHzとなっています。TimerAをインターバルタイマーとして使用すると、TA.TMA.BIT.CKSIで選ばれた分周比でCPUクロックが分周され、次に続くカウンターで分周されたクロックを256個数えられます。
実際には0~255まで数えるのですが、TimerAは255から0に戻る時(8bitカウンターがオーバーフローする時)、割り込みがイネーブルされていた場合、割り込みを発生します。
結局20000000÷8192÷256≒9.5Hzで割り込みが発生する事となり、LEDの点滅周期は≒210msとなります。
ビルドを行い、FDTを使ってターゲットに書き込みを行います。
書き込みモードを解除して通常の動作モードに切り替えてみると、LEDがチカチカ点滅しているのを見る事が出来ると思います。
これでダサい?ソフトウエアループを使ったLEDチカチカから、割り込みを使ったスマートなLEDチカチカ(笑)にステップアップできました。
おっと、肝心な事を書き忘れていました。
__interrupt(vect=19) void INT_TimerA(void)
と記述されていますが、最初の__interruptはこの関数が割り込み処理である事を示し、続くvect=19はベクター番号を指定しています。
割り込みベクターはROMの0番地から始まる領域に書く事が決まっており、0番地がベクター番号0となっています。ベクター番号19と書く事でコンパイラは自動的にROMの書き込みアドレス(H8/Tinyの場合は19×2)を計算する事が可能となり、実際にそのアドレスの位置に割り込み関数のアドレスを埋め込みます。
後ろの型の宣言は通常のC言語の関数そのものの宣言です。
2009-06-13 00:37
nice!(0)
コメント(9)
トラックバック(0)
> 割り込みコントローラのフラグbitをクリアしています。
> これを行わないと次の割り込みが発生しなくなります
割り込みが永遠にかかり続けるのではないでしょうか。
by noritan (2009-06-13 05:36)
ごめんなさい、そうでした。
by hamayan (2009-06-13 07:26)
割り込みの受信方法には、二種類あります。
「レベル」と呼ばれる方式は、フラグの状態をサンプリングします。そのため、フラグがセットされている限り、割り込み要求が続きます。
一方、「エッジ」と呼ばれる方式は、フラグの変化をつかまえて、割り込み処理を開始します。そのため、フラグがセットされっぱなしの状態でも新たに割り込みが発生することがなく、フラグをクリアしないと次の割り込みが受付られません。
だから、「割り込みが発生しなくなる」と「割り込みが永遠にかかり続ける」のどちらの可能性もあるだろうと思います。H8はモトローラ派だから、レベルでしょうか?
ついでに、
「エッジ・アンド・レベル」という方式も使われていて、エッジとレベルの両方のイベントの論理和で割り込み処理が始まります。英語の「and」が論理和を表すというややこしい例の一つです。
この方式では、サンプリングで引っかからないパルスも受け付けることが出来ます。
釈迦に説法?
by noritan (2009-06-13 10:52)
先程試験してみましたら、LEDが点きっぱなしになります。
※おそらく点きっぱなしに見えているだけだと思われる。
これはタイマーのオーバーフローに拠る割り込みなので、ポートの様にレベルまたはエッジを明確に言えないのですが、現象はレベルと言うことになるのでしょう。
ちなみにH8/3694Fのポートにはエッジしか選択の要素がありませんです。
「エッジ・アンド・レベル」を持つタイプのマイコンはちょっと知らなかったです。
どちらかを選べると言うのはよく見かけますが。
やはりフリスクのマイコンですか?良さそうですね。
新しいマイコンはこう言った所がどんどん改良されているので、細かい技術トレンドも追いかけていないといけませんね。
by hamayan (2009-06-13 11:22)
私は仕事でH8のSLPシリーズ良く使うんですが、ポートの割り込みは
エッジでしかかけられませんが、割り込み処理終了時に信号レベルが
復帰していない場合、フラグ消去手順によって割り込みを連続発生させ
るか、次のエッジを待つか、どちらかを選ぶ事ができるので助かってます。
擬似的にレベル割り込み状態ってことでw
by 榑林 (2009-06-13 20:31)
色々使い方が有るものだと。
>割り込みを連続発生させるか、
でもこの使い方は上限を設定しないと危なくないですか?。
by hamayan (2009-06-13 20:57)
ハード仕様で、そうしないと理想的な動きにならなかったんです。
このポートだけレベル割り込みにしたいというような。
処理としてはクリアした割り込みフラグを、割り込み処理終了前に
ハード仕様を使用して信号レベルによって再度セットしているような
感じですかねぇ。
上限を設定するというのはスタックとかの話かもしれませんが
スタックは増えてないようなので問題ないようですね。
ハードが壊れてレベルが戻らなくなったらどうにも動きませんが・・・。
by 榑林 (2009-06-13 21:51)
スタックはネストしない限り問題無いでしょう。これで飛ぶようなマイコンなら困っちゃう。
> ハードが壊れてレベルが戻らなくなったらどうにも動きませんが・・・。
それです、それ。
そう言った状況も考慮して上限以上は異常と。
つまり外部の装置の状況に大きく依存し、自分まで動かなくなるのは問題にならないだろうか?と言う話です。
by hamayan (2009-06-13 22:11)
ハード異常の方でしたか。
正確には、このフラグクリア操作をポートの割り込み処理内でやって
いるわけではなく、タイマーなどの処理内でおこなっているんです。
なので割り込み処理が絶え間なく連続発生して、何もできなくなる
という事はありません。
あくまで、H8でもレベル割り込みの用に動かせますよという話で。
by 榑林 (2009-06-14 07:23)