PIC16F88の 「入力ピン状態変化割り込み」と「外部割り込み」をトグルスイッチとタクトスイッチを使って確認しよう

【 当サイトには広告リンクが含まれています。 】

トグルスイッチを切り替えると、「入力ピン状態変化割り込み」が発生し、赤色LEDと緑色LEDがウィンカーのように交互に点滅します。

タクトスイッチを押すと、「外部割り込み」が発生し、赤色/緑色、いずれかのLEDが点滅している場合は、すべてのLEDが消灯し、すべてのLEDが消灯している場合は、ハザードのように両方のLEDが点滅します。



実験準備

実験に必要な機器とキットの部品を準備します。

機器

「MPLAB X IDE 6.20」をインストールしたWindows11搭載のパソコンとPICマイコンライタ(PIC K150)を準備します。

  • 「MPLAB X IDE 6.20」のインストールについてはこちらを参考にしてください。

  • PICマイコンライタ(PIC K150)についてはこちらを参考にしてください。


部品

赤色LEDと固定抵抗等、実験に使う部品を準備します。

部 品 名規 格数 量取扱い店(参考)
PICマイコンPIC16F88-I/P1電子工作ステーション
LED5mm 赤色 (同等品)1電子工作ステーション
LED5mm 緑色 (同等品)1電子工作ステーション
カーボン抵抗1/4W 330Ω2電子工作ステーション
カーボン抵抗1/4W 10KΩ3電子工作ステーション
カーボン抵抗1/4W 1KΩ1電子工作ステーション
タクトスイッチ7mm1電子工作ステーション
電解コンデンサ10μF/50V/105℃1電子工作ステーション
積層セラミックコンデンサ0.1μF(+80%/-20%) / 50V / 4電子工作ステーション
ブレッドボード・
ジャンパーワイヤーSET
14種×10本1電子工作ステーション
2入力NANDゲートTC74HC00AP1秋月電子通商
6回路シュミットトリガー
インバーター
TC74HC14AP1秋月電子通商
ブレッドボードEIC-80321秋月電子通商
スイッチングACアダプター 5V2AAD-T50P2001秋月電子通商
ブレッドボード用
DCジャックDIP化キット
AE-DC-POWER-JACK-DIP1秋月電子通商
※ブレッドボード用
トグルスイッチ
AE-BBTGLSW-CONV1秋月電子通商

※ブレッドボード用トグルスイッチは半田付けが必要です。


配線

準備した部品を回路図に従ってジャンパーワイヤーで接続し、実験回路を製作します。


回路図



回路について

割り込みラインに接続されているタクトスイッチ(SW1)やトグルスイッチ(SW2)は、機械的なスイッチですのでチャタリング(バウンス)が発生する可能性があります。

チャタリングにより、マイコンは複数の割込みが発生したと認識し、不安定な動作となります。

回路図-1のタクトスイッチには、抵抗とコンデンサを組み合わせた積分回路にシュミットトリガ(74HC14)を接続して、チャタリングを防止しています。

トグルスイッチについては、NANDゲート(74HC00)を2個使ってSRラッチ回路を制作し、チャタリングを防止しています。

両方の回路とも、出力をオシロスコープで確認したところ、チャタリングは確認できませんでした。

なお、現在ではプログラムによるチャタリング防止が主流となっているようです。


MPLABでC言語プログラミング

「PIC16F88でLチカさせてみよう」記事の「MPLABでC言語プログラミング」を参考に、MPLAB X IDE v6.20 を使って、PIC16F88のC言語プログラムを作成します。

Project Name: と Project Location:の設定


New Project-Project Name and Folderダイアログの内容は、次のように設定、選択します。

項 目設 定 内 容
Project Name:任意(ここでは、16f88_turn_signal)
Project Location:任意
Encoding:Shift JIS


main.c(ソースファイル)のFile Name:の設定


File nameに「任意の名前(16f88_turn_signal_src)」を入力し、Extentionに「c」を選択します。


コンフィグレーションビットの設定

コンフィグレーションビットを次のように設定します。
(Source Files への入力は、次項の「プログラムの作成とビルド」を参照して下さい。)

FieldOption説 明
コンフィグレーションビット1
FSOCINTOSCIO内部RC発振回路を利用します(RA6、RA7ピンは汎用入出力)
WDTEOFFウォッチドッグタイマを無効にします
PWRTEOFFパワーアップタイマーを有効にします
MCLREOFF入出力ピンとして使用します
BORENONブラウンアウトリセットを有効にします
LVPOFF低電圧書き込みを無効にします
CPDOFFデータメモリ(EEPROM)の読出しを保護をしない
WRTOFFプログラムメモリへの書込みを保護しない(書込める)
CCPMXRB3キャプチャ/コンペア/PWM(CCP1)ピンをRB3に指定します
CPOFFPICライターを使ったプログラムメモリの読出しを保護しない(読み出せる)
コンフィグレーションビット2
FCMENOFF外部クロックが異常停止した場合、内部クロックに切り替えません
IESOOFF電源立ち上げ時に、外部クロックが安定するまで、内蔵クロックを使用しません


プログラムの作成とビルド

「PIC16F88でLチカさせてみよう」記事の「プログラムの作成とビルド」を参考に、ソースファイルを作成し、ビルドします。

プログラムの入力

「MPLAB X IDE v6.20」を起動し、「Projects」ウィンドウのソースファイル(16f88_turn_signal_src)のエディタを表示ます。(表示されていない場合は、ソースファイルをダブルクリックします)

「ソースファイル(16f88_turn_signal_src)」のエディタに、トグルスイッチとタクトスイッチの割り込み処理で、LEDを500ms間隔で点滅させるC言語プログラムを作成します。

次のプログラムをエディタに入力するか、コピー、貼り付けします。

/*****************************************************************************
LEDウィンカー/ハザードプログラム
 * File:   16f88_turn_signal_src.c
 * Author: Hagetamaboti
 * Created on 2025/mm/dd
******************************************************************************
ライセンス:SPDX-License-Identifier: MIT
******************************************************************************/	

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

// ********** PIC16F88 コンフィグレーションビットの設定 ********** 
// コンフィグレーションビット1
#pragma config FOSC = INTOSCIO   // 内部RC発振回路を利用します(RA6、RA7ピンは汎用入出力)
#pragma config WDTE = OFF        // ウォッチドッグタイマを無効にします
#pragma config PWRTE = ON        // パワーアップタイマーを有効にします
#pragma config MCLRE = OFF       // 入出力ピンとして使用します
#pragma config BOREN = ON        // ブラウンアウトリセットを有効にします 
#pragma config LVP = OFF         // 低電圧書き込みを無効にします  
#pragma config CPD = OFF         // データメモリ(EEPROM)の読出しを保護をしない
#pragma config WRT = OFF         // プログラムメモリへの書込みを保護しない(書込める)
#pragma config CCPMX = RB3       // キャプチャ/コンペア/PWM(CCP1)ピンをRB3に指定します 
#pragma config CP = OFF          // PICライターを使ったプログラムメモリの読出しを保護しない(読み出せる)

// コンフィグレーションビット2
#pragma config FCMEN = OFF       // 外部クロックが異常停止した場合、内部クロックに切り替えません
#pragma config IESO = OFF        // 電源立ち上げ時に、外部クロックが安定するまで、内蔵クロックを使用しません


// ********** 定数定義 **********
#define _XTAL_FREQ 8000000      // 遅延関数(__delay_ms)を使用するためにシステムクロック(8MHz)を設定
#define RED_LED 0x01            //赤LED点灯
#define GREEN_LED 0x02          //緑LED点灯
#define RED_GREEN_LED 0x03      //赤緑LED点灯

// ********** グローバル変数定義 **********
//Ledの状態設定
unsigned char led_sts = 0x0;    //0:消灯、1:赤LED点灯、2:緑LED点灯、3:赤緑LED点灯

// ********** 関数定義 **********
//LED点灯・消灯関数
void Led_On_Off(void);


// ********** メイン関数 **********
void main(void) {
    
    //SFR(特殊機能レジスタ)設定
    OSCCON = 0x70;              // システムクロックを内部8MHzに設定
    ANSEL = 0x00;               // アナログ入力は使用しない(すべてデジタルに設定)
    CMCON = 0x07;               // コンパレータを無効にする
    PORTA = 0x00;               // PORTA初期化
    PORTB = 0x00;               // PORTB初期化      
    TRISA = 0x00;               // PORTAはすべて出力(RA5は入力のみ)
    TRISB = 0x11;               // PORTBのRB0,RB4は入力その他は出力
    
       
    //割り込みの許可
    INT0IE = 1;                 //RB0/INT 割り込み発生を許可
    RBIE = 1;                   //RB4~RB7 ポート変化割り込み発生を許可
    GIE = 1;                    //すべての割込みを許可
    //無限ループ
    while(1)
    {      
        //LED点灯・消灯関数
        Led_On_Off();
    }
   
}



// ********** 割り込み処理 **********
void __interrupt() isr(void)
{
  
    //プッシュスイッチ (RB0/INT 割込み)
    if (INT0IF) 
    {
        INT0IF = 0;                         //割り込みフラグクリア
        
        if (led_sts == 0)
        {
            led_sts = RED_GREEN_LED;        //赤緑LED点灯(ハザード)                    
        }
        else
        {
            led_sts = 0;                    //Led消灯     
        }
         
    }

    //トグルスイッチ (PORTB-RB4) 割込み)      
    if (RBIF)
    {
         RBIF = 0;                           //割り込みフラグクリア
       
        if (RB4 == 1)
        {
            led_sts = RED_LED;              //赤LED点灯(ウィンカー)
        }
        else
        {
            led_sts = GREEN_LED;            //緑LED点灯(ウィンカー) 
        }
        
    } 

}


// ********** LED点灯・消灯処理 **********
void Led_On_Off()
{
    PORTA = led_sts;            //Led点灯・消灯設定           
    __delay_ms(500);            // 500ms 待ち
    PORTA = 0x0;                //LED消灯 
    __delay_ms(500);            // 500ms 待ち
    
    return;
}



ビルド

正常にビルドが完了するまで、デバッグを行います。


トグルスイッチの割り込み処理について

トグルスイッチの割り込みは、「入力ピン状態変化割り込み」に割り当てられている、RB4~RB7の内のRB4で検出します。

「入力ピン状態変化割り込み」は、入力ピン(ここではRB4)の入力信号が変化した時に割り込みを検出しますので、トグルスイッチを切り替える度に、割り込みが検出されます。

RB4~RB7 割り込みを許可するビット(RBIE)とすべての割込みを許可するビット(GIE)が有効のなっていれば、入力信号が変化した時に割込みを検出し、現在進行中の処理は中断され、割り込み処理(void __interrupt() isr(void))が実行されます。

割り込み処理(void __interrupt() isr(void))は、RB4~RB7 割り込み以外の割り込みが発生した場合でも実行されますので、フラグ(RBIF)で発生元がRB4~RB7 割り込みであることを判定し、フラグ(RBIF)をクリアした後、RB4に該当する処理を実行します。

RB4~RB7 割り込みは、RB4以外の入力ピン以外の割り込みが発生した場合でも実行されますので、 RB4のHigt/Lowの状態により、赤緑のLEDのどちらかを点滅させます。

割り込み処理終了後、中断した処理の次の処理(命令)が実行されます。


タクトスイッチの割り込み処理について

タクトスイッチの割り込みは、「外部割り込み」のRB0/INTで検出します。

RB0/INTは、入力信号の立上りまたは、立下りで割込みを検出します。

立上りまたは、立下りは、SFRにあるOPTION_REGの割り込みエッジ選択ビット(INTEDG)で選択され、電源投入時の初期状態では立上りに設定されています。

RB0/INT 割り込みを許可するビット(INT0IE)と、すべての割込みを許可するビット(GIE)が有効のなっていれば、入力信号が立上った時に割込みを検出し、現在進行中の処理は中断され、割り込み処理(void __interrupt() isr(void))が実行されます。

割り込み処理(void __interrupt() isr(void))は、RB0/INT以外の割り込みが発生した場合でも実行されますので、フラグ(INT0IF)で発生元がRB0/INT割り込みであることを判定し、フラグ(INT0IF)をクリアした後、赤緑両方のLEDを点滅または消灯させます。

割り込み処理終了後、中断した処理の次の処理(命令)が実行されます。


実行ファイルをPICに書込む

「PIC16F88でLチカさせてみよう」記事の「実行ファイルをPICに書込む」を参考に、ビルドした、C言語プログラムをPICマイコンライタ(PIC K150)を使ってPIC16F88に書込みます。


実機で性能確認

C言語プログラムが書き込まれたPIC16F88を、制作した実験回路 に実装します。

電源を接続すると、赤または緑のLEDが500ms間隔で点滅します。

トグルスイッチを切り替えると、ウィンカーのように赤色LEDと緑色LEDが500ms間隔で交互に点滅します。

タクトスイッチを押すと、赤色/緑色いずれかのLEDが点滅している場合は、すべてのLEDが消灯し、すべてのLEDが消灯している場合は、ハザードのように両方のLEDが500ms間隔で点滅します。




まとめ

MPLAB X IDE v6.20を使ってC言語でプログラミングを行い、「外部割り込み」と「入力ピン状態変化割り込み」の処理方法を学習しました。

トグルスイッチを切り替えると、「入力ピン状態変化割り込み」が発生し、ウィンカーのように赤色LEDと緑色LEDを交互に点滅させることができました。

タクトスイッチを押すと、「外部割り込み」が発生し、赤色/緑色いずれかのLEDが点滅している場合は、すべてのLEDを消灯させ、すべてのLEDが消灯している場合は、ハザードのように両方のLEDを点滅させることができました。