home1.gif

next1.gif
back1.gif
 

Interrupt (IRQ)

 

基礎編
 PORT入出力
 シリアル通信
 タイマー機能
 A/Dコンバータ
 D/Aコンバータ
 外部割り込み
 液晶モニタ

応用編
 アウトプットコンペア
 インプットキャプチャ
 SRAM増設

Tips
 関数集
 シリアルEEPROM
 20桁×4行液晶モニタ
  (SC2004C)
 加速度センサを読む

外部割り込み

 イントロダクション
 外部割り込みと聞いてピンと来なければ、IRQと言ったら分かる人も居るでしょうか? つまり、H8のLSI以外からの入力(スイッチ入力でもセンサ入力でも何でも良い)があると、即座に現在進行中のプログラムを一時停止して割り込み処理を行うという物です。IRQの割り込みは比較的優先順位が高いので、よほどクリティカルな作業をしているときでもなければ強制的に割り込み処理が実行されます。

 いったいどういう局面で使用されるか。たとえば、「そんな頻繁に起こるわけではないが、起こったときには最優先でこういう処理をして欲しい」とか、「どのタイミングで来るか分からないが、必要なときにはすぐにそのルーチンを呼び出したい」というような場合が考えられます。つまり、インプットキャプチャで周期を計るには周期不定だし、mainルーチンで毎回チェックするほどの周期でくるわけでもない場合、もしかしたら電源が落ちるまでの間に一度も来ないかも知れない処理、そういう処理に向いていると言えます。もちろん、何らかのセンサ情報を取得するためのトリガとしても使えますが、そういうときはインプットキャプチャの方が向いていると言えます。

 外部割り込みを使う
 割り込みを使うと言うことは、すなわちmain.c以外に3つのファイルを編集すると言うことですね。このファイルをダウンロードしてください。
 resetprg.cに関してはもう省略します。hwsetup.cは「IRQ」と名前の付く部分に着目していけば自ずと正解になるわけですが、こんな感じになります。

hwsetup.c

    void HardwareSetup()
    {
      SYSCR.BYTE = 0;
      SYSCR.BIT.SSBY  = 1;
      SYSCR.BIT.STS   = 7;
      SYSCR.BIT.UE    = 1;
      SYSCR.BIT.NMIEG = 1;
      SYSCR.BIT.RAME  = 1;

      INTC.ISCR.BYTE = 0;
      INTC.ISCR.BIT.IRQ5SC = 1;
      INTC.ISCR.BIT.IRQ4SC = 1;
      INTC.ISCR.BIT.IRQ3SC = 1;
      INTC.ISCR.BIT.IRQ2SC = 1;
      INTC.ISCR.BIT.IRQ1SC = 1;
      INTC.ISCR.BIT.IRQ0SC = 1;

      INTC.IER.BYTE = 0;
      INTC.IER.BIT.IRQ5E = 1;
      INTC.IER.BIT.IRQ4E = 1;
      INTC.IER.BIT.IRQ3E = 1;
      INTC.IER.BIT.IRQ2E = 1;
      INTC.IER.BIT.IRQ1E = 1;
      INTC.IER.BIT.IRQ0E = 1;

      INTC.ISR.BYTE = 0;
      INTC.ISR.BIT.IRQ5F = 1;
      INTC.ISR.BIT.IRQ4F = 1;
      INTC.ISR.BIT.IRQ3F = 1;
      INTC.ISR.BIT.IRQ2F = 1;
      INTC.ISR.BIT.IRQ1F = 1;
      INTC.ISR.BIT.IRQ0F = 1;

      INTC.IPRA.BYTE = 0;
      INTC.IPRA.BIT.B7 = 1;  // Set IRQ0      Priority Level
      INTC.IPRA.BIT.B6 = 1;  // Set IRQ1      Priority Level
      INTC.IPRA.BIT.B5 = 1;  // Set IRQ2,IRQ3 Priority Level
      INTC.IPRA.BIT.B4 = 1;  // Set IRQ4,IRQ5 Priority Level
    }

  メインルーチンですが、今回はIRQ0〜5に対応するボタンが押されたときにLEDが消えたり付いたりするという内容を作りますので、驚くほどシンプルになります。なお、IRQ0〜5に対応するポートとはPort8-0〜3と、Port9-4,5です。

main.c

    void main(void)
    {
        P8.DDR     = 0x00;        // Port-8は入力設定
        P9.DDR     = 0x00;        // Port-9は入力設定
        PB.DDR     = 0xff;        // Port-Bは出力設定
        PB.DR.BYTE = 0x00;

        while(1);                 // 何もせず待機

    }

 今回の主役はintprg.cに居ます。

intprg.c

    #include "iodefine.h"

    void    INT_IRQ0(void)        // Port8-0(IRQ0)が押されたときの処理
    {
        PB.DR.BIT.B0 = !PB.DR.BIT.B0;
    }
    void    INT_IRQ1(void)        // Port8-1(IRQ1)が押されたときの処理
    {
        PB.DR.BIT.B1 = !PB.DR.BIT.B1;
    }
    void    INT_IRQ2(void)        // Port8-2(IRQ2)が押されたときの処理
    {
        PB.DR.BIT.B2 = !PB.DR.BIT.B2;
    }
    void    INT_IRQ3(void)        // Port8-3(IRQ3)が押されたときの処理
    {
        PB.DR.BIT.B3 = !PB.DR.BIT.B3;
    }
    void    INT_IRQ4(void)        // Port9-4(IRQ4)が押されたときの処理
    {
        PB.DR.BIT.B4 = !PB.DR.BIT.B4;
    }
    void    INT_IRQ5(void)        // Port9-5(IRQ5)が押されたときの処理
    {
        PB.DR.BIT.B5 = !PB.DR.BIT.B5;
    }

 ほとんど説明するまでもないような内容ですが、それぞれのIRQに対応するボタンが押されると、6つ並んだ割り込み処理のどこかに飛んできます。たとえばPort8-1に繋がったボタンが押されると、それはIRQ1ですから、void INT_IRQ1(void)の中に記述した内容が実行されます。実行が終わるとまたメインルーチンに戻っていきます。

 なお、外部割り込みの発生条件は、そのポートの電位がLowに引き下げられたときに限ります。したがって、信号の入力に使う場合で、エッジの立ち上りを検出したいならば物理的な回路でレベルを反転させなければいけません。そのまま繋ぐことができないので面倒ですが、回路としては簡単です。下図のようにすればOKです。

 これは、NPN型のトランジスタをスイッチとして使う方法で、入力がOFFの時にはトランジスタは電流を通さないのでIRQの入力ポートには5Vの電圧がかかります。逆に、入力がONの時には5Vの電圧は抵抗を介してそのままGNDに落ちるため、入力ポートは0Vになります。よって、入力信号が反転できる仕組みです。

 

home1.gif next1.gif back1.gif