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

» 2010年02月25日 00時00分 公開
前のページへ 1|2|3       

――大規模で複雑なプログラムを作るとき、すべての処理を1つのファイルに記述するこはありません。プログラムを機能によって分類し、複数のモジュールからプログラムが構成されるように作成します。それではプログラムをモジュール化してみましょう。

 晴子さんは、プログラムを「main.c」「h8tiny.h」「interrupu.c」の3つに分けました(晴子さんのプログラム「7seg2.lzh」)。それでは個々のプログラムを解説しましょう。

main.c

 main.cには、main関数のみが記述されています。ここではH8マイコンの周辺機能を初期化し、さらにカウント変数をクリアして無限ループに入ります。仕事はすべて割り込みで行われるからです。

 いままで紹介したプログラムでは、プログラムの先頭部分でレジスタの宣言などを行っていましたが、main.cでは、

#include “h8tiny.h” 

と1行で済ませています。

 #includeはソースを差し込む指定で、ここでh8tiny.hファイルの内容が差し込まれるのです。

#include “h8tiny.h”
 
int count1, count10;
 
int main(void)
{
    asm("orc.b #0xc0,ccr");        /* 割り込み禁止 */
    /* タイマAの初期化 */
    TMA = 0x18;
    IRR1 &= ~IRRTA;
    IENR1 |= IENTA;
 
    /*  タイマVの初期化  */
    TCSRV = 0;
    TCORA = 124;
    TCRV1 = 0xe3;
    TCRV0 = 0x4b;
 
    /*  ポートの初期化  */
    PCR5 = 0x03;
    PCR8 = 0xff;
    asm("andc.b #0x3f,ccr");    /* 割り込み許可 */
 
    count1 = 0;
    count10 = 0;
    for (;;) ;
    return 0;
} 
main.c

h8tiny.h

 それでは、h8tiny.hを見てみましょう。

 h8tiny.hは、次のようにレジスタの宣言などが含まれています。このようにレジスタ宣言をヘッダファイルで定義しておけば、後はインクルードするだけで共通に利用できます。

#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 TCRV0 (*(volatile unsigned char *)0xffa0)
#define TCSRV (*(volatile unsigned char *)0xffa1)
#define TCORA (*(volatile unsigned char *)0xffa2)
#define TCORB (*(volatile unsigned char *)0xffa3)
#define TCRV1 (*(volatile unsigned char *)0xffa5)
 
#define IRRTA   0x40
#define IENTA   0x40
#define CMFA    0x40
 
#define LED1    0x01
#define LED2    0x02 
h8tiny.h

interrupu.c

 interrupu.cには、割り込みベクタが書かれています。ここでもH8マイコンの周辺機能を使いますが、レジスタの定義はh8tiny.hをインクルードするだけです。

 カウント変数count1とcount10の宣言で、

extern int count1, count10; 

と、extern宣言していますが、これは外部の変数を使うという意味です。main.cにある変数count1とcount10を使うので、interrupu.cではextern宣言しているわけです。

#include "h8tiny.h"
 
void int_tima(void) __attribute__((interrupt_handler));
void int_timv(void) __attribute__((interrupt_handler));
 
extern int count1, count10;
 
void int_tima(void)
{
    IRR1 &= ~IRRTA;
    if (count1 < 9)
        count1++;
    else {
        count1 = 0;
        if (count10 < 9)
            count10++;
        else
            count10 = 0;
    }
}
 
void int_timv(void)
{
    static unsigned char LED[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    static int tagle = 0;
 
    if (TCSRV & CMFA) {
        TCSRV &= ~CMFA;
        if (tagle) {
            PDR5 = ~LED2;
            PDR8 = LED[count1];
            tagle = 0;
        }
        else {
            PDR5 = ~LED1;
            PDR8 = LED[count10];
            tagle = 1;
        }
    }
    else
        TCSRV = 0;
} 
interrupu.c

 最後に、プログラムの実行方法を説明します。

 まず、スタートアップ・ルーチンをアセンブルします。

$ h8300-elf-gcc -c crt0.s 

 そして、main.cをコンパイルします。

$ h8300-elf-gcc -c -mh -mn main.c 

 さらに、interrupt.cをコンパイルします。

$ h8300-elf-gcc -c -mh -mn interrupt.c 

 最後にリンクして、実行ファイルを作りましょう。

$ h8300-elf-gcc -o swcount.bin -T 3664.x -nostdlib -mh -mn crt0.o main.o interrupt.o 

 いかがでしょうか。ソースファイルの数だけコンパイルし、最後にリンクすればよいのです。意外と簡単ですよね。

コラム:多重割り込みとH8/3664

割り込み処理の途中で、ほかの割り込み処理を行うことを「多重割り込み」と呼びます。プログラムに複数の割り込み処理ルーチンがあるときは、多重割り込みの配慮が必要になります。

今回紹介したプログラムでは、タイマAとタイマVの2つの割り込みが発生します。その動作を詳しく調べてみましょう。

ルネサス テクノロジの「H8/3664グループ ハードウェアマニュアル」に、H8/3664の割り込みシーケンスが書かれています。これを要約すると、

(1)割り込み要求が発生する。
(2)コンディションコードレジスタ(CCR)のIビットが「1」の間、割り込みは保留される。
(3)CCRのIビットが「0」ならば、CPUは実行中の命令を実行した後、割り込み処理を開始する。まず、プログラムカウンタ(PC)とCCRをスタックに退避する。
(4)CCRのIビットを「1」にセットする。
(5)割り込み要求に対応するベクタアドレスを生成し、PCにセットし割り込み処理を開始する。

以上のように、CCRのIビットが「1」のときCPUは割り込みを保留します。つまり、H8/3664では、割り込み処理の途中で発生する割り込みは保留され、割り込み処理が終了した後、受け付けられることになります。H8/3664では多重割り込みを推奨していないようです。



photo

なるほど、割り込みも奥が深いなぁ。


photo

そうね。


制御のプログラムってイベント処理が多いから。


photo

ところで晴子さん。


宿題がちゃんとできたご褒美(デート)、いつにしましょうか?


photo

えっ、ワタシいつそんな約束したかしら。


あっ、いけない。今日買い物頼まれているんだったわ。


健一君にはいつもどおり宿題を用意しといたから、ワタシ帰るね。


バイバーイ。


photo

えっー!!



晴子さんからの宿題(5)

H8Tiny-USBから通信で「Hello world」を送ってね。パソコンに通信ソフトをインストールしないとダメよ!!






 前回に引き続き、タイマ割り込みをテーマに、7セグメントLEDのダイナミック点灯を行いました。これでH8Tiny-USBのハードウェアをすべて使いこなしたことに……。といいたいところですが、まだ「シリアル通信」が残っていますね。

 H8Tiny-USBとパソコンをつなぐUSBケーブルは、電源の供給、プログラムのダウンロードのほか、H8Tiny-USBとの通信に使うことができます。というわけで、次回(ついに完結!!)は、シリアル通信によるprintf関数を作ってみましょう。お楽しみに!(次回に続く)


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.