マイコン1個にLED1個という、これ以上簡単なものは考えられない最小限の構成。
LEDがロウソクのようにゆらゆらっと光る
電池を入れると8時間光って16時間消える周期で繰り返す。
BC19-01の解説用PDF
ミニブレッドボード BB-601(白)[BB-601(White)]
PICマイコンPIC12F1822-I/P [PIC12F1822-I/P]
5mmウォームホワイト・キャンドル色LED OSM2DK5111A-UV (5個入)[OSM2DK5111A-UV]
(VFが2.9V程度のものなら、どんなLEDでも良い)
電池ボックス 単3×2本 Bスナップ・背中合わせ [BH-322-1B]
バッテリースナップ(電池スナップ・Bスナップ) 縦型 カバー付 [SBS-IR-1/150mm]
ブレッドボードとパターン互換のユニバーサル基板を小さく切ったものを使うと回路が小型化できて、LaQに組み込むことも可能。
片面ユニバーサル基板(ブレッドボード配線パターンタイプ) Dタイプ(47x36mm) ガラスコンポジット [AE-DB1]
ICソケット ( 8P) (10個入)[2227-08-03]
ピンソケット(メス) 1x4(4P) [FH-1x4SG/RH]
ピンソケット(メス) 1x2(2P)[FH-1x2SG/RH]
XC8 Compiler対応(文字Code :UTF-8)
/* * File: ledcandle_12f1822.c * Author: kaimu * * Created on April 13, 2019, 5:48 PM *//* * Output * CCP1 (RA2) [PIN5] : LED */#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なし。// 動作設定その2// Configuration 2#pragma config WRT = OFF // 書き込み保護なし。#pragma config PLLEN = OFF // PLLなし。#pragma config STVREN = ON // スタックオーバー/アンダーフローでリセット。#pragma config BORV = LO // 電源電圧低下監視閾値はLowモード#pragma config LVP = OFF // 低電圧プログラムなし。// LED点滅設定#define LED_BLINK_PERIOD_MIN 50 // LEDが点滅する周期の最小値(20-100)#define TIME_LIMIT 50// I/Oポートの定義 (LEDを接続するポートが変わった時はここを変更する)#define PORT_LED_1 RA2#define TRISA_LED_1 TRISA2#define ledOn() (PORT_LED_1 = 1)#define ledOff() (PORT_LED_1 = 0)#define led() (PORT_LED_1 ^= 1)void wait(volatile uint32_t t)// Delay{ while (t-- > 0) NOP();}void initIo(void) { //OSCCON = 0b01111010; // PLL disable, 16MHz internal clock // OSCCON = 0b01100010; // PLL disable, 8MHz internal clock OSCCON = 0b01101010; // PLL disable, 4MHz internal clock //OSCCON = 0b01011010; // PLL disable, 1MHz internal clock //OSCCON = 0b00111010; // PLL disable, 500kHz internal clock INTEDG = 0; // Interrupt on falling edge of RB0/INT pin INTE = 1; // External Interrupt Enable GIE = 1; //Interrupt Enable ANSELA = 0b00000000; //ALL digital port CM1CON0 = 0x00; //Comparator disable TRISA = 0b00001001; //I/O Direction. RA1-2,4-5 : output, RA0,3 : Input LATA = 0b00000000; // PORTA Latch Settings}void initPwm(void) { //Timer2 settings for PWM standard mode PR2 = 0; // PWM Period = [(PR2) +1 ]*4*(1/FOSC)*(Timer2 Prescale value) T2CON = 0b00000010; //00 = Prescaler is 1, 01 = Prescaler is 4, // 10 = Prescaler is 16, 11 = Prescaler is 64 APFCON &= ~(1 << CCP1SEL); //CCP1 function is on RA2 //CCP1SEL = 1;//CCP1 function is on RA5 CCP1CON = 0b00001100; //PWM mode: P1A, P1C active-high; P1B, P1D active-high CCPR1L = 64; // PWM Duty Cycle (CCPR1L:CCP1CON<5:4>)*(1/FOSC)*(TMR2 Prescale Value) //Start PWM TMR2 = 0; TMR2ON = 1;}void stopPwm(void) { CCP1ASE = 1; TMR2ON = 0;}void startPwm(void) { CCP1ASE = 0; TMR2ON = 1;}void pwmPulseWidth(uint8_t value) { CCPR1L = value;}volatile uint32_t TimerCounter; // Counter of Timer Interrupt#define T0UNIT 15UL // TimerCounter at 1 sec.void initTimer0(void)//Initialize Timer 0// count up every 256*256us = 65536us = 65.536ms (clock 4/4=1MHz, prescaler 1:256// if you want t[s] timer, TimerCount <= t / 0.065536{ TMR0IF = 0; // interrupt flag clear TimerCounter = 0; // Timer Interrupt Counter clear OPTION_REG = 0b11010111; // Timer0 Internal clock, Prescaler 1:256 // Timer0 Interrupt occured every 65.536ms TMR0IE = 1; // enable Timer0 interrupt GIE = 1; // enable interrupt}void __interrupt() intr(void)// Interrupt processing function{ if (INTF == 1) { INTF = 0; } if (TMR0IF == 1) { TMR0IF = 0; //Clear TMR0 Interrupt flag TimerCounter++; }}void initialize(void) { initIo(); initPwm(); initTimer0();}void ledoff(void) { ledOff();}void ledon(void) { ledOn();}void waittimeout(uint32_t timeLimit) { uint32_t timeLimitCount = timeLimit * T0UNIT; // 時間切れまでのカウント数 TimerCounter = 0; // タイマのリセット。計時開始。 timeLimitCount = T0UNIT * timeLimit; while (TimerCounter < timeLimitCount) { //制限時間になるまでの処理 }}void starttimer0() { TimerCounter = 0; // タイマのリセット。計時開始。}int8_t istimeout0(uint32_t timeLimit)//指定時間に達していなければ、0xffを返し、指定時間に達していたら0x0を返す。{ uint8_t retvalue; if (TimerCounter < T0UNIT * timeLimit) { retvalue = 0xff; } else { retvalue = 0x00; } return retvalue;}////// ここまで、プログラミングのためのデータや関数を定義する /////////// この後のmain(void) { から }までの間に、プログラムが書ける。 /////void main(void) { uint8_t pulsewidtharray[] = {0x40, 0x28, 0x3f, 0x1f, 0x2a, 0x30, 0x40, 0x38, 0x30, 0x3a, 0x2f, 0x30}; // pwm Pulse width array uint8_t npwa = 12; // number of pwm pulsewidth array uint8_t pwaindex = 1; // pulse width array index uint8_t pulsewidth; // current pulsewidth uint32_t ledontime = 28800; // 点灯時間28800sec.(8h) uint32_t ledofftime = 57600; // 消灯時間5sec.(16h) initialize(); //システムの初期化 stopPwm(); ledoff(); //LEDを消す while (1) { //無限ループ。次の}までの間を無限回繰り返す。 starttimer0(); // タイマを開始 startPwm(); PR2 = 50; while (istimeout0(ledontime)) { pulsewidth = pulsewidtharray[pwaindex]; for (uint8_t i = pulsewidth / 8; i < pulsewidth; i++) { pwmPulseWidth(i); wait(2000); } for (uint8_t i = pulsewidth; i > pulsewidth / 8; i--) { pwmPulseWidth(i); wait(2000); } if (pwaindex > 0) { pwaindex--; } else { pwaindex = npwa - 1; } } //消灯時間の間LEDを消灯する stopPwm(); ledoff(); starttimer0(); while (istimeout0(ledofftime)); }}////// この上の } より上にプログラムが書ける。 /////