忍者ブログ

Fグループ電子工作講座

秋月電子SH7125ボードで始めるマイコン開発

外部入力割込み(IRQ)の設定 基本編

割り込みオブ割り込み、外部割込み(IRQInterrupt ReQuest)の設定を行います。
割り込みを使う理由と概念はこちら:割り込み処理とは
外部割込みに設定した端子に入力が加わると、メイン処理はそっちのけで特定の関数を実行します。
高速で出力されるパルス数のカウントやパルスの周期測定などに用います。
私は超音波の発信から受信までの時間測定に使用しました。
また、音の様に一瞬だけ出力信号も検出できることから、100均で売ってるタイマーのブザーから信号を取り出す時にも使用しています。

端子の選定

外部入力割り込み可能な端子はIRQ表記があります
PA2:IRQ0
PA3:IRQ1
PA4:IRQ2
PA5:IRQ3
このうちPA3PA4はシリアル通信で使っています。
プログラムの書き込みにもPA3PA4を使用しRS232C用の電圧変換ICも接続されているので熟知するまでは他の目的では使用するのはやめた方が良いでしょう。
従って、使用可能なのはPA2PA5の2つです。


初期化設定

ソースファイル「intIRQ.c」を作り割り込み処理に必要なプログラムを書いていきます。

int _intrupt_f;
static unsigned long _intrupt_count[4];

void init_IRQ(void)
{
    int i=0;

    PFC.PACRL2.BIT.PA5MD=7;    //PA5を外部割込みに設定
    PFC.PACRL1.BIT.PA2MD=3;    //PA2を外部割込みに設定

    INTC.IRQCR.BIT.IRQ0S=2;    //立上り:2 立下り:1
    INTC.IRQCR.BIT.IRQ3S=2;    //立上り:2 立下り:1

    //    SCIの割り込みレベル(優先順位)を設定
    INTC.IPRA.BIT._IRQ0 = 0x9;    // ※(0x0:最低~0xF:最高)
    INTC.IPRA.BIT._IRQ3 = 0x8;    // ※(0x0:最低~0xF:最高)

    _intrupt_f=0;

    for(i=0;i<4;i++){
        _intrupt_count[i]=0;    // カウント値を初期化
    }

    INTC.IRQSR.BIT.IRQ0F=0;        // IRQ割込フラグをクリア
    INTC.IRQSR.BIT.IRQ3F=0;
}

IRQCR:IRQコントロールレジスタ
割り込みの条件(立ち上がり検出、立下り検出等)を設定します。
信号がOFFからONに変わることを立ち上がり、ONからOFFに変わることを立下りと呼びます。

IRQSR:IRQステータスレジスタ
IRQ端子の割り込み許可と状態取得をします。

IRQ0FIRQ3F:それぞれ0にすると割り込みが機能するようになります。

ついでに割り込みが発生したか分かるように_intrupt_f、割り込みが発生した回数が分かるように_intrupt_count_0_intrupt_count_3を作成しておきます。

割り込み動作の有効化

PWMの時と同様に初期状態では割り込みを受け付けないように設定されているので、割り込みを有効化しておきます。
resetprg.c
の36行目付近
#define SR_Init    0x000000F0

#define SR_Init    0x00000000
へ変更します。

外部入力割込み関数

IRQ0による割り込みIRQ0はベクタ番号64にて実行されます。
IRQ3による割り込みIRQ3はベクタ番号67にて実行されます。
これらはそれぞれvecttbl.cに記述されており、最終的にはintprg.cINT_IRQ0INT_IRQ3が実行されます。

intprg.cでINT_IRQ0INT_IRQ3を検索すると関数の実体が見つかりますが、
// 64 Interrupt IRQ0
void INT_IRQ0(void){/* sleep(); */}

// 67 Interrupt IRQ0
void INT_IRQ3(void){/* sleep(); */}

となっており、相変わらず関数の中身はコメントしかないので結局何も実行されません
とりあえず割り込みが発生した回数をカウントする関数を作成します。

//IRQ0割り込み
void IRQ_INT_IRQ0(void)
{
    _intrupt_f|=1;
    _intrupt_count[0]++;
    INTC.IRQSR.BIT.IRQ0F=0;
}

//IRQ3割り込み
void IRQ_INT_IRQ3(void)
{
    _intrupt_f|=8;
    _intrupt_count[3]++;
    INTC.IRQSR.BIT.IRQ3F=0;
}

この割り込み関数はとてもシンプルです。
立ち上がりを検出した瞬間にINT_IRQ0が実行される、ただそれだけです。
次の立ち上がりを検出するためにIRQ0Fをもう一度0にします。
これでまた次の立ち上がりを検出できます。

忘れないうちにintprg.cのINT_IRQ0INT_IRQ3を編集しておきます。
void INT_IRQ0(void){IRQ_INT_IRQ0();}
void INT_IRQ3(void){IRQ_INT_IRQ3();}

情報取得関数

最後に_intrupt_fと_intrupt_countを別のファイルからアクセスできるように関数を作成します。
//割り込み検出を取得する
int get_intrupt_f(void){
    return     _intrupt_f;
}
//割り込み検出を初期化する
int clr_intrupt_f(void){
    _intrupt_f=0;
}

//割り込み回数を取得する
unsigned long get_irq_cnt(int port){
    if(port<0||port>3)
        return 0;
    return _intrupt_count[port];
}

ヘッダファイル

ヘッダファイル「intIRQ.h」は関数のプロトタイプ宣言を書いておきます。

#if !defined _INTIRQ_H_    //読み込まれていない(_INTIRQ_H_が定義されていない)とき読み込む

#define _INTIRQ_H_ 0
void init_IRQ(void);
void IRQ_INT_IRQ0(void);
void IRQ_INT_IRQ3(void);
int get_intrupt_f(void);
int clr_intrupt_f(void);
unsigned long get_irq_cnt(int port);
#endif

作成したソースファイル「intIRQ.c」とヘッダファイル「intIRQ.h」はプロジェクトに追加しておきます。


メインプログラム

シリアル通信を使って割り込みの結果を確認してみます。
今回作成した「intIRQ.c」「intIRQ.h」の他に汎用IO設定(io_setup.cio_setup.h)タイマー処理一式(intCMT.cintCMT.h)とシリアル通信一式(intSCI.cintSCI.h)を使用します。

メインプログラム
#include "iodefine.h"
#include <stdio.h>
#include "io_setup.h"
#include "intCMT.h"
#include "intSCI.h"
#include "intIRQ.h"

void main(void){
    //変数定義
    char trans_buf[100];
    unsigned long timer;    //ループ制御用タイマー
    int i;

    //各機能の初期化
    hardware_setup();    //汎用IOの初期化
    init_CMT0(1);        //タイマーの初期化
    init_SCI1();        //シリアル通信の初期化
    init_IRQ();

    timer=getsystime();    //現在時刻の取得(intCMT)

    write_sci1("sh7125 connect\n");

    while(1){    //無限ループ開始
        if(timer<getsystime()){            //タイマー設定時刻を経過
            timer=getsystime()+50;        //50ms後に設定
            if(get_intrupt_f()){        //外部割込みが発生していた
                clr_intrupt_f();        //フラグを解除
                sprintf(trans_buf,"%d,%d\n",get_irq_cnt(0),get_irq_cnt(3));    //割り込み回数を文字列に格納
                write_sci1(trans_buf);    //通信で出力
            }//intrupt_f
        }//50ms
    }//end while
}

書き込んで実行してみます。
シリアル通信受信はいつものTMZあたりで。
起動時は「sh7125 connect」と数字が幾つかが表示され、あとはPA2,PA5当たりを触ると指をアンテナにして割り込みが発生しカウント数がポロポロ表示されるはずです。

これで高速で入力される信号をカウントすることができますが、次回はもう少し機能を拡張します。
PR

コメント

プロフィール

HN:
ぼんどF博士
性別:
男性
自己紹介:

最新コメント