すでに作成した、赤外線受信機とオルゴールをまとめ、電池ケースにコンパックトに収納しました。使用した電池ケースは、単3が4本入りケース上部に電源SWが取り付けられている電池ケースです。電池は2本のみ使用し、残り2本のスペースにPIC16F18346、赤外線リモコンセンサー、LED、圧電スピーカーを組み込みました。

↓ 電池ケースの裏蓋を外した内部

LEDの点滅を制御する「LED」モードとオルゴール曲を演奏する「Song」モードがあります。

このプログラムは、main.c,config.c,config.h,gakufu.h,ir.c,ir.h,led.c,led.h,song.c,song.hの10本のファイルから構成されています。スペースの関係で、このページには、main..cのファイルだけ掲載します。他のファイルは、下のアイコンからダウンロードしてください。また、楽譜ファイル(gakufu.h)は、このホームページPIC16F18346のオルゴール項目にあるPCアプリで作成したものと同一の構成です。そのまま、使用することが可能です。PICkit3などですぐに書き込める box_orgel.hex も同梱しています。
Orgel ソースファイル B03_orgel.zip |
main.c
/* File: オルゴール main.c 8 MHz NCO PWM DSM
* LED RC2-5 * SP RA4 * Ir RA5
*
* Language: MPLABX XC8
* Target: PIC16F18346
*/
// 音が減衰する程度 指定値(ms)で1/16減少
#define EnvelopeConst 50
// 音符と音符の間の無音時間(ms)
#define Silent 30
#include <xc.h>
#include <stdint.h>
#include <stdlib.h>
#include "config.h"
#include "song.h"
#include "led.h"
#include "ir.h"
#define _XTAL_FREQ 8000000
// 共通変数 ************************************************
uint8_t boxMode = mSong; // 0:Song 1:Steady 2:Flash 3:Randum
uint8_t irState = 0;
uint16_t revdData = 0;
//---------------------- main ------------------------
void main(void) {
uint16_t code;
OSCFRQ = 0b00000110; // HFOSC 16MHz
OSCCON1 = 0b01100001; // HFINT1 DIV 2 = 8MHz
int_pins();
int_modules();
srand(10); // 乱数初期値
PEIE = 1; // 周辺機能割込みの使用許可
GIE = 1; // 全割込みの使用許可
TMR1IF = 1; // Gap フラグ セット
while(1){ // 繰り返しループ ------------------
if(TMR1IF){ // Gap 検出で
irState = leaderStart; // Ir受信リセットし
TMR1IF = 0; // 次のIr信号受信まで
if(boxMode == mSteady){ // Steady Modeなら
// ------------ // ----------
SLEEP(); // Sleep
// ------------ // ----------
}
}
if(revdData){ // IR受信した
code = revdData;
revdData = 0;
// ---- 受信データーの処理 -----------------------------------
if(boxMode){
switch (code){
case 0xC0C8: modeSong(); break; // Key 切換
case 0xC084: steady(1); break; // Key 1 LED1 反転
case 0xC044: steady(2); break; // Key 2 LED2 反転
case 0xC0C4: steady(3); break; // Key 3 LED3 反転
case 0xC024: steady(4); break; // Key 4 LED4 反転
case 0xC0A4: steady(0); break; // Key 5 全消灯
case 0xC064: steady(9); break; // Key 6 全反転
case 0xC0E4: flash(0); break; // Key 7 点滅1
case 0xC014: flash(1); break; // Key 8 点滅2
case 0xC094: flash(2); break; // Key 9 点滅3
case 0xC054: flash(3); break; // Key 10 点滅4
case 0xC0D4: flash(4); break; // Key 11 点滅5
case 0xC034: random(); break; // Key 12 点滅6
case 0xC098: speed(inc); break; // Key +
case 0xC018: speed(dec); break; // Key ー
case 0xC078: dir(0); break; // Key 大
case 0xC0F8: dir(1); break; // Key 小
default: steady(0); break; // 他のKey 全消灯
}
}else{
switch (code){
case 0xC0C8: modeLED(); break; // Key 切換
case 0xC084: playSong(1); break; // Key 1 LED1 反転
case 0xC044: playSong(2); break; // Key 2 LED2 反転
case 0xC0C4: playSong(3); break; // Key 3 LED3 反転
case 0xC024: playSong(4); break; // Key 4 LED4 反転
case 0xC0A4: playSong(5); break; // Key 5 全消灯
case 0xC064: playSong(6); break; // Key 6 全反転
case 0xC0E4: playSong(7); break; // Key 7 点滅1
case 0xC014: playSong(8); break; // Key 8 点滅2
case 0xC094: playSong(9); break; // Key 9 点滅3
case 0xC054: playSong(10); break; // Key 10 点滅4
case 0xC0D4: playSong(11); break; // Key 11 点滅5
case 0xC034: playSong(12); break; // Key 12 点滅6
default: LATC = 0; break; // 他のKey 全消灯
}
}
}
} // while
}
//----------------------割込み処理------------------------
void interrupt isr(void){
// Ir信号がOnOffした ---------------------------------
if(IOCIF){ //IRsencerからの割込みを確認
IOCAF = 0; // 割込みフラッグをクリア
irRx(); // 受信処理 ----->
}
if(boxMode){ // LED Modeの時だけ
// Timer0からの割り込み
if(TMR0IF){
TMR0IF = 0;
led_isr(); // 点滅制御 ----->
}
if(CCP4IF){ // Randum Mode で
CCP4IF=0; // LEDを50mSで消灯
TMR5ON = 0;
if(boxMode == mRandum)LATC=0;
}
}
}