aitendoのFMラジオモジュールをPICで動かす。
最小構成で電池駆動にする。機能も最小とし、操作はプリセットした受信周波数を切り替えるボタンのみ。
■回路図
※ SDA, SCL線はラジオモジュール内でプルアップされている。
■PICについて
PIC16F1503は安価で入手可能。I2C通信ポートが使える。低電圧で動作。EEPROMは搭載していない。
■PICのプログラム
FMラジオモジュールのチップ(RDA1508M)に、放送受信に必要な設定を書き込むとラジオが起動する。後はスリープモードへ移行させ、メインプログラムは終了。
周波数切り替えの押しボタンが押されるとハードウェア割り込みにより受信周波数の設定を変更して、周波数の数値をチップに書き込む関数を起動する。
■参考にした情報
■PICのプログラム
FMラジオモジュールのチップ(RDA1508M)に、放送受信に必要な設定を書き込むとラジオが起動する。後はスリープモードへ移行させ、メインプログラムは終了。
周波数切り替えの押しボタンが押されるとハードウェア割り込みにより受信周波数の設定を変更して、周波数の数値をチップに書き込む関数を起動する。
/* // Project Name: FM_Radio_16F1503 // Date: 2021.10.24 // Target PIC: PIC16F1503 // Compiler: XC8 (ver.2.32) // */ /************************************ File name: main.c ************************************/ // CONFIG1 #pragma config FOSC = INTOSC // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled) #pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled) #pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) // CONFIG2 #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) #pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled) #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) #include <xc.h> #define _XTAL_FREQ 4000000 #define SW1 PORTAbits.RA5 //ch切り替えスイッチ(押すと 0, 離すと 1) // RDA5708M register 02H setting #define DHIZ 1 #define DMUTE 1 #define MONO 1 #define BASS 1 #define SEEKUP 0 #define SEEK 0 #define SKMODE 0 #define CLK_MODE 0b000 #define RDS_EN 0 #define NEW_METHOD 0 #define SOFT_RESET 0 #define ENABLE 1 // RDA5708M register 04H setting #define DE 0 #define AFC 1 // RDA5708M register 05H setting #define INT_MODE 1 #define SEEKTH 0b1000 #define bit7 1 //***プロトタイプ宣言***************************************************** void i2cTxData(char); void configCmd(void); void SleepIn(void); void i2cStart(void); void i2cStop(void); void reset(void); void send(unsigned char, unsigned char, unsigned char); void Freqset(void); //変数宣言と初期設定 char VOLUME=0x15; /音量設定の初期値 int freq[] = {8000, 8130, 8250, 9050, 9160, 9300}; char ch=0; int RcvFreq = 8000; /受信周波数の初期値
unsigned char num = sizeof freq / sizeof freq[0]; //////////// Main ////////////////////////////////// void main(void){ OSCCON = 0b01101000; // 4MHz __delay_ms(100); ANSELA = 0x0; // PortAをデジタルI/Oにする ANSELC = 0x0; // PortCをデジタルI/Oにする TRISA = 0b11100011; // RA0, RA1, RA5 をINPUTに TRISC = 0b11000011; // RC0(SCL)とRC1(SDA)をINPUTに SSPCON1 = 0x28; // I2Cマスター SSPSTAT = 0x00; SSPADD = 0x24; // I2C周波数100KHz for 4MHz WPUA = 0b00100000; // RA5 をプルアップ // 16F1503の PortCはプルアップ設定できない OPTION_REGbits.nWPUEN=0; //0 = Weak pull-ups are enabled by individual WPUx latch values __delay_ms(1000); reset(); __delay_ms(100); configCmd(); INTCONbits.IOCIE=1; //IOC(状態変化割り込み)Enable IOCAPbits.IOCAP5=1; //Port RA5(=SW1)ボタン割り込み INTCONbits.GIE=1; //INTグローバルEnable while(1){ SleepIn(); } } ///////////// Main ここまで ///////////////////////////// void i2cStart(void){ SEN = 1; // Start condition while(SEN); // Start condition } void i2cStop(void){ //i2c STOP SSP1IF = 0; // クリア PEN = 1; // Stop condition while(PEN); // Stop condition } void i2cTxData(char data){ SSP1IF = 0; // SSPBUF = data; // while(!SSP1IF); // } void send(unsigned char ch,unsigned char i,unsigned char j){ i2cStart(); i2cTxData(0x22); // スレーブアドレス 0010001+0 i2cTxData(ch); // channel i2cTxData(i); // upper i2cTxData(j); // lower i2cStop(); } void reset(void) { send(0x02,0x00,0x01); /ミュート状態にする } void configCmd(void){ unsigned char upper, lower; //02Hレジスタへの書き込み upper = 0; upper += DHIZ << 7; upper += DMUTE << 6; upper += MONO << 5; upper += BASS << 4; upper += SEEKUP<< 1; upper += SEEK; lower = 0; lower += SKMODE << 7; lower += CLK_MODE << 4; lower += RDS_EN << 3; lower += NEW_METHOD << 2; lower += SOFT_RESET << 1; lower += ENABLE; send(0x02, upper, lower); //send(0x02,0xf0,0x01); __delay_ms(100); //03Hレジスタへの書き込み Freqset(); //04Hレジスタへの書き込み upper = 0; upper += DE << 4; upper += AFC; lower = 0; send(0x04, upper, lower); //send(0x04,0x04,0x00); //05Hレジスタへの書き込み upper = 0; upper += INT_MODE << 7; upper += SEEKTH; lower = 0; lower += bit7 << 7; lower += VOLUME; send(0x05, upper, lower); //send(0x05,0x88,0x80+VOLUME); } void Freqset(void){ signed int reg_val; reg_val = (RcvFreq - 7600)/10; send(0x03, reg_val >> 2, (reg_val << 6) + 0x18); __delay_ms(100); } void SleepIn(void){ IOCAPbits.IOCAP5=1; //RA5(=SW1)ボタン割り込みON SLEEP(); } void __interrupt() isr(void) { if(IOCAFbits.IOCAF5){ //RA5(=SW1)による割り込みフラグ ch = (++ch >= num)? 0 : ch; RcvFreq = freq[ch]; //受信周波数の設定 Freqset(); IOCAFbits.IOCAF5=0; //割り込みフラグをクリア } } //end of the program
■参考にした情報
コメント