第17回 割込み処理(2) 〜割込み処理プログラムの基本構造〜

割込み処理プログラムの基本構造について説明します。

これから行うことの説明

割込み処理プログラムの説明をするために、今まで作成していたタイマープログラムはいったん脇に置いておいて、簡単なプログラムを作成して割込み処理プログラムの基本構造を確認することにします。

これから、以下のようにプログラム作成を通して、割込み処理を行うための基本的なプログラムの書き方を確認します。

  1. 最初に、LEDを1秒ごとに点滅させるプログラムを作成します。点滅は「点灯1秒→消灯1秒」を10回繰り返すプログラムにします。
  2. 次に、LEDを1秒ごとに点滅処理している最中に、RA3のスイッチが押された場合、割り込み処理としてLEDを0.1秒ごとに2回点滅処理をして、元の処理(1秒ごとに点滅処理)に戻るようにします。

割込み処理のポイントは、(1)のLEDの点滅処理のプログラム内容を変更することなく、RA3のスイッチが押された場合の処理をプログラムできる、というところにあります。

それでは、(1)のプログラムを作成して、(2)で割込み処理を追加してみましょう。

 

(1)のLED点滅プログラム

新規プロジェクトを作成して、LEDを1秒ごとに10回点滅させるプログラムを作成します。なお、10回点滅後にブザーを鳴らすようにします。今までのタイマープログラムを理解されていれば、このプログラムは簡単ですよね。

/*
 * File:   main.c
 * 割り込み処理のベースとなるプログラム
 * LEDを1秒ごとに10回点滅させる
 */

#include <xc.h>

// PIC12F1822 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)


// クロック周波数指定
// __delay_ms()関数が使用する
#define _XTAL_FREQ 1000000


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

    // PICマイコン設定
    OSCCON = 0b01011010;  // 内部クロック周波数を1MHzに設定
    ANSELA = 0b00000000;  // 全てのピンをデジタルに設定
    TRISA  = 0b00001000;  // RA3を入力、それ以外は出力に設定

    // ブザーをOFFにする
    LATA4 = 0;

    // 点滅開始
    for(unsigned char i=0; i<10; i++) {
        LATA5 = 0;
        __delay_ms(1000);
        LATA5 = 1;
        __delay_ms(1000);            
    }
    
    // ブザーをONにする
    LATA4 = 1;

    // ブザーを鳴らしたままにする
    while (1);

}

これから、このプログラムに対して、「RA3のスイッチが押されたら、1秒ごとの点滅処理は一旦中止して、LEDを0.1秒ごとに2回点滅、終わったら元に戻る」という割込み処理を追加していきます。

 

割込み処理のプログラム構造

割込み処理の基本的な書き方の概念図を説明します。

まず、上のLED点滅プログラムは以下のようになっています。

ベースプログラム

このプログラムに対して、割込み処理を追加するとどうなるか説明します。割込み処理の内容は「スイッチが押されたら、通常の点滅処理は一旦中止して、LEDを0.1秒ごとに5回点滅、終わったら元に戻る」です。

プログラムの追加は大きく分けて2種類あります。一つは「割込み処理関数の追加」、もう一つは「割込み有効化/無効化」です。

先ほどのプログラム構造に、この2種類を追加すると以下のようになります。割込み処理に関して追加したところは緑色の部分です。

割り込み処理追加プログラム

まず、main関数とは別に「LEDを0.1秒ごとの点滅を2回繰り返す」という処理内容の割り込み処理関数を追加します。次に、本体のmain関数の中で、割り込み処理を行いたい部分の前で「割込み有効化」をします。この「割込み有効化」は、具体的には「RA3レジスタの値が1から0に変化したら、現在の処理を一旦中断して『割り込み処理関数』を実行する」という設定になります。(RA3ピンにはスイッチをプルアップで接続していますので、RA3レジスタはスイッチがOFFの時は1、ONの時は0でしたよね)

次に、LEDを1秒ごとに10回点滅処理が終わり、割り込み処理が必要なくなったら「割込み無効化」をします。例えばブザーを鳴らしている間も割り込み処理をさせたい場合は、この割込み無効化はする必要はありません。

このように「割込み処理」とは、マイコンの何かの状態が変化したら、今実行している処理は一旦中断して、別に用意した処理を行う、というものです。

今回は、main関数の中のLED点滅処理中に、RA3のスイッチが押された場合にLEDを0.1秒ごとに点滅する、という割り込み処理のプログラム構造を説明しましたが、他のケースでも割込み処理プログラムの基本構造は同じです。

最初に割込み処理の説明で、

「通常のプログラムを動作中、周辺機器などからの要求により強制的に別のプログラムを実行する処理」

とありましたが、この意味がなんとなくわかりましたでしょうか。

次回は、この割込み処理プログラムを実際に作成して、実際の回路で動作確認します。

 

更新履歴

日付 内容
2017.8.15 新規投稿
2018.12.2 割り込み処理内容変更