PIC 12F615


初めての PIC 割り込みに挑戦 (1)

次は割り込み処理

前回Lチカを実装してみました。
今回は割り込み処理を試してみたいと思います。
想定する動作は、タクトスイッチを押す毎にLEDの点灯と消灯を繰り返すものとしました。

割り込みを実現するにはいくつかのレジスタを設定する必要があります。今回の処理では、
 ・GPIO 3番ピンの interrupt-on-change
を使えるようにするためにIOCレジスタを設定します。
また、INTCONレジスタのGPIEとGIEビットを設定して割り込みを許可します。
割り込みがトリガーされるとINTCONレジスタのGPIFビットが設定されるので、処理終了時にクリアする必要があります。
以上のことを考慮したソースが次です。

/*
 * CNC Power unit
 * 
 * File:   main.c
 * Author: masato
 *
 * Created on 2017/02/05, 8:02
 */

// PIC12F615 Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config IOSCFS = 8MHZ    // Internal Oscillator Frequency Select (4 MHz)
#pragma config BOREN = ON       // Brown-out Reset Selection bits (BOR enabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

static int val = 0;
static int odd = 0;
void interrupt ISR(void) {
    if (INTCONbits.GPIF) {
        if (odd) {
            val ^= 1;
            GP4 = val;
        }
        odd ^= 1;
        INTCONbits.GPIF = 0;    // 割り込みフラグクリア
    }
}

void main(void) {

    // レジスタセット
    TRISIO = 0b00001000;
    ANSEL =  0b00000000;
    CMCON0 = 0b00000000;
    IOCbits.IOC3 = 1;

    INTCONbits.GPIE = 1;        // GPIO変更割り込み許可
    INTCONbits.GIE =  1;        // グローバル割り込み許可

    GP0 = 0;
    GP1 = 0;
    GP2 = 0;
    GP4 = 0;
    GP5 = 0;

    while(1);

    return;
}

ところが何故かこれでは思うように動きませんでした。タクトスイッチを押すと点灯し、放すと消灯します。

デッバグの意味で次のようにプログラムを修正しました。

/*
 * CNC Power unit
 * 
 * File:   main.c
 * Author: masato
 *
 * Created on 2017/02/05, 8:02
 */

// PIC12F615 Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config IOSCFS = 8MHZ    // Internal Oscillator Frequency Select (4 MHz)
#pragma config BOREN = ON       // Brown-out Reset Selection bits (BOR enabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

static int val = 0;
static int odd = 0;
static int even = 0;
void interrupt ISR(void) {
    if (INTCONbits.GPIF) {
        if (odd) {
            val ^= 1;
            GP4 = val;
        }
#if 1
        if (even & 0x01)
            GP0 = 1;
        else
            GP0 = 0;

        if (even & 0x02)
            GP1 = 1;
        else
            GP1 = 0;

        if (even & 0x04)
            GP2 = 1;
        else
            GP2 = 0;

        even++;
#endif
        odd ^= 1;
        INTCONbits.GPIF = 0;    // 割り込みフラグクリア
    }
}

void main(void) {

    // レジスタセット
    TRISIO = 0b00001000;
    ANSEL =  0b00000000;
    CMCON0 = 0b00000000;
    IOCbits.IOC3 = 1;

    INTCONbits.GPIE = 1;        // GPIO変更割り込み許可
    INTCONbits.GIE =  1;        // グローバル割り込み許可

    GP0 = 0;
    GP1 = 0;
    GP2 = 0;
    GP4 = 0;
    GP5 = 0;

    while(1);

    return;
}

すると思った通りに、タクトスイッチを押す毎に点灯と消灯を繰り返すようになりました。
う~ん。どうして?