akira.kei が 2025年02月25日23時52分32秒 に編集
初版
タイトルの変更
8ピンPICのPIC16F18313を使う(その14)割り込みボタン
タグの変更
PIC16F18313
PIC
記事種類の変更
セットアップや使用方法
Lチカの変更
本文の変更
[<前の記事](url) : [次の記事>](url) ## またLチカ 割り込みボタンの使い方を再確認する意味で、ボタンを押すとLチカの周期が変わるようにしてみた。PIC16F18313に限らないが、色々気にすべき点が多くて意外に面倒だったが、ボタンを押すと「ちっ、かっ、ちっ、かっ…」だったのが「チカチカ…」とボタンと連動して点滅周期の変更ができた。 ## pragma_config.h コンフィギュレーションワードの設定はいつもの内蔵1MHzなので説明は割愛して以下に列挙する。今回は外部電源を繋いでいるので、ほとんどの安全機能はOFFでいい。 ``` // CONFIG1 #pragma config FEXTOSC = OFF #pragma config RSTOSC = HFINT1 #pragma config CLKOUTEN = OFF #pragma config CSWEN = OFF #pragma config FCMEN = OFF // CONFIG2 #pragma config MCLRE = OFF #pragma config PWRTE = OFF #pragma config WDTE = OFF #pragma config LPBOREN = OFF #pragma config BOREN = OFF #pragma config BORV = LOW #pragma config PPS1WAY = ON #pragma config STVREN = OFF #pragma config DEBUG = OFF // CONFIG3 #pragma config WRT = OFF #pragma config LVP = OFF // CONFIG4 #pragma config CP = OFF #pragma config CPD = OFF ``` ## main.c メイン関数の冒頭はいつものincludeだが、__delay_msマクロを使うので_XTAL_FREQを設定しておいた。 ``` #include <xc.h> #include "pragma_config.h" #define _XTAL_FREQ 1000000 ``` 割り込みルーチンはいつもmainの前に置くようにしている。高速点滅と低速点滅の切り替えフラグをグローバル変数にして割り込みルーチンではこれを切り替えるだけにしてある。割り込み直後に「割り込み禁止」にしているのはスイッチのチャタリングの影響を避けるつもりだったが、意味が無かったかも。 割り込みフラグ(INTF)を調べてクリアしてフラグを反転するだけしかやっていない。 ``` unsigned char flg=0; void __interrupt() isr(void) { INTCONbits.GIE=0; if(PIR0bits.INTF) { PIR0bits.INTF=0; flg=~flg; } INTCONbits.GIE=1; } ``` main関数の冒頭ではアナログ無効、まずは全端子入力設定にして、RA4を出力にしてLEDを接続した。また、RA2にスイッチを接続したのでプルアップを設定した。 ``` void main(void) { ANSELA=0; TRISA=0xff; TRISAbits.TRISA=0; // LED WPUAbits.WPUA2=1; // Pullup for SW ``` PIC16F18313では割り込みモジュールもPPSで割り当てなければならない。データシートのレジスタ説明は「xxxPPS」とした表記されておらず、INTPPSなのかINT1PPSなのか、はたまたINT0PPSなのか定かでは無かったが、レジスタマップを見てようやく「INTPPS」である確信が得られた。不親切すぎw 残りは普通にINT割り込み関係の設定だ。 ``` // INTPPSbits.INTPPS=0b00010; // RA2->INT PIR0bits.INTF=0; PIE0bits.INTE=1; INTCONbits.PEIE=1; INTCONbits.GIE=1; ``` あとはループの中でフラグの値に従って点滅させるだけだ。__delay_msの括弧の中身は変数は使えない(リテラルである必要がある。マクロだからか)。長いプログラムなら「LATAbits.LATA4」などでLED制御をせず、LED_OnとかLED_Toggleとかを設定しても良かったが、まぁ短いからいいだろう。ただ可読性の観点からは当然置き換えるべきだ。 ``` // while(1) { LATAbits.LATA4=1; if(flg) __delay_ms(100); else __delay_ms(500); LATAbits.LATA4=0; if(flg) __delay_ms(100); else __delay_ms(500); } } ```