[BC19-04] マイコン・プログラミング入門
2-LED, Buzzer , TACT switch PIC12F1822 Platform
LED2個、圧電スピーカ、タクトスイッチをPIC12F1822に接続した簡単な回路で、マイコン・プラグラミングを基礎から試せる解説書
アイデアとプログラミング次第で、LEDイルミネーション、ラーメンタイマーやオルゴールなどが作れる。
使用部品
使用部品
ブレッドボード
PICマイコン PIC12F1822
LED φ5mm (VF=2V程度)2個
炭素皮膜抵抗器 150Ω 2個
タクトスイッチ 2端子 5mmピッチリード
積層セラミックコンデンサ 0.1uF 5mmピッチリード
圧電スピーカー(圧電サウンダ)(13mm)PKM13EPYH4000-A0
電池ボックス(単3形2本用)、バッテリースナップ
ジャンパ線
回路図
回路図
bc2019-04-2LED-BUZ-12f1822.pdf
mplabxide_how2make_project.pdf
サンプルコード ( XC8 Compiler )
サンプルコード ( XC8 Compiler )
機能: 衝撃を検出すると警報音とLED点灯が10秒間継続するライト
機能: 衝撃を検出すると警報音とLED点灯が10秒間継続するライト
動作:
動作:
(1)最初にピッとブザーが鳴り、LED0→LED5の順で3回点滅する。(起動チェック)
(2)異常がないときは、LED5が点灯している。
(3)衝撃を検出するとブザーが鳴り、LED5が消灯してLED0が点灯する。10秒間、ブザー鳴動とLED0の点灯を続けた後、1秒間ブザー鳴動は停止し、LED0が消灯する。
(4) スイッチが押されたときは、ピッピッと2回ブザーが鳴った後、LEDが消灯し、ブザー鳴動も止まる。(緊急停止)その後(2)に戻る。
#include <xc.h>
#include <stdint.h>
#pragma config FOSC = INTOSC // 内部クロック使用。
#pragma config WDTE = OFF // ウォッチドッグタイマなし。
#pragma config PWRTE = ON // 64ms後にプログラム開始。
#pragma config MCLRE = OFF // 外部リセットなし。RA3は入力ピン。
#pragma config CP = OFF // コード保護なし。
#pragma config CPD = OFF // データ保護なし。
#pragma config BOREN = ON // 電源電圧低下時のリセットあり。
#pragma config CLKOUTEN = OFF // クロック出力不可。
#pragma config IESO = OFF // 内部外部クロックなし。
#pragma config FCMEN = OFF // FCMなし。
#pragma config WRT = OFF // 書き込み保護なし。
#pragma config PLLEN = OFF // PLLなし。
#pragma config STVREN = ON //スタックオーバー/アンダーフローでリセット。
#pragma config BORV = LO // 電源電圧低下監視閾値はLowモード
#pragma config LVP = OFF // 低電圧プログラムなし。
void wait(volatile uint32_t i) {
while (i-- > 0);
}
void led0on(void) {
// RA0に接続したLEDを点灯
RA0 = 1;
}
void led0off(void) {
// RA0に接続したLEDを消灯
RA0 = 0;
}
void led5on(void) {
// RA5に接続したLEDを点灯
RA5 = 0;
}
void led5off(void) {
// RA5に接続したLEDを消灯
RA5 = 1;
}
uint8_t isswon() {
//スイッチが押されているときに0でない値、スイッチが押されていないときに0を返す。
return (RA3 ^ 1);
}
void startccp(uint8_t p) {
ANSA2 = 0; // PORT_ADCで定義されたポートをディジタルポートにする。
TRISA2 = 0; // RA2を出力モードにする
PR2 = p; // 音の周期の設定
CCP1ASE = 0; // CCP1シャットダウンイベントステータスをクリアしてCCP1を実行許可
TMR2ON = 1; // Timer2を実行許可
}
void stopccp(void) {
CCP1ASE = 1; // CCP1シャットダウンイベントステータスをセットしてCCP1を実行禁止
TMR2ON = 0; // Timer2 停止
}
uint32_t TimerCounter; // 時間計測用変数
void waittimeout0(uint32_t t) {
// t [s]間何もせずに待つ
TimerCounter = 0; // タイマカウンタのクリア
while (TimerCounter <= t * 15); // t[s]間待つ
}
uint16_t adc(void)
// A/D変換 戻り値はA/D変換値 0~1023
{
uint16_t adcv; // A/D変換値を格納する変数を宣言
stopccp(); //ポートRA2のccpを停止
ANSA2 = 1; //ポートRN2をアナログポートにする。
TRISA2 = 1; // A/D変換端子(RA2)を入力モードにする。
//A/D変換
wait(10); // 少し待つ
GO_nDONE = 1; //A/D変換の開始
while (GO_nDONE); // A/D変換が完了するまで待つ
adcv = ADRESH << 2 | ADRESL >> 6; // A/D変換で得られた値を変数adcvへ
return adcv;
}
uint8_t isshock(void) {
if (adc() > 100) { //衝撃検出時には
return 0xff; // 0xff(真となる値)を返す
} else { //衝撃がなければ
return 0x00; // 0x00(偽となる値)を返す
}
}
void __interrupt() intr(void)
// 割込み処理関数
{
if (INTF == 1) { //割込みが発生したことを示すフラグが立ったら、
INTF = 0; //割込み発生フラグをクリアする。クリアしないと次の割込みが発生しない。
}
if (TMR0IF == 1) {
TMR0IF = 0; // TMR0フラグをクリアする。
TimerCounter++;
}
if (IOCAF3 == 1) { // RA3の変化による割込みが発生したら
if (isswon()) {//タクトスイッチが押されていれば、立下りと判断
//(IOCAN3=1によるネガティブエッジ設定がXC8 compiler v2.10では反映されないことへの対応策)
stopccp(); // ブザーを止める
for (uint8_t i = 0; i < 2; i++) {
startccp(150); // 音を鳴らす
wait(8000);
stopccp(); //音を止める
wait(8000);
}
led0off(); // LED0を消灯する。
TimerCounter = 0x0fffffff; // Timerもクリアする
}
// RA3の変化による割込みのフラグをクリア。クリアしないと次の割込みが発生しない。
IOCAF3 = 0;
}
}
void main(void) {
// I/Oポートの初期化
OSCCON = 0b01101010; // PLL disable, 4MHz internal clock
ANSELA = 0b00000000; //ALL digital port
TRISA = 0b00001000; //I/O Direction. RA0-2,4-5 : output, RA3 : Input
OPTION_REGbits.nWPUEN = 0; //ウィークプルアップを有効にする。
WPUA = 0b00001000; // RA3のウィークプルアップを有効にする。
LATA = 0b00000000; // PORTA Latch Settings
// A/D変換の設定
ANSA2 = 1; // PORT_ADCで定義されたポートをアナログポートにする。
TRISA2 = 1; // A/D変換端子を入力モードにする。
ADCON0 = 0b00000001 | (2 << 2); //AD変換(ポートAN2)を有効化。
ADCON1 = 0b01000000; //0:(ADFM=0)精度10bit, 100:Fosc/4 ,0:Reserved, 00:AVDD=VREF
CM1CON0 = 0x00; //コンパレータを無効化。
//Timer2 をPWM 標準モードに設定
PR2 = 0; // PWM Period = [(PR2) +1 ]*4*(1/FOSC)*(Timer2 Prescale value)
T2CON = 0b00000010; // 周波数のプリスケーラ(倍率)を16倍にする
APFCON &= ~(1 << CCP1SEL); //CCP1 をポート RA2 に割り当てる
CCP1CON = 0b00001100; //PWM モード: P1A, P1C, P1B, P1D アクティブHigh
CCPR1L = 64; // PWMデューティ比(CCPR1L:CCP1CON<5:4>)*(1/FOSC)*(TMR2 Prescale Value)
// タイマ0割込みの設定
TMR0IF = 0; // タイマ0割込みフラグをクリアする。
OPTION_REG &= 0b11000000; // ウィークプルアップ設定用の第7,6ビットを保持。
OPTION_REG |= 0b00010111; // タイマ0のクロックを内部クロックの1/256に
TMR0IE = 1; // タイマ0割込み許可
//ポート変化割込みの設定
IOCAP3 = 0; //ポートRA3がLowからHighに変化(ポジティブエッジ)したときに割込み発生しないよう設定
IOCAN3 = 1; //ポートRA3がHighからLowに変化(ネガティブエッジ)したときに割込み発生するよう設定
IOCIE = 1; //ポートが変化したときの割込みを許可
GIE = 1; //これまで許可したあらゆる割込みを許可
//ブザー
startccp(100); // 音を鳴らす
wait(3000);
stopccp(); //音を止める
//最初のLED点滅
for (uint8_t i = 0; i < 3; i++) {
led0on();
led5off();
wait(5000);
led0off();
led5on();
wait(5000);
}
led0off();
led5off(); // LED全部消灯
while (1) {
led5on(); // LED5点灯
if (isshock()) { // 衝撃があったとき
startccp(100); // 音を鳴らす
led0on();
led5off(); // LED0を点灯, LED5は消灯
waittimeout0(10); //10秒間何もせずに待つ
led0off(); // LED0消灯
led5off(); // LED5消灯
}
}
}