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

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

[横田一弘 埼玉県立新座総合技術高等学校 教諭,@IT MONOist]

 それでは、今度はH8/3664に搭載されているタイマVを使って、ダイナミック点灯させてみましょう。

 タイマVには、タイマカウンタが設定した値になったときにイベントを発生させる「コンペアマッチ機能」があります。今回はこの機能を使って、1m秒置きに割り込みを発生させ、それにより2つの7セグメントLEDをダイナミック点灯させます。


 1m秒周期のイベント発生に必要なハードウェア構成を図2に示します。

タイマVによるコンペアマッチA割り込み 図2 タイマVによるコンペアマッチA割り込み

 まず16MHzのシステムクロックΦを、「プリスケーラ(分周器)」によって周波数を下げます。タイマVでは、Φ/4、Φ/8、Φ/16、Φ/32、Φ/64、Φ/128から選択することが可能です。

 8ビットのタイマカウンタV(TCNTV)は、分周されたクロックによってカウントアップされます。

 タイマVのコンペアマッチ機能が選択されていると、比較回路によってTCNTVとタイムコンスタントレジスタA(TCORA)の値が比較されます。ここで、TCNTVとTCORAの値が一致した次のクロック入力で、TCNTVを0クリアし、コンペアマッチフラグA(CMFA)を「1」にします。これを割り込み要因とすることによって、周期的に割り込みを発生させることができるのです。

 それでは、16MHzから1m秒周期の割り込みを発生するには、どのようにタイマVを使うのでしょうか。次の2通りの設定が考えられます。

[その1]

  • プリスケーラをΦ/128に設定。タイマカウンタに125kHzのクロックを入力
  • コンスタントレジスタの値を「124」とし、「124」の次のクロックで割り込み発生

[その2]

  • プリスケーラをΦ/64に設定。タイマカウンタに250kHzのクロックを入力
  • コンスタントレジスタを「249」に設定。「249」の次のクロックで割り込み発生

 以上の解説を基に、C言語プログラムを考えます。

 タイマVの制御レジスタには、「タイマコントロールレジスタV0(TCRV0)(図3)」「タイマコントロールレジスタV1(TCRV1)(図4)」「タイマコントロール/ステータスレジスタV(TCSRV)(図5)」があります。

タイマコントロールレジスタV0 図3 タイマコントロールレジスタV0(TCRV0)
タイマコントロールレジスタV1 図4 タイマコントロールレジスタV1(TCRV1)
タイマコントロール/ステータスレジスタV 図5 タイマコントロール/ステータスレジスタV(TCSRV)

 [その1]の設定で1秒間隔の周期イベントを発生させるために、最初にタイマコンスタントレジスタA(TCORA)に「124」を代入します。

    TCORA = 124; 

 タイマVのパルス出力機能は使わず、コンペアマッチAによるタイマカウンタのクリア、コンペアマッチAによる割り込み許可、タイマクロックをΦ/128にするのに、

    TCRV1 = 0xe3;
    TCRV0 = 0x4b; 

とします。

 タイマVは、TCRV0の下位3ビットが「0」以外になると、TCNTVにクロック投入されるようになっています。そのため、TCRV0を最後に設定しタイマを起動させます。

 タイマV割り込み処理ルーチンは、int_timv関数です。

 ここでは、コンペアマッチAイベントでダイナミック点灯を行います。

 タイマVの割り込みは、「コンペアマッチA」「コンペアマッチB」「オーバーフロー」の3つの要因で引き起こされます。そのため、割り込み処理ルーチンでは、

    if (TCSRV & CMFA) {
        /* コンペアマッチA割り込み処理 */
    }
    else if (TCSRV & CMFB) {
        /* コンペアマッチB割り込み処理 */
    }
    else if (TCSRV & OVF) {
        /* オーバーフロー割り込み処理 */
    } 

のように、割り込み要因に対応した選択処理を行います。

 プログラムは次のようになります(ソースコード2)。

/* 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 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
 
void int_tima(void) __attribute__((interrupt_handler));
void int_timv(void) __attribute__((interrupt_handler));
 
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;
}
 
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;
} 
ソースコード2

  • ソースコード2のダウンロード(7seg1.lzh

プログラム分割で処理を絞れ!!

photo

タイマVを使ったら、ダイナミック点灯がループじゃなくなった。


photo

タイマで周期的に処理するのは、制御プログラミングの基本の形よ。


あと、割り込み処理ルーチンでは下手にループさせないこと! これ重要よ。


photo

えっ、何で?


photo

だって、割り込みで長い処理を行うとCPUを占有しちゃうでしょ。


割り込み処理は、さっさと済ませること。


photo

ふむふむ。『ちょっとだけよー』ってことか!


よし! これを『割り込みチラリズムの法則』と命名しよう。


photo

……。


じゃ、次のワタシのプログラムを見て!


photo

無視か……。



Copyright © ITmedia, Inc. All Rights Reserved.