周期イベントでLEDのダイナミック点灯を!:イチから作って丸ごと学ぶ! H8マイコン道(11)(1/3 ページ)
タイマ割り込みをテーマに、7セグメントLEDのダイナミック点灯を行う。また、プログラムのモジュール化についても解説する。
前回のあらすじ
――前回は、晴子さんの指導の下、H8マイコンの周辺機能の1つ「タイマA」を使って、1秒間隔で「0」から「9」の数字を7セグメントLEDに巡回表示するプログラムの作成を行いました。制御プログラムに欠かせない「割り込み処理」についてマスターした健一君ですが、またまた晴子さんから難題が出されました……。(前回へ)
さて、午後の授業も終わり、そろそろ健一君が来るころですね。
ダイナミック点灯って何だ
ここは健一君が所属する大学のサークル部屋。また、いつもの足音が聞こえてきました……。
こんにちは!! 晴子さん。
あら、健一君。
今日はずいぶん元気がいいのね。
ということは、今度こそワタシの宿題はバッチリよね〜?
へへっ。
まあ、これを見てよ!(画像1)
スゴーイ!
あまり期待してなかったけど、健一君もやればできるじゃないの。
ムッ!
何もそんなふうにいわなくてもいいじゃないか!
ゴメン、ゴメン。
それじゃあ、じっくりと見せてもらおうじゃないの。健一君の実力とやらを!
――健一君、とうとう晴子さんの宿題をやってのけました。連載第8回「ポートを使いこなし、いざ制御プログラミングの世界へ」でお伝えしましたが、H8Tiny-USBの7セグメントLED表示回路は「ダイナミック・ドライブ」と呼ばれるタイプのものです。それでは、健一君のプログラムを検証してみましょう。
晴子さんからの宿題(4)
0秒から59秒までカウントするプログラムを作ってね。左右2つの7セグメントLEDを使って、2けた同時に表示できないとダメよ!!
前回の晴子さんの宿題(4)のポイントは「いかにして、2けた表示させるか」です。それでは最初にH8Tiny-USBのハードウェアを調べてみましょう。
図1に、H8Tiny-USBの7セグメントLED表示回路を示します。2つの7セグメントLEDはポート5とポート8に接続されていますが、ポート5は表示させる7セグメントLEDを選択するために、ポート8は7セグメントLEDに何を表示させるかを指定するために使います。
では、健一君が自信満々で作ってきたプログラムを見てみましょう(ソースコード1)。
/* 1秒間隔でカウント表示する。 * */ #define PCR5 (*((volatile unsigned char *)0xffe8)) #define PDR5 (*((volatile unsigned char *)0xffd8)) #define PCR8 (*((volatile unsigned char *)0xffeb)) #define PDR8 (*((volatile unsigned char *)0xffdb)) #define TMA (*(volatile unsigned char *)0xffa6) #define IRR1 (*(volatile unsigned char *)0xfff6) #define IENR1 (*(volatile unsigned char *)0xfff4) #define IRRTA 0x40 #define IENTA 0x40 #define LED1 0x01 #define LED2 0x02 void int_tima(void) __attribute__((interrupt_handler)); void wait(long); int count1, count10; int main(void) { unsigned char LED[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; asm("orc.b #0xc0,ccr"); /* 割り込み禁止 */ TMA = 0x18; IRR1 &= ~IRRTA; IENR1 |= IENTA; asm("andc.b #0x3f,ccr"); /* 割り込み許可 */ PCR5 = 0x03; PCR8 = 0xff; count1 = 0; count10 = 0; for (;;) { PDR5 = ~LED2; PDR8 = LED[count1]; wait(1000); PDR5 = ~LED1; PDR8 = LED[count10]; wait(1000); } return 0; } void int_tima(void) { IRR1 &= ~IRRTA; if (count1 < 9) count1++; else { count1 = 0; if (count10 < 9) count10++; else count10 = 0; } } void wait(long times) { while (times--); }
- ソースコード1のダウンロード(7seg0.lzh)
1秒間隔のカウントは、前回紹介したタイマA割り込みによって処理されます。int_tima関数がその割り込み処理ルーチンで、ここでは変数count1を1の位に、変数count10を10の位にカウントアップしています。
7セグメントLEDのダイナミック表示は、main関数で処理しています。main関数のfor文の本体では、先にLED2を選択して1の位を表示させ、次にLED1を選択して10の位を表示させています。以上の繰り返しによって、2つの7セグメントLEDが同時に光っているように見えるのです。ちなみに、wait関数の引数を大きくし過ぎると、表示がちらついてしまいます。
タイマVで周期イベントを引き起こせ
あら、健一君にしては上出来だわ。
えっへん!
ボクだってこのくらいできるんだから。
ウフフッ。そうね。
じゃあ、ダイナミック点灯もタイマを使ってやってよ。
うはっ! 何だか急に頭が痛くなってきた。
早退しようかな……。
キッ!!
Copyright © ITmedia, Inc. All Rights Reserved.