akira.kei が 2025年01月26日01時22分26秒 に編集
コメント無し
本文の変更
[<前の記事](https://elchika.com/article/4f28d674-fd28-4db3-a8c2-7308a419d701/) : [次の記事>](url) ## LEDの接続はしない まずは今回の「Lチカ」だが実際にはLEDは接続せず、オシロスコープでピンの電圧をモニタする。このLEDを接続したつもりになるピンの選定だが、電源とPICkit4の通信ライン(ICSP)とリセットで8ピンのうち5ピンを使っているし、動作(速度)モニタのためにCLKOUT(RA4)するので、結局RA2とRA5しか空いてないことになる。  ## Pragma Config 前記事に書いたように PIC16F18313 では多彩な内部クロックが選定できるが、Configuration Wordに対して適切な指定をすれば、main関数に何もクロック関連設定を書かなくてもいい。MPLAB Xの「Production」メニュー内の「Set Configuration Word」を選ぶと、下の方に設定画面が出る。この画面で適切な内容を選択して左側にある「Insert Source Code in Editor」ボタンを押すと、ソースコード内に「#pragma config」ステートメントが挿入される。ヘッダファイルとして「pragma_config.h」を用意してその中にこれを記述するようにした。第一Config Wordは以下のように設定する。 ``` // CONFIG1 #pragma config FEXTOSC = OFF // 外部クロック無効 #pragma config RSTOSC = HFINT1 // 1MHz内部クロック #pragma config CLKOUTEN = ON // RA4にFosc/4を出力 #pragma config CSWEN = OFF // NOSCやNDIV設定無効 #pragma config FCMEN = OFF // Fail-Safe無効 ``` 第二Config Wordは以下だ。単純なプログラムでバッテリー駆動しない場合はほとんどの安全機能はOFFでいい。 ``` #pragma config MCLRE = ON // MCLR使用 #pragma config PWRTE = OFF // PowerUp Timer無効 #pragma config WDTE = OFF // Watchdog Timer無効 #pragma config LPBOREN = OFF // Low Power電圧降下リセット無効 #pragma config BOREN = OFF // 電圧降下リセット無効 #pragma config BORV = LOW // (任意) #pragma config PPS1WAY = ON // PPS設定は1度だけ #pragma config STVREN = OFF // スタック溢れリセット無効 #pragma config DEBUG = OFF // デバッグ無効 ``` 趣味の電子工作の場合は第三、第四Config Wordは全てOFF指定だ。特にLVPは「常に」ONかOFFにするのかどちらかに決めておいた方がいい。プログラマにLVP専用の[Snap](https://akizukidenshi.com/catalog/g/g113854/)を使う場合は常にONだが、PICkitの場合は常にOFFの方がトラブルが少ないように思える。 ``` // CONFIG3 #pragma config WRT = OFF // 書き込みプロテクト無効 #pragma config LVP = OFF // 低電圧プログラムモード無効 // CONFIG4 #pragma config CP = OFF // コードプロテクト無効 #pragma config CPD = OFF // データプロテクト無効 ``` ## main関数 main関数の冒頭(宣言部)は以下になる。xc8コンパイラ使用なら「xc.h」が必須、Config Wordをまとめたヘッダファイルの指定とdelay関数のための_XTAL_FREQも指定が必要だ。 ``` #include <xc.h> #include "pragma_config.h" #define _XTAL_FREQ 1000000 ``` Lチカとしてのループは以下のようにdelay_ms関数を使った。RA2とRA5にLEDが接続されていると想定して、交互にLEDが光るようにした。ANSELAレジスタはクリアしなくても問題は無いが念のため。トグル機能は関数化しても良い(する必要性は感じないが)。 ``` void main(void) { unsigned char flg=1; ANSELA=0; TRISAbits.TRISA2=0; TRISAbits.TRISA5=0; while(1) { if(flg) { LATAbits.LATA2=1; LATAbits.LATA5=0; } else { LATAbits.LATA2=0; LATAbits.LATA5=1; } flg=1-flg; __delay_ms(500); } } ``` 上(黄色)がRA2、下(水色)がRA5であり交互に50%デューティ1Hz周期で点滅する。 
ただ実際にはこういう点滅はプログラム制御ではなく、ハードウェア(タイマー)を使った方が頭が良さそうだ。
ただ実際にはこういう点滅はプログラム制御ではなく、ハードウェア(タイマー)を使った方が頭が良さそうだ。 ## いやちょっと待てよ… どうせdelay関数を使うならトグル動作は要らなかったなw フラグを排除してループ内に展開し、遅延時間(us_tmp)を調整したら、きちんと1Hz周期で点滅出来た。OSCTUNEで微調整すればかなり良いところまで行けそう。 ``` #include <xc.h> #include "pragma_config.h" #define _XTAL_FREQ 1000000 #define us_tmp 986 void main(void) { ANSELA=0; TRISAbits.TRISA2=0; TRISAbits.TRISA5=0; while(1) { LATAbits.LATA2=1; LATAbits.LATA5=0; __delay_ms(499); __delay_us(us_tmp); LATAbits.LATA2=0; LATAbits.LATA5=1; __delay_ms(499); __delay_us(us_tmp); } } ```