周期イベントでLEDのダイナミック点灯を!イチから作って丸ごと学ぶ! H8マイコン道(11)(1/3 ページ)

タイマ割り込みをテーマに、7セグメントLEDのダイナミック点灯を行う。また、プログラムのモジュール化についても解説する。

» 2010年02月25日 00時00分 公開

前回のあらすじ

――前回は、晴子さんの指導の下、H8マイコンの周辺機能の1つ「タイマA」を使って、1秒間隔で「0」から「9」の数字を7セグメントLEDに巡回表示するプログラムの作成を行いました。制御プログラムに欠かせない「割り込み処理」についてマスターした健一君ですが、またまた晴子さんから難題が出されました……。前回へ

 さて、午後の授業も終わり、そろそろ健一君が来るころですね。


本連載の登場人物

佐藤 健一(さとう けんいち)
電子工学を専攻している大学2年生。ロボットサークルに参加している。最近、やっと電子工作ができるようになったが……。

岡野 晴子(おかの はるこ)
健一君が所属するサークルの先輩。組み込みソフトウェアを研究しており、サークルでも中心的な存在。活発で頼れる(健一君あこがれの)女性。



※注:本連載では、筆者が実際にH8Tiny-USBを制作し、動作確認を行った内容を掲載していますが、読者個人で作成したH8Tiny-USBの動作保証や、H8Tiny-USBを使用したことによる、損害・損失については一切保証できません。すべての作業は自己責任で行ってください。よろしくお願いします。


ダイナミック点灯って何だ

ここは健一君が所属する大学のサークル部屋。また、いつもの足音が聞こえてきました……。

photo

こんにちは!! 晴子さん。


photo

あら、健一君。


今日はずいぶん元気がいいのね。


ということは、今度こそワタシの宿題はバッチリよね〜?


photo

へへっ。


まあ、これを見てよ!(画像1)



これが健一君の成果だ! 画像1 これが健一君の成果だ!

photo

スゴーイ!


あまり期待してなかったけど、健一君もやればできるじゃないの。


photo

ムッ!


何もそんなふうにいわなくてもいいじゃないか!


photo

ゴメン、ゴメン。


それじゃあ、じっくりと見せてもらおうじゃないの。健一君の実力とやらを!



――健一君、とうとう晴子さんの宿題をやってのけました。連載第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に何を表示させるかを指定するために使います。

7セグメントLED表示回路 図1 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 健一君が作ったプログラム

  • ソースコード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で周期イベントを引き起こせ

photo

あら、健一君にしては上出来だわ。


photo

えっへん!


ボクだってこのくらいできるんだから。


photo

ウフフッ。そうね。


じゃあ、ダイナミック点灯もタイマを使ってやってよ。


photo

うはっ! 何だか急に頭が痛くなってきた。


早退しようかな……。


photo

キッ!!



       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.