この記事は PICマイコン Advent Calendar 2025 12日目の記事です。
1. はじめに
前回の記事では、タイマ割り込みを使って LED を周期的に点滅させました。
今回は、外部入力の変化をきっかけに処理を行う 状態変化割り込みを扱います。
なお、クロック設定や I/O ピン設定、割り込みの基本については、前回と前々回の記事を参照してください。
前回
前々回
2. 使用マイコン
本記事ではPIC24Fファミリに属するPIC24FJ64GB002を使用します。
LEDはRB10に接続しています。
入力としてタクトスイッチをRB14(CN12)に接続しています。
チャタリングを防止するためにセラミックコンデンサを挟んでいます。
3. 状態変化割り込みを使ってみる
状態変化割り込みは、ピンの状態が前回から変化したときに発生する割り込みです。
スイッチ入力やフォトインタラプタなど、外部信号の変化をきっかけに処理を行いたい場合によく使われます。
状態変化割り込みに対応したピンは、データシート上でCNxと表記されています。
これらのピンは、内部プルアップや内部プルダウンに対応していることが多いです。
ただし、PIC24FJ64GB004 FAMILYでは内部プルダウンが未実装なので注意が必要です。
今回は外付けのプルアップ抵抗を使用せず、内部プルアップを有効化します。
内部プルアップを有効化するにはCNPUレジスタを設定します。
内部プルダウンを有効化したい場合はCNPDレジスタを設定します(本記事で使用しているマイコンファミリには未実装ですが...)。
割り込みハンドラでは、まず CN 割り込みフラグをクリアします。
これは他の割り込みと同様で、必ず行う必要があります。
状態変化割り込みでは、どのピンが、立ち上がり/立ち下がりのどの方向に変化したかをハードウェアは教えてくれません。
そのため、割り込みハンドラ内でPORTレジスタを読み、現在のピンの状態をもとにソフトウェア側で判定します。
今回は、タクトスイッチが押された瞬間にLEDをトグルさせたいので、RB14がLowのときにLEDをトグルするようにします。
なお、ピンに印加されている信号を読むには、PORTレジスタを使用します。
コード例
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
void _ISRFAST _CNInterrupt(){
IFS1bits.CNIF = 0;
if(PORTBbits.RB14 == 0){
LATBbits.LATB10=!LATBbits.LATB10;
}
}
int main(int argc, char** argv) {
OSCCON = 0x0000;
CLKDIV = 0x0000;
AD1PCFG = 0xffff;
TRISA = 0xffff;
TRISB = 0xffff;
TRISBbits.TRISB10 = 0;
TRISBbits.TRISB14 = 1; // CN12
CNPU1bits.CN12PUE = 1;
CNEN1bits.CN12IE = 1;
IFS1bits.CNIF = 0;
IEC1bits.CNIE = 1;
while(1){}
return (EXIT_SUCCESS);
}
※ config.h にはConfiguration Bitsの基本設定を入れています。
4. おわりに
今回は、状態変化割り込みを使って処理を行いました。
状態変化割り込みは、設定が比較的簡単でありながら、スイッチ入力など、さまざまな場面で利用できるペリフェラルです。
そのため、外部入力を扱う際の基本的な手法として、一度は動かしておくとよい機能だと思います。