2015年7月29日

1.簡単なOSを作成する ~タイマー割込み編~

前回、~LED点灯編~を実施しました。

p4ddr = 0xffになっていた理由についてはライト専用レジスタで、リードは無効(リードした場合1が読みだされる)という事でした(笑) 。すみません。。。

仕切りなおし、今回は~タイマー割込み編~になります。
タイマー割込みでLED点滅させるプログラムを作っていきましょう。

では、1secタイマーでLEDをON/OFFできるように作ってみよう。




まず、1secタイマーを作るためには8bit/16bitタイマーどちらを使うか?どのように使うか?

8bitタイマーの場合、タイマーカウンタが8bitの為、255がMAXになる。
8bitタイマーのカウントクロックは分周比8/64/8192の3種類が存在する。

H8-3069Fの動作周波数は20MHzなので、各分周比で割ってやると、
1秒間にカウントアップする回数が算出される。

この1秒間にカウントアップする回数が、TCNTで表現される整数範囲以下でなければ、
カウントできない。分周比8/64は溢れてしまう。分周比8192は割り切れない為、使えない。

なので、16bitタイマーを使用する。
16bitタイマーの分周比は1/2/4/8が存在する。

1秒間にカウントアップする回数は下記の通り。
ここでもTCNTの整数範囲を溢れてしまうので、2段階カウントアップ方式を使って
1secタイマーを実現する。

分周比:8/TCNT0:10000/TCNT1:250

TCNT0が10000になった時にもう一つのタイマーをスタートさせ、
TCNT1が250になった時に割り込みを発生させる事とする。

イメージ的には分周、分周していくイメージになる。

20MHz = 20000000 Hz /8 = 2500000 Hz

2500000 Hz / 10000 / 250 = 1Hz




下記に考え方と、フローチャートを作ってみたので、プログラミングしてみる。

こんな感じ。
main.cmain.c
int main(void)
{
    serial_init(SERIAL_DEFAULT_DEVICE);

    puts("-----------------Led1 and 2 is Light start!!\n");   
    /* p4ddr(P46 and P47) output setting 0x0c = 1100 0000  */
    /* p4dr (P46 and P47) output         0x0c = 1100 0000  */
   
    P4DDR.BYTE        = 0;
    P4DDR.BIT.B6    = ENABLE;
    P4DDR.BIT.B7    = ENABLE;

    P4DR.BYTE        = DISABLE;
   
    P4DR.BIT.B6     = LED_ON;
    P4DR.BIT.B7     = LED_OFF;
   
    /**
     * カウントクロック設定 φ/8
     */
    T_16TCR0.BIT.TPSC = 0x03;
    T_16TCR1.BIT.TPSC = 0x03;
   
    /**
     * カウンタクリア要因の選択
     */
    T_16TCR0.BIT.CCLR = 0x01; // GRA
    T_16TCR1.BIT.CCLR = 0x01; // GRA
   
    /**
     * アウトプットコンペアレジスタの選択
     */
    T_TIOR0.BIT.IOA = 0x02; // GRA コンペアマッチ 1出力
    T_TIOR1.BIT.IOA = 0x02; // GRA コンペアマッチ 1出力
   
    /**
     * IMF フラグ割込 要求許可
     */
    T_TISRA.BIT.IMIE = 0x01; //割込 要求許可
    T_TISRB.BIT.IMIE = 0x01; //割込 要求許可
   
    /**
     * 周期設定
     */
    T_GRA0_H.BYTE = 0x2710; // 10000
    T_GRA1_H.BYTE = 0x00FA; //   250
   
    /**
     * TIMER START
     */
    T_TSTR.BYTE = 0x01; // 16TCNT0 Start
   
    while(1)
    {
        puts("T_16TCNT0:");   
            putxval(T_16TCNT0_H.BYTE,2);
            putxval(T_16TCNT0_L.BYTE,2);
        puts("\n");   

        puts("T_16TCNT1:");   
            putxval(T_16TCNT1_H.BYTE,2);
            putxval(T_16TCNT1_L.BYTE,2);
        puts("\n");   

        puts("T_GRA0:");
            putxval(T_GRA0_H.BYTE,2);
            putxval(T_GRA0_L.BYTE,2);
        puts("\n");   

        puts("T_GRA1:");
            putxval(T_GRA1_H.BYTE,2);
            putxval(T_GRA1_L.BYTE,2);
        puts("\n");   

        puts("T_TISRA IMF:");
            putxval(T_TISRA.BIT.IMF,2);
        puts("\n");   

        puts("T_TISRB IMF:");
            putxval(T_TISRB.BIT.IMF,2);
        puts("\n");   

        if(T_TISRA.BIT.IMF == 0x01)
        {
            P4DR.BIT.B6     = LED_ON;
            P4DR.BIT.B7     = LED_ON;
            break;
           
        }else{

            P4DR.BIT.B6     =~ P4DR.BIT.B6;
            P4DR.BIT.B7     =~ P4DR.BIT.B7;

        }
       
    }
   
  return 0;   
}

<実行結果>

-----------------Led1 and 2 is Light start!!
T_16TCNT0:10c7
T_16TCNT1:0000
T_GRA0:10ff
T_GRA1:faff
T_TISRA IMF:01
T_TISRB IMF:00

GRA0:0x10FF = dec4351になっている。期待値は0x2710 = dec10000なのに。
とりあえず、本日はここまで。次回デバッグです。
ひとつひとうみていこう。

0 件のコメント: