16F873A XC8開発例 - モーメンタリスイッチによるLEDの点灯制御
はじめに
本ページでは,PIC16F873AとMPLAB XC8 C Compilerを使用した開発例として,モーメンタリ動作の押しボタンスイッチによるLEDの点灯制御回路の製作例を紹介します.
モーメンタリ動作の押しボタンスイッチは,スイッチが押されている間はON状態になり,スイッチから手を離すとOFF状態に復帰します. このことから自己復帰型スイッチとも呼ばれています. ここでは,モーメンタリ動作の押しボタンスイッチを押下する度にLEDの点灯・消灯を切り替えることができ,スイッチから手を離しても点滅状態を保持するプログラムを紹介します.
下記の環境で動作を確認しておりますが,動作を保証するものではありません. 掲載情報は自己責任の上でご利用ください.
PIC | 16F873A-I/SP |
---|---|
MPLAB X IDE | MPLAB X IDE v1.95 for Mac |
MPLAB XC8 | MPLAB XC8 C Compiler v1.21 for Mac |
PICkit 2 | MPLAB X IDEを使用して書込み |
回路
回路図
今回はブレッドボード上に回路を組むことにしました. PICkit 2によるICSP (In Circuit Serial Programming)と電源供給を行うことし,回路部品数は必要最低限に抑えています.

回路部品
上記の回路図中で使用している回路部品のリストです. 参考単価は,特に記載がない限り,秋月電子通商で購入した場合のものです.
番号 | 部品名 | 型番 | 数量 | 参考単価 |
---|---|---|---|---|
U1 | PICマイコン | Microchip 16F873A-I/SP | 1 | 350円 |
X1 | セラロック | 村田製作所 10MHz | 1 | 30円 |
LED1, SW1 | LED付き 押しボタンスイッチ |
Switronic ST-12-303FC-G(緑,正方形) | 1 | 150円 |
R1, R3 | 炭素皮膜抵抗 | 各社 1/4W 10kΩ | 2 | 1円 |
R2 | 炭素皮膜抵抗 | 各社 1/4W 200Ω | 1 | 1円 |
その他 | リード線など | 適量 |
プログラム
下記のプログラムはMPLAB XC8 C Compiler向けです.Cコンパイラの種類にご注意ください.
モーメンタリ動作の押しボタンスイッチSW1を押す度に,LED1の点灯・消灯を切り替えることができます. 押しボタンスイッチのチャタリング対策として,スイッチの状態は10ミリ秒の間隔を置いて2回確認するようにしています. スイッチが押下された状態の場合は,変数sw1_stateの値から前回のスイッチの状態を確認します. これはスイッチが押下された状態で点灯・消灯の切り替えを複数回繰り返さないための判定処理です. sw1_stateが0であればスイッチは押下直後ということなので,LEDの点灯状態を保持するための変数modeの値を反転します.
この開発例ではLEDの点灯・消灯の切り替えを行っていますが,回路とプログラムを変更することで様々な応用が可能ではないかと思います. 例えばモータの正転・逆転の切り替えです. モータの回転方向が直接視認できない場合でも,LEDで回転方向を容易に把握することができるようになります.
#include <xc.h>
#define _XTAL_FREQ 10000000 // 10MHz
#pragma config BOREN = ON, CPD = OFF, DEBUG = OFF, WRT = OFF, FOSC = HS, WDTE = OFF, CP = OFF, LVP = OFF, PWRTE = ON
void main()
{
static bit sw1_state;
static bit mode;
TRISA = 0x01; // PORTAの入出力設定
TRISB = 0x00; // PORTBの入出力設定
TRISC = 0x00; // PORTCの入出力設定
ADCON0 = 0b00000000; // A/D変換を無効化
ADCON1 = 0b00000111;
PORTA = 0x00; // PORTAを初期化
PORTB = 0x00; // PORTBを初期化
PORTC = 0x00; // PORTCを初期化
sw1_state = 0b0; // 制御変数を初期化
mode = 0b0;
while (1) { // 無限ループ
if (RA0 == 0b1) { // SW1がONの場合
__delay_ms(10); // 10ミリ秒タイマ
if (RA0 == 0b1) { // SW1の状態を再確認(チャタリング対策)
if (sw1_state == 0b0) { // 前回のSW1の状態がOFFだった場合
mode ^= 0b1; // モードを切替
}
sw1_state = 0b1; // 今回のSW1の状態を記録
}
else{
sw1_state = 0b0; // 今回のSW1の状態を記録
}
}
else{ // SW1がOFFの場合
sw1_state = 0b0; // 今回のSW1の状態を記録
}
if (mode == 0b1) { // モードの判定
PORTB = 0x01; // LED1を点灯
}
else{
PORTB = 0x00; // LED1を消灯
}
}
}
実装
回路構成例
上記の回路図を基に,ブレッドボード上に回路を組み立てました.電源はPICKit 2から供給しています.

__delay_ms関数にエラーマークが表示されるときは
文法や関数の利用方法に問題がなくコンパイルが成功するにも関わらず, __delay_ms関数や__delay_us関数にエラー(警告)マークが表示される場合,下記の記事をご一読ください.