215.HEW4でCMT割り込み(SH2-7144F)


2006/07/07 【ソフトウエア編TOPに戻る】

今回は、以前にもご紹介したことのあるCMT(コンペアマッチタイマ)による割り込みを再びご紹介しましょう。ただし、今回は開発環境としてHEW4を利用します。以前のご紹介は2002年のことで、早いもので4年も経ってしまっていました。その後ソフトウエアの開発環境の変遷などもありましたが、最近CQ出版さんの雑誌「インターフェイス」に付録されていた小型のSH2-7144Fマイコンボードと、ルネサス純正の統合開発環境HEW4(High Performance Embedded Workshop)を使って遊んでみることにします。 インターフェイスSH2-7144Fボードや割り込みなしのテストプログラムなどについては、電子回路編の「SH2(7144F)マイコンボード」のページでもご紹介していますので、先ずはそちらからご覧下さい。


215−1.割り込みプログラム事例

SH2による割り込みプログラミングについては、ソフトウエア編のSH2のコーナーで既にご紹介していました。当然SH2シリーズのマイコンなので今回のSH2-7144Fでも割り込み動作の仕組みに違いはありません。なので、今回はHEW4の環境における割り込みプログラミングの要点だけをご紹介しましょう。

今回ご紹介するテストプログラムは、MTU4チャンネルで割り込み無しのPWM動作によってサーボ制御用の信号をPE14ポートから出力させます。そして、CMT0チャンネルによるwait関数で一定の待機時間を作りサーボの首振りをさせます。同時に、CMT1チャンネル割り込み処理により0.5秒ごとのインターバルを作り、PE15ポートのLEDを点滅させます。

今回は手抜きのため、テストプログラムソースのご紹介と要点の解説だけに絞らせて頂きますので、是非下記のページなども参考としてご覧下さい。(すみません...)

211.CMTで時間つぶし(SH2-7045F)
212.CMTで割り込み処理(SH2-7045F)
213.モード1による8相PWM(SH2-7045F)

ところで、今回はHEW4のプロジェクトの中から、以下のソースに手を加えます。それぞれHEW4の画面上、左側の「Projects」ウィンドウ上から選ぶことができます。

1.TEST1.c:これは今回のテストプログラムソースです。
2.intprg.c:これは割り込み発生時にベクタテーブルから処理が移る、各割り込み要因ごとの関数名が記述されたソースです。
3.resetprg.c:これはリセット時の処理が記述されたソースです。

なお、プロジェクト内のソースのうち、利用者が自分で作るのはメインとなるプログラムソース(今回の事例ではTEST1.c)のみで、それ以外のソース類は全てHEW4がプロジェクト作成時に自動で生成してくれるものです。


今回のテストプログラムは、ここをクリックするとダウンロードできます7144test2.c
※上記のプロジェクト上はソースプログラムの名称はTEST1.cですが、ダウンロード用のプログラム名は7144test2.cとしています。


【先頭に戻る】


■TEST1.c (7144test2.c)

/**********************************************************
7144test2.c                                      2006.06.28
                                                     RIKIYA
SH2_7144F

CMT1を使った割り込みインターバルタイマー動作と
MTU4を使ったサーボ用PWM波形出力 (PE14から出力)
/*********************************************************/
#include "iodefine.h"

void main(void);
void setup(void);
void wait(unsigned short);

/* ハードウエアセットアップ******************************/
void setup(void){

// CMT設定 CMT0:wait() CMT1:割り込みインターバル

    MST.CR2.BIT._CMT = 0;        // CMTスタンバイ解除

    CMT0.CMCSR.BIT.CKS = 0;      // CMT0 CLOCK 24MHz/8
    CMT0.CMCOR = 300;            // 0.1mS/0.3333uS = 300
    CMT.CMSTR.BIT.STR0 = 0;      // CMT0 COUNT STOP

    INTC.IPRG.WORD |= 0x000F;    // CMT1 割込みLEVEL = 1
    CMT1.CMCSR.BIT.CKS = 3;      // CMT1 CLOCK 24MHz/512
    CMT1.CMCSR.BIT.CMIE = 1;     // CMT1 割り込み許可
    CMT1.CMCOR = 23441;          // 0.5S/21.33uS = 23441
    CMT.CMSTR.BIT.STR1 = 1;      // CMT1 START

// MTU4 TIOC4C PWM MODE 1 設定

    MST.CR2.BIT._MTU = 0;        // MTUスタンバイ解除

    PFC.PECRL1.BIT.PE14MD = 1;   // PE14 TIOC4Cに設定
    PFC.PEIORL.BIT.B14 = 1;      // PE14 OUTPUT MODE
    PFC.PEIORL.BIT.B15 = 1;      // PE15 OUTPUT MODE

    MTU4.TCR.BYTE = 0xA2;        // TGR4C CLEAR,24MHz/16
    MTU4.TGRC = 30000;           // 周期20mS = 0.666uS x 30000
    MTU4.TGRD = 2250;            // パルス幅1.5mS = 0.666uS x 2250
    MTU.TOER.BIT.OE4C = 1;       // TIOC4C OUTPUT ENABLE
    MTU4.TIOR.BYTE.L = 0x56;     // TCR4D → 0 , TGR4C → 1
    MTU4.TMDR.BYTE = 0xC2;       // PWM MODE1

    MTU.TSTR.BIT.CST4 = 1;       // TCNT4 START
}

/* メイン関数********************************************/
void main(void){

    setup(); // ハードウエアセットアップ

    while(1){
        wait(10000);            // 1秒待機
        MTU4.TGRD = 2700;       // パルス幅1.8mS = 0.666uS x 2700

        wait(10000);            // 1秒待機
        MTU4.TGRD = 1800;       // パルス幅1.2mS = 0.666uS x 1800
    }
}


/* CMT0時間稼ぎ********************************************
引数のmsecには、1/10000(0.1mS)秒単位で待機時間を指定する。
unsigned short型、0xffff(65535)まで。
**********************************************************/
void wait(unsigned short msec){

unsigned short i;

    CMT.CMSTR.BIT.STR0 = 1;      // CMT0 COUNT START
    for(i=0;i<msec;i++){
        do{                      // CMCNT = CMCORまで待つ(1ms)
        }while(CMT0.CMCSR.BIT.CMF == 0);
        CMT0.CMCSR.BIT.CMF = 0;  // コンペアフラグをリセット
    }
    CMT.CMSTR.BIT.STR0 = 0;      // CMT0 COUNT STOP
    return;
}

/* CMT1割り込み処理***************************************/
void int_cmt_cmt1(void){

    PE.DRL.BIT.B15 ^= 1;         // ビット出力の反転動作
    CMT1.CMCSR.BIT.CMF = 0;      // コンペアフラグをリセット
}

上記のテストプログラムは、特にご説明の必要もないと思います。コメント欄を見て頂ければ大丈夫と思います。細かなパラメータ設定の意味などについては、冒頭でご紹介している過去のSH2関連ページをご参照下さい。

main関数ではMTU4チャンネルのジェネラルレジスタTGRDの値を変更することでPWMのパルス幅を変更し、サーボの首振り角度を制御しています。そして、wait関数でTGRDを変更する期間、すなわち首振りのインターバルを決定しています。さて、main関数の中で記述されている処理はそれだけなので、PE15ポートに接続されているLEDを点滅させる処理は含まれていません。それを実行するのが、int_cmt_cmt1関数中の記述であり、これがCMT1チャンネルのコンペアマッチで発生する割り込み処理ということになります。

CMT1の割り込みでint_cmt_cmt1関数が実行されるのは、intprg.cのソースに以下のように手を加えているからです。


■intprg.c の手直し

/***********************************************************************/
/*                                                                     */
/* FILE        :intprg.c                                               */
/* DATE        :Mon, May 15, 2006                                      */
/* DESCRIPTION :Interrupt Program                                      */
/* CPU TYPE    :SH7144F                                                */
/*                                                                     */
/* This file is generated by Renesas Project Generator (Ver.4.0).      */
/*                                                                     */
/***********************************************************************/

#include <machine.h>
#include "vect.h"
#pragma section IntPRG
// 4 Illegal code
void INT_Illegal_code(void){/* sleep(); */}

【中略】

// 147 Reserved

// 148 CMT CMT1
void int_cmt_cmt1(void);
#pragma interrupt INT_CMT_CMT1

void INT_CMT_CMT1(void){
int_cmt_cmt1();
/* sleep(); */}
// 149 Reserved

// 150 Reserved

【以下略】

intprg.cのソースをずーっと306行ほど下に進むと、以下のような記述が出てきます。

void INT_CMT_CMT1(void){
/* sleep(); */}


このINT_CMT_CMT1関数は、プロジェクト内のvecttbl.cによってCMT1の割り込み発生によって呼ばれる関数として定義されています。これは初期状態は何もしない関数ですが、ここに実行したい処理を追加で記述することによって割り込み時に実行されることになります。

そこで、上記ソースの青文字部分の記述を追記しています。
void int_cmt_cmt1(void); ← 割り込み発生時にINT_CMT_CMT1関数から呼ばれる関数の宣言
#pragma interrupt INT_CMT_CMT1 
← 割り込み関数であることの宣言
void INT_CMT_CMT1(void){
int_cmt_cmt1(); ← 割り込み発生時に処理する関数の呼び出し(メインプログラム側に内容を記述)
/* sleep(); */}


これによって、CMT1のコンペアマッチ割り込みが発生するとint_cmt_cmt1();関数が実行されます。この関数は前項テストプログラムの割り込み処理部に記述した関数名になります。


■resetprg.c の手直し

/***********************************************************************/
/*                                                                     */
/* FILE        :resetprg.c                                             */
/* DATE        :Mon, May 15, 2006                                      */
/* DESCRIPTION :Reset Program                                          */
/* CPU TYPE    :SH7144F                                                */
/*                                                                     */
/* This file is generated by Renesas Project Generator (Ver.4.0).      */
/*                                                                     */
/***********************************************************************/

#include <machine.h>
#include <_h_c_lib.h>
//#include <stddef.h> // Remove the comment when you use errno
//#include <stdlib.h> // Remove the comment when you use rand()
#include "typedefine.h"
#include "stacksct.h"

//#define SR_Init 0x000000F0
#define SR_Init 0x00000000


#define INT_OFFSET 0x10


【以下略】

resetprg.cのソース冒頭の部分に上記のような記述があり、初期状態として #define SR_Init 0x000000F0の記述があります。これはCPUの基本動作を決定するSR(ステータスレジスタ)の初期値を設定しているものですが、これを上記の青色の記述のように修正して、#define SR_Init 0x00000000としてしまいます。 F0 に書き換えることによって割り込みマスクレベルを0に設定し、1以上の割り込み優先レベルに設定されている割り込みであれば実行を許可するようにしています。

【先頭に戻る】



さて、今回はHEW4を使った開発環境での割り込みプログラミングの事例についてご紹介してみました。開発環境によってプログラミングの具体的な方法も変わってきます。今回の事例を参考にして頂けると、他の機能を使った割り込みプログラミングにも踏み込めるのかな?と思っています。

 

【ソフトウエア編TOPに戻る】


【表紙に戻る】