16F1459は、外部からの信号で割込み(インタラプト)を発生させることができます。RC0 ピンの信号で割り込みを発生する「INTピン」割込みと、すべてのPORTA PORTB で利用できる「IOC」割込みの2種類があります。
<INTピン割込み>
INIT ピンでは、エッジ トリガ型割り込みを発生します。OPTION レジスタのINTEDG ビットによって、割り込みを発生させるエッジが決定されます。INTEDG ビットがセットされていると、立ち上がりエッジで割り込みが発生し、クリアされていると立ち下がりで割り込みが発生します。INIT ピンに有効なエッジが現れると、INTCON レジスタの INTF ビットがセットされ、このとき、GIE および INTE ビットもセットされていると、割り込み処理が実施されます。
<IOC割込み>
IOC(INTERRUPT-ON-CHANGE)割込みも、エッジ トリガ型割り込みを発生します。IOCAPまたはIOCBP レジスタのビットがセットされていると、PortAまたはPortBの該当ビット入力信号の立ち上がりエッジで、IOCANまたはIOCBN レジスタのビットがセットされていると立ち下がりで割り込みが発生します。IOCxP とIOCxNの両方がセットされていれば、 立ち上がりと立ち下がりのどちらのエッジでも割り込みが発生します。該当 ピンに有効なエッジが現れると、IOCAFまたはIOCBF レジスタの該当 ビットがセットされ、このとき、GIE および IOCIE ビットもセットされていると、割り込み処理が実施されます。 INTCONレジスタの IOCIF ビットはRead only で直接クリアすることはできませんが、セット原因となったIOCAFまたはIOCBF レジスタを全てクリアすることでIOCIF ビットもクリアします。
割り込みに関連するレジスター一覧を下表に示します。
| レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|---|
| INTCON | GIE | PEIE | TMR0IE | INTE | IOCIE | TMR0IF | INTF | IOCIF*1 |
| OPTION_REG | nWPUEN | INTEDG | TMR0CS | TMR0SE | PSA | PS<2-0> | ||
| IOCAF | - | - | IOCAF5 | IOCAF4 | IOCAF3 | - | IOCAF1 | IOCAF0 |
| IOCAN | - | - | IOCAN5 | IOCAN4 | IOCAN3 | - | IOCAN1 | IOCAN0 |
| IOCAP | - | - | IOCAP5 | IOCAP4 | IOCAP3 | - | IOCAP1 | IOCAP0 |
| IOCBF | IOCBF7 | IOCBF6 | IOCBF5 | IOCBF4 | - | - | - | - |
| IOCBN | IOCBN7 | IOCBN6 | IOCBN5 | IOCBN4 | - | - | - | - |
| IOCBP | IOCBP7 | IOCBP6 | IOCBP5 | IOCBP4 | - | - | - | - |
ササンプルで作成したプログラムは、SW1,SW2でLEDの点滅方向を変化させます。
<プログラム>
/* File name: IOCA
* Description: interrupt-on-change example
* SW1(RA3),SW2(RA5)が押されると割込みが発生し、
* カウントの加算、減算を変更する。
* カウント値により、LEDを点灯させる。
* Notes: 4MHz内部クロック
* LED: RC2
* Language: MPLABX XC8
* Target: PIC16F1459
*/
#include <xc.h>
#define _XTAL_FREQ 4000000
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config BOREN = ON, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, CPUDIV = NOCLKDIV, USBLSCLK = 48MHz, PLLMULT = 3x
#pragma config PLLEN = DISABLED, STVREN = ON, BORV = LO, LPBOR = OFF, LVP = OFF
char dir = 1; // カウント方向
void main(void){
char num = 0;
OSCCON = 0b00110111; // 内部クロック4Mhz
LATC = 0;
TRISC = 0b11110000; // 入出力設定
IOCAN = 0b00101000; // RA3,RA5入力立下りで割込み
IOCAF = 0;
IOCIE = 1; // IOCを許可
GIE = 1; // 割込み許可
while(1){ //
num += dir; // カウントを更新
switch(num & 3){
case 0:LATC = 0b0001;break;
case 1:LATC = 0b0010;break;
case 2:LATC = 0b0100;break;
case 3:LATC = 0b1000;break;
}
__delay_ms(400); // LEDスピード
}
}
//----------------------割込み処理------------------------
void interrupt isr(void){
if(IOCAF){ // Port A からの割込みを確認
if(IOCAF5) dir = 1; // RA5 割込み
if(IOCAF3) dir = -1; // RA3 割込み
IOCAF = 0; // 割込みフラッグをクリア
}
}