数字收音机参考程序
- 格式:docx
- 大小:25.17 KB
- 文档页数:11
#include<reg52.h>#define uchar unsigned char#define uint unsigned intuint key_=0;uint k_1=0;uint a_3=0;uint m1,m_1,m_4;uint a_4=0;uint k_2=0;uint i_1=0;uint n_0=1;uint l1=1;uint l2=1;uint z,p=1;uint j_=1;uint r_i=0x0427;double b1=0;uint a1=0;uint a2=0;uint FreqTune=0x0000;uint vol=0xa;const uchar FmAddr = 0x22;sbit SDA =P0^0;sbit SCL =P0^1;sbit KEY =P1^4;sbit KEYu=P1^0;sbit KEYd=P1^2;sbit KEY1=P1^1;sbit KEY2=P1^3;sbit rs=P0^5;sbit rw=P0^6;sbit en=P0^7;sbit P02=P0^2;sbit P03=P0^3;sbit P04=P0^4;uchar code table[]="0123456789."; uchar code table_[]="Mhz Vol:";uchar code table_1[]="RT";uchar code table1[]="Welcome";uchar code table2[]="Digital FMdevice"; uchar code table3[]="Please choose"; uchar code table_3[]="s ";uchar code table4[]="function keys"; uchar code table5[]=" -Interphone "; uchar code table6[]=" FM receiver "; uchar code table7[]=" -FM receiver "; uchar code table8[]=" FM transmitter"; uchar code table9[]=" -FM transmitter"; uchar code table10[]=" Transmit Data "; uchar code table11[]=" -Transmit Data "; uchar code table12[]=" Interphone "; uchar code table14[]="Waiting ";uchar code table15[]="............... "; uchar code table16[]=" Interphone "; uchar code table18[]=" FM RX ";uchar code table20[]=" FM TX ";uchar code table22[]=" TX DATA ";uchar code tabletp[]=" ";uchar codetable23[]={0x00,0x1F,0x0A,0x04,0x04,0x0 4,0x04,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F, };uchar codetable24[]={0x00,0x1F,0x0A,0x04,0x04,0x0 4,0x04,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0E,0x1E, };uchar codetable25[]={0x00,0x1F,0x0A,0x04,0x04,0x0 4,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0C,0x1C ,};uchar codetable26[]={0x00,0x1F,0x0A,0x04,0x04,0x0 4,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x18, } ;uchar codetable27[]={0x00,0x1F,0x0A,0x04,0x04,0x0 4,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, };uchar codetable28[]={0x00,0x1F,0x0A,0x04,0x04,0x0 4,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, };uchar codetable29[]={0x02,0x06,0x1E,0x1E,0x1E,0x1 E,0x06,0x02,};void Dela_y(uint c) //延时{int i=0;for(i=0;i<c;i++);}void DelayIT(uint del_1)//延时 10ms * del {uint i,j;for(i=0; i<del_1; i++)for(j=0; j<1827; j++);}void delay_lcd(uint n)//lcd延时{uint x,y;for(x=n;x>0;x--)for(y=110;y>0;y--);}void lcd_wcom(uchar com)//lcd写命令{rs=0;rw=0;P3=com;delay_lcd(5);en=1;en=0;}void lcd_wdat(uchar dat)//lcd写数据{rs=1;rw=0;P3=dat;delay_lcd(5);en=1;en=0;}void lcd_init()//lcd初始化{lcd_wcom(0x38);lcd_wcom(0x0c);lcd_wcom(0x06);lcd_wcom(0x01);}void OpenIIC(){SDA = 1;SCL = 1; Dela_y(5);SDA = 0; Dela_y(5);SCL = 0; Dela_y(5);}void CloseIIC(){SDA = 0 ;SCL = 1; Dela_y(5);SDA = 1; Dela_y(5);SCL = 1; SDA = 1; Dela_y(150); //防止过快的读取造成EPPROM 来不及反应}}void IICWriteByte( uchar byte ){uchar i=0;int f=30000;bit bitdata;for(i=0;i<8;i++){bitdata=byte>>(7-i) & 1;SDA = bitdata;SCL =1; Dela_y(5);SCL = 0; Dela_y(5);}SCL = 1;while(SDA && -f); Dela_y(5);SCL = 0; Dela_y(5);}void IICWrite(uchar uaddr, uchar romaddr, uint rdata,bit _16b){uchar temp;OpenIIC();IICWriteByte(uaddr);IICWriteByte(romaddr);if(_16b){temp =(uchar)((rdata>>8) & 0x00ff) ; IICWriteByte(temp);}temp = (uchar) (rdata & 0xff); IICWriteByte(temp);CloseIIC();}uchar IICReadByte(bit next){uchar buf =0,i=0;for(i=0;i<8;i++){buf <<=1;SCL = 1; buf |= SDA; Dela_y(5);SCL = 0; Dela_y(5);}if(next){SDA = 0; SCL = 1; Dela_y(5);SCL = 0; Dela_y(5); SDA = 1;}else{SDA = 1; SCL = 1; Dela_y(5);SCL = 0; Dela_y(5); SDA=0;}return buf;}uint IICRead(uchar uaddr, uchar ramAddr,bit _16b){uint buf;OpenIIC();IICWriteByte(uaddr);IICWriteByte(ramAddr);OpenIIC();IICWriteByte(uaddr | 0x01);if(_16b){buf = IICReadByte(1);buf = buf<<8;buf =buf|IICReadByte(0);}else{buf = IICReadByte(0);}CloseIIC();return buf;}uint FM_ReadReg(uchar regAddr)//读取FM 模块的寄存器{return IICRead(FmAddr,regAddr,1);}void FM_WriteReg(uchar regAddr,uint dat)//写FM模块的寄存器{IICWrite(FmAddr,regAddr,dat,1);}void FM_SetFreq_RX(uint FreqTune_1)//设置RX频道的频率87-1*,步进频率100k0x00{FM_WriteReg(3,(FreqTune_1<<6) |0x0010);}void FM_SetFreq__RX(uint FreqTune__1)//设置RX频道的频率65-90,步进频率100k 0x00{FM_WriteReg(53,0x28a);FM_WriteReg(53,0x384);FM_WriteReg(3,(FreqTune__1<<6) |0x001c);}void FM_SetVolume(uint vol_)//设置音量0x0{FM_WriteReg(5,vol_|=0x88a0);}void show(uint addr,double m)//lcd显示初始地址addr及数字xxx.x{uchar n;uchar _n=10;for(n=0;n<5;n++){if(n==0) _n=m/100;if(n==1) _n=((int)m/10)%10;if(n==2) _n=(int)m%10;if(n==3) _n=10;if(n==4) _n=((int)(m*10))%10;lcd_wcom(addr+n);lcd_wdat(table[_n]);}}void show_(uint a_ddr,double k_)//lcd显示初始地址addr及数字xx{uchar n;uchar _n=10;for(n=0;n<2;n++){if(n==0) _n=(int)k_/10;if(n==1) _n=(int)k_%10;lcd_wcom(a_ddr+n);lcd_wdat(table[_n]);}}void rssi(uint r_addr,int rssi) //LCD信号强度指示显示(地址,0——5){lcd_wcom(0x40);if(rssi==0){for(m1=0;m1<16;m1++){lcd_wdat(table28[m1]);}};if(rssi==1){for(m1=0;m1<16;m1++){lcd_wdat(table27[m1]);}};if(rssi==2){for(m1=0;m1<16;m1++){lcd_wdat(table26[m1]);}};if(rssi==3){for(m1=0;m1<16;m1++){lcd_wdat(table25[m1]);}};if(rssi==4){for(m1=0;m1<16;m1++){lcd_wdat(table24[m1]);}};if(rssi==5){for(m1=0;m1<16;m1++){lcd_wdat(table23[m1]);}};lcd_wcom(r_addr); //显示地址for(m1=0;m1<2;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(m1);} ;}void kanji()//开机画面{uchar m1;DelayIT(20);lcd_init(); //液晶初始化lcd_wcom(0x84); //显示地址for(m1=0;m1<7;m1++) //将table1[Welcome]中的数据依次写入1602显示{lcd_wdat(table1[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table2[Digital FMdevice]中的数据依次写入1602显示{lcd_wdat(table2[m1]);}DelayIT(100);lcd_init(); //液晶初始化lcd_wcom(0x81); //显示地址for(m1=0;m1<13;m1++) //将table3[Please choose]中的数据依次写入1602显示{lcd_wdat(table3[m1]); DelayIT(4) ;}lcd_wcom(0x80+0x41); //显示地址for(m1=0;m1<13;m1++) //将table4[function keys]中的数据依次写入1602显示{lcd_wdat(table4[m1]); DelayIT(5) ;}DelayIT(50) ;}void K_S()//主键盘扫描{if(a_3!=1)//有后退按键{a_3=1;if(k_1==0)//对讲机模式{lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table5[-Interphone]中的数据依次写入1602显示{lcd_wdat(table5[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table6[FM receiver]中的数据依次写入1602显示{lcd_wdat(table6[m1]);}};if(k_1==1)//收音机模式{lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table12[]中的数据依次写入1602显示{lcd_wdat(table12[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table7[]中的数据依次写入1602显示{lcd_wdat(table7[m1]);}};if(k_1==2)//FM发射模式{lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table6[]中的数据依次写入1602显示{lcd_wdat(table6[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table9[]中的数据依次写入1602显示{lcd_wdat(table9[m1]);}};if(k_1==3) //第四模式{lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table8[]中的数据依次写入1602显示{lcd_wdat(table8[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table11[]中的数据依次写入1602显示{lcd_wdat(table11[m1]);}};};if(KEYu==0) key_--;//按键判断if(KEYd==0) key_++;if(k_1!=key_%4) //有上下选择按键{k_1=key_%4;if(k_1==0){lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table5[]中的数据依次写入1602显示{lcd_wdat(table5[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table6[]中的数据依次写入1602显示{lcd_wdat(table6[m1]);}};if(k_1==1){lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table12[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table7[m1]);}};if(k_1==2){lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table6[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table9[m1]);}};if(k_1==3){lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table11[]中的数据依次写入1602显示{lcd_wdat(table8[m1]);}lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table11[m1]);}};DelayIT(30);};}使用道具举报13#枫霰中级会员发表于 2012-1-19 16:22:58|只看该作者接上:void mace()//主程序扫描{•串个门•加好友•打招呼•发消息if(k_1==0)//第一模式{for(;m_1>0;m_1--){m_4=8;lcd_init(); //液晶初始化for(;m_4<12;m_4++){lcd_wcom(0x80+0x44); //显示地址for(m1=0;m1<m_4;m1++) //将table15[ ]中的数据依次写入1602显示{lcd_wdat(table15[m1]);DelayIT(4);}}lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table16[m1]);}};z=1;};if(k_1==1) //第二模式{for(;m_1>0;m_1--){m_4=8;lcd_init(); //液晶初始化for(;m_4<12;m_4++){lcd_wcom(0x80+0x44); //显示地址for(m1=0;m1<m_4;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table15[m1]);DelayIT(4);}};lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<18;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table18[m1]);}};z=2;};if(k_1==2)//第三模式{for(;m_1>0;m_1--){m_4=8;lcd_init(); //液晶初始化for(;m_4<12;m_4++){lcd_wcom(0x80+0x44); //显示地址for(m1=0;m1<m_4;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table15[m1]);DelayIT(5);}};lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table20[m1]);}};z=3;};if(k_1==3&&k_2==1) //第四模式{for(;m_1>0;m_1--){m_4=8;lcd_init(); //液晶初始化for(;m_4<12;m_4++){lcd_wcom(0x80+0x44); //显示地址for(m1=0;m1<m_4;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table15[m1]);DelayIT(5);}};lcd_init(); //液晶初始化lcd_wcom(0x80); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table22[m1]);}};z=4;};}void main() //主程序{ uint z_1,Tune;P1=0xff;FM_WriteReg(2,0xd281);//rda5820地址FM_ReadReg(0x0b);P02=0;P03=0;kanji(); //开机画面while(1) //进入程序死循环{if(KEY2==0&&k_2<1) k_2++;//左右按键判断if(KEY1==0&&k_2>0) k_2--;if(k_2==0) //没有右按键{n_0=1;m_1=1;K_S(); //上下模式建扫描};if(k_2==1) //有右键{a_3=0;mace(); //模式扫描if(z==1) //第一模式{if(KEY==1){for(;p>0;p--) FM_SetFreq__RX(0x00);//设置频率65Mhzlcd_wcom(0x80+0x46); //显示地址for(m1=0;m1<8;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table_[m1]);} ;lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<1;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table_1[m1]);} ;for(;l1>0;l1--)l2=1;FM_WriteReg(0x40,0x0000);//进入接收模式if(KEYu==0&&KEY2==0&&vol<0xf)vol+=0x1;else if(KEYd==0&&KEY2==0&&vol>0x0)vol-=0x1;else if(KEYu==0&&Tune<20)a1++,Tune+=1;else if(KEYd==0&&Tune>0)a1--,Tune-=1; //声音,频率调节FreqTune=Tune*10;if(b1!=65+(double)Tune*1){b1=65+(double)Tune*1;FM_SetFreq__RX(FreqTune);//写入频率=65+tune};z_1=0xff&(FM_ReadReg(0x0a));FM_SetVolume(vol); //写入音量show(0x80+0x41,65+((double)z_1)/10);show_(0x80+0x4e,((double)vol)); //显示频率音量rssi(0x8d,(uint)((FM_ReadReg(0x0b)>>10)/5)); //显示信号强度if( ((FM_ReadReg(0x0b)>>10)/5) ){lcd_wcom(0x8f);for(m1=6;m1<7;m1++) //将s显示{lcd_wdat(table10[m1]);} ;};if( !((FM_ReadReg(0x0b)>>10)/5) ){lcd_wcom(0x8f);for(m1=0;m1<1;m1++) //将显示{lcd_wdat(table10[m1]);} ;};DelayIT(10);//延时 10ms * del};if(KEY==0){for(;l2>0;l2--){l1=1,FM_WriteReg(0x40,0x0001),FM_SetFreq__RX(FreqTune), lcd_wcom(0x80+0x40); //显示地址for(m1=0;m1<16;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(tabletp[m1]);} ;};FM_WriteReg(0x40,0x0001) ;z_1=0xff&(FM_ReadReg(0x0a));show(0x80+0x44,65+((double)z_1)/10);lcd_wcom(0x80+0x43); //显示地址for(m1=1;m1<2;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table_1[m1]);} ;if(KEYu==0&&KEY==0&&r_i<0x043b)r_i+=0x000c;//功率调节if(KEYd==0&&KEY==0&&r_i>0x0405)r_i-=0x000c;FM_WriteReg(0x42,r_i);rssi(0x80+0x4d,(uint)((r_i&0xff)/0x0c));DelayIT(10);//延时 10ms * del};};if(z==2) //第二模式{p=1;for(;j_>0;j_--)FM_SetFreq_RX(0x00);FM_WriteReg(0x40,0x0000);lcd_wcom(0x80+0x46); //显示地址for(m1=0;m1<8;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table_[m1]);} ;if(KEYu==0&&KEY2==0&&FreqTune<0xd2)a1+=10,FreqTune +=0x000a;else if(KEYd==0&&KEY2==0&&FreqTune>0x00)a1-=10,FreqTune-=0x000a;else if(KEYu==0&&KEY==0&&vol<0xf)a2++,vol+=0x1;else if(KEYd==0&&KEY==0&&vol>0x0)a2--,vol-=0x1;else if(KEYu==0&&FreqTune<0xd2)a1++,FreqTune+=0x0001; else if(KEYd==0&&FreqTune>0x00)a1--,FreqTune-=0x0001; if(b1!=87+(double)a1*0.1){b1=87+(double)a1*0.1;FM_SetFreq_RX(FreqTune);};FM_SetVolume(vol);z_1=0xff&(FM_ReadReg(0x0a));show(0x80+0x41,87+((double)z_1)/10);show_(0x80+0x4e,((double)vol));rssi(0x8d,(uint)((FM_ReadReg(0x0b)>>10)/5));if( ((FM_ReadReg(0x0b)>>10)/5) ){lcd_wcom(0x8f);for(m1=6;m1<7;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table10[m1]);} ;};if( !((FM_ReadReg(0x0b)>>10)/5) ){lcd_wcom(0x8f);for(m1=0;m1<1;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table10[m1]);} ;};DelayIT(10);//延时 10ms * del};if(z==3) //第三模式{ p=1;for(;j_>0;j_--)FM_SetFreq_RX(0x00);FM_WriteReg(0x40,0x0001) ;lcd_wcom(0x80+0x49); //显示地址for(m1=0;m1<3;m1++) //将table[]中的数据依次写入1602显示{lcd_wdat(table_[m1]);} ;if(KEYu==0&&KEY2==0&&FreqTune<0xd2)a1+=10,FreqTune +=0x000a;else if(KEYd==0&&KEY2==0&&FreqTune>0x00)a1-=10,FreqTune-=0x000a;else if(KEYu==0&&KEY==0&&r_i<0x043b)r_i+=0x000c;else if(KEYd==0&&KEY==0&&r_i>0x0405)r_i-=0x000c;else if(KEYu==0&&FreqTune<0xd2)a1++,FreqTune+=0x0001; else if(KEYd==0&&FreqTune>0x00)a1--,FreqTune-=0x0001; if(b1!=87+(double)a1*0.1){b1=87+(double)a1*0.1;FM_SetFreq_RX(FreqTune);};z_1=0xff&(FM_ReadReg(0x0a));FM_WriteReg(0x42,r_i);show(0x80+0x44,87+((double)z_1)/10);rssi(0x8d,(uint)((r_i&0xff)/0x0c));DelayIT(10);//延时 10ms * del};if(z==4) //第四模式{p=1;};};};}使用道具举报枫霰中级会员•串个门•加好友•打招呼14#发表于 2012-1-19 17:08:50|只看该作者本帖最后由枫霰于 2012-1-19 17:10 编辑RDA5820收音+发射模块PL102BH-20.pdf 资料•发消息近几天刚刚学了IIC总线控制,想亲自实践一下,就从众多IIC控制的芯片中找到了这个RDA5820模块,刚从网上淘回来就开始写控制它的C51程序,经过一周多努力终于调试成功。
这是一个单片机控制的收音机程序完整代码和原理图下载地址:/bbs/dpj-19294-1.html 下面我我截图的一个子程序.#include "STC12C5620AD.H"#include "EEPROM.H"#include "Channel_Handle.H"/********************** 声明外部变量**************************//********************** EEPROM 存储电台PLL*************************/void EEPROM_Save_PLL(uchar Index,uint Udata){uchar Temp_H;uchar Temp_L; //PLL转换缓存uchar EEPROM_H;uchar EEPROM_L; //EEPROM读取缓存Temp_H=Udata>>8;Temp_L=Udata%256;switch (Index){case 1:EEPROM_H=EEPROM_Read_Byte(0x00,0x02); //暂存N0.8电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x00,0x03); //暂存N0.8电台PLL高位EEPROM_Earse(0x00,0x00); //擦除第1扇区EEPROM_Write_Byte(Temp_H,0x00,0x00); //写入N0.1电台PLL高位EEPROM_Write_Byte(Temp_L,0x00,0x01); //写入N0.1电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x00,0x02); //写入N0.8电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x00,0x03); //写入N0.8电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 2:EEPROM_H=EEPROM_Read_Byte(0x02,0x02); //暂存N0.9电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x02,0x03); //暂存N0.9电台PLL高位EEPROM_Earse(0x02,0x00); //擦除第2扇区EEPROM_Write_Byte(Temp_H,0x02,0x00); //写入N0.2电台PLL高位EEPROM_Write_Byte(Temp_L,0x02,0x01); //写入N0.2电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x02,0x02); //写入N0.9电台PLL高EEPROM_Write_Byte(EEPROM_L,0x02,0x03); //写入N0.9电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 3:EEPROM_H=EEPROM_Read_Byte(0x04,0x02); //暂存N0.10电台PLL 高位EEPROM_L=EEPROM_Read_Byte(0x04,0x03); //暂存N0.10电台PLL 高位EEPROM_Earse(0x04,0x00); //擦除第3扇区EEPROM_Write_Byte(Temp_H,0x04,0x00); //写入N0.3电台PLL高位EEPROM_Write_Byte(Temp_L,0x04,0x01); //写入N0.3电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x04,0x02); //写入N0.10电台PLL 高位EEPROM_Write_Byte(EEPROM_L,0x04,0x03); //写入N0.10电台PLL 低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 4:EEPROM_H=EEPROM_Read_Byte(0x06,0x02); //暂存N0.11电台PLL 高位EEPROM_L=EEPROM_Read_Byte(0x06,0x03); //暂存N0.11电台PLL 高位EEPROM_Earse(0x06,0x00); //擦除第4扇区EEPROM_Write_Byte(Temp_H,0x06,0x00); //写入N0.4电台PLL高位EEPROM_Write_Byte(Temp_L,0x06,0x01); //写入N0.4电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x06,0x02); //写入N0.11电台PLL 高位EEPROM_Write_Byte(EEPROM_L,0x06,0x03); //写入N0.11电台PLL 低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 5:EEPROM_H=EEPROM_Read_Byte(0x08,0x02); //暂存N0.12电台PLL 高位EEPROM_L=EEPROM_Read_Byte(0x08,0x03); //暂存N0.12电台PLL 高位EEPROM_Earse(0x08,0x00); //擦除第5扇区EEPROM_Write_Byte(Temp_H,0x08,0x00); //写入N0.5电台PLL高位EEPROM_Write_Byte(Temp_L,0x08,0x01); //写入N0.5电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x08,0x02); //写入N0.12电台PLL 高位EEPROM_Write_Byte(EEPROM_L,0x08,0x03); //写入N0.12电台PLL 低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 6:EEPROM_H=EEPROM_Read_Byte(0x0a,0x02); //暂存N0.13电台PLL 高位EEPROM_L=EEPROM_Read_Byte(0x0a,0x03); //暂存N0.13电台PLL 高位EEPROM_Earse(0x0a,0x00); //擦除第6扇区EEPROM_Write_Byte(Temp_H,0x0a,0x00); //写入N0.6电台PLL高位EEPROM_Write_Byte(Temp_L,0x0a,0x01); //写入N0.6电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x0a,0x02); //写入N0.13电台PLL 高位EEPROM_Write_Byte(EEPROM_L,0x0a,0x03); //写入N0.13电台PLL 低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 7:EEPROM_H=EEPROM_Read_Byte(0x0c,0x02); //暂存N0.14电台PLL 高位EEPROM_L=EEPROM_Read_Byte(0x0c,0x03); //暂存N0.14电台PLL 高位EEPROM_Earse(0x0c,0x00); //擦除第7扇区EEPROM_Write_Byte(Temp_H,0x0c,0x00); //写入N0.7电台PLL高位EEPROM_Write_Byte(Temp_L,0x0c,0x01); //写入N0.7电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x0c,0x02); //写入N0.14电台PLL 高位EEPROM_Write_Byte(EEPROM_L,0x0c,0x03); //写入N0.14电台PLL 低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 8:EEPROM_H=EEPROM_Read_Byte(0x00,0x00); //暂存N0.1电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x00,0x01); //暂存N0.1电台PLL高位EEPROM_Earse(0x00,0x00); //擦除第1扇区EEPROM_Write_Byte(Temp_H,0x00,0x02); //写入N0.8电台PLL高位EEPROM_Write_Byte(Temp_L,0x00,0x03); //写入N0.8电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x00,0x00); //写入N0.1电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x00,0x01); //写入N0.1电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 9:EEPROM_H=EEPROM_Read_Byte(0x02,0x00); //暂存N0.2电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x02,0x01); //暂存N0.2电台PLL高位EEPROM_Earse(0x02,0x00); //擦除第2扇区EEPROM_Write_Byte(Temp_H,0x02,0x02); //写入N0.9电台PLL高位EEPROM_Write_Byte(Temp_L,0x02,0x03); //写入N0.9电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x02,0x00); //写入N0.2电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x02,0x01); //写入N0.2电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 10:EEPROM_H=EEPROM_Read_Byte(0x04,0x00); //暂存N0.3电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x04,0x01); //暂存N0.3电台PLL高位EEPROM_Earse(0x04,0x00); //擦除第3扇区EEPROM_Write_Byte(Temp_H,0x04,0x02); //写入N0.10电台PLL高位EEPROM_Write_Byte(Temp_L,0x04,0x03); //写入N0.10电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x04,0x00); //写入N0.3电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x04,0x01); //写入N0.3电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 11:EEPROM_H=EEPROM_Read_Byte(0x06,0x00); //暂存N0.4电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x06,0x01); //暂存N0.4电台PLL高位EEPROM_Earse(0x06,0x00); //擦除第4扇区EEPROM_Write_Byte(Temp_H,0x06,0x02); //写入N0.11电台PLL高位EEPROM_Write_Byte(Temp_L,0x06,0x03); //写入N0.11电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x06,0x00); //写入N0.4电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x06,0x01); //写入N0.4电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 12:EEPROM_H=EEPROM_Read_Byte(0x08,0x00); //暂存N0.5电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x08,0x01); //暂存N0.5电台PLL高位EEPROM_Earse(0x08,0x00); //擦除第5扇区EEPROM_Write_Byte(Temp_H,0x08,0x02); //写入N0.12电台PLL高位EEPROM_Write_Byte(Temp_L,0x08,0x03); //写入N0.12电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x08,0x00); //写入N0.5电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x08,0x01); //写入N0.5电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 13:EEPROM_H=EEPROM_Read_Byte(0x0a,0x00); //暂存N0.6电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x0a,0x01); //暂存N0.6电台PLL高位EEPROM_Earse(0x0a,0x00); //擦除第6扇区EEPROM_Write_Byte(Temp_H,0x0a,0x02); //写入N0.13电台PLL高位EEPROM_Write_Byte(Temp_L,0x0a,0x03); //写入N0.13电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x0a,0x00); //写入N0.6电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x0a,0x01); //写入N0.6电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 14:EEPROM_H=EEPROM_Read_Byte(0x0c,0x00); //暂存N0.7电台PLL高位EEPROM_L=EEPROM_Read_Byte(0x0c,0x01); //暂存N0.7电台PLL高位EEPROM_Earse(0x0c,0x00); //擦除第7扇区EEPROM_Write_Byte(Temp_H,0x0c,0x02); //写入N0.14电台PLL高位EEPROM_Write_Byte(Temp_L,0x0c,0x03); //写入N0.14电台PLL低位EEPROM_Write_Byte(EEPROM_H,0x0c,0x00); //写入N0.7电台PLL高位EEPROM_Write_Byte(EEPROM_L,0x0c,0x01); //写入N0.7电台PLL低位EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号break;case 15:EEPROM_Earse(0x0e,0x00); //擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号EEPROM_Write_Byte(Temp_H,0x0e,0x02); //写入N0.15电台PLL高位EEPROM_Write_Byte(Temp_L,0x0e,0x03); //写入N0.15电台PLL低位break;default:break;}}/********************** EEPROM 读取电台PLL*************************/uint EEPROM_Get_PLL(uchar Index){uint PLL_Temp;uchar Temp_H;uchar Temp_L;switch (Index){case 1: //NO.1电台PLLTemp_H=EEPROM_Read_Byte(0x00,0x00); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x00,0x01); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 2: //NO.2电台PLL Temp_H=EEPROM_Read_Byte(0x02,0x00); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x02,0x01); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 3: //NO.3电台PLL Temp_H=EEPROM_Read_Byte(0x04,0x00); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x04,0x01); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 4: //NO.4电台PLL Temp_H=EEPROM_Read_Byte(0x06,0x00); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x06,0x01); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 5: //NO.5电台PLL Temp_H=EEPROM_Read_Byte(0x08,0x00); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x08,0x01); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 6: //NO.6电台PLL Temp_H=EEPROM_Read_Byte(0x0a,0x00); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x0a,0x01); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;case 7: //NO.7电台PLL Temp_H=EEPROM_Read_Byte(0x0c,0x00); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x0c,0x01); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 8: //NO.8电台PLL Temp_H=EEPROM_Read_Byte(0x00,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x00,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 9: //NO.9电台PLL Temp_H=EEPROM_Read_Byte(0x02,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x02,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 10: //NO.10电台PLL Temp_H=EEPROM_Read_Byte(0x04,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x04,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 11: //NO.11电台PLL Temp_H=EEPROM_Read_Byte(0x06,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x06,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 12: //NO.12电台PLL Temp_H=EEPROM_Read_Byte(0x08,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x08,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 13: //NO.13电台PLL Temp_H=EEPROM_Read_Byte(0x0a,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x0a,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 14: //NO.14电台PLL Temp_H=EEPROM_Read_Byte(0x0c,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x0c,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;case 15: //NO.15电台PLL Temp_H=EEPROM_Read_Byte(0x0e,0x02); //获取PLL高位Temp_L=EEPROM_Read_Byte(0x0e,0x03); //获取PLL高位PLL_Temp=Temp_H<<8|Temp_L;break;default:break;}return PLL_Temp;}/********************** EEPROM 读取最后一次序号*************************/ uchar EEPROM_Get_Index(){uchar Index;Index=EEPROM_Read_Byte(0x0e,0x00);return Index;}/********************** EEPROM 写入最后一次序号*************************/ void EEPROM_Write_Index(uchar Index){EEPROM_Earse(0x0e,0x00); //首先擦除第8扇区EEPROM_Write_Byte(Index,0x0e,0x00); //写入电台序号}。
//******************************************************//功能:以LCD1602为显示的TEA5767模块的收音机//编译软件:KELI C//单片机:STC89C52 晶振:13.56MHZ#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define DELAY5US _nop_();_nop_();_nop_();_nop_();_nop_();//**************TEA5767模块接线方法********************sbit SDA=P2^6;sbit SCL=P2^7;//*************频率调节按键接线************************sbit Key1=P3^2;sbit Key2=P3^3;//==============LCD1602接口连接方法===================== /*-----------------------------------------------------|DB0-----P0.0 | DB4-----P0.4 | RW-------P2.3 ||DB1-----P0.1 | DB5-----P0.5 | RS-------P2.4 ||DB2-----P0.2 | DB6-----P0.6 | E--------P2.2 ||DB3-----P0.3 | DB7-----P0.7 |---------------------------------------------------*///================================================*/#define LCM_Data P0 //LCD1602数据接口#define Busy 0x80 //用于检测LCM状态字中的Busy标识sbit LCM_RW = P2^3; //读写控制输入端,LCD1602的第五脚sbit LCM_RS = P2^4; //寄存器选择输入端,LCD1602的第四脚sbit LCM_E = P2^2; //使能信号输入端,LCD1602的第6脚//*****************参数定义***************************** unsigned long int FM_FREQ; //频率unsigned short int FM_PLL; //PLLuchar idata sbuf[5]; // 数据发送缓冲区uchar idata numbyte;uchar idata numbyte_AMP;uchar idata ADDRESS_AMP;uchar idata ADDRESS_SEND; //TEA5767发送地址uchar idata ADDRESS_RECEIVE; //TEA5767接收地址uchar idata rbuf[5]; // 数据接收缓冲区uchar idata ampint[5];uchar bdata PLL_HIGH;uchar bdata PLL_LOW; //设定用于搜索和预设的可编程频率合成器uchar bdata I2C_byte1;//发送的五字节TEA5767可位寻址的设置值uchar bdata I2C_byte2;uchar bdata I2C_byte3;uchar bdata I2C_byte4;uchar bdata I2C_byte5;sbit MUTE =I2C_byte1^7;//如果MUTE=1,则左右声道被静音;MUTE=0,左右声道正常工作sbit SM = I2C_byte1^6; //SM=1,则处于搜索模式;SM=0,不处于搜索模式sbit SUD=I2C_byte3^7; //SUD=1,增加频率搜索;SUD=0,减小频率搜索uchar byte1;uchar byte2;uchar byte3;uchar byte4;uchar byte5;uchar num1,num2,num3,num4;uchar tab1[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};bit bdata NACK; // 错误标志位//**********相关函数声明**************************************void init(void); //TEA5767初始化void delay600ms(void); //延迟600msvoid delay100ms(void); //延迟100msvoid delay10ms();void delay1ms(void); //延迟1msvoid sendnbyte(uchar idata *sla, uchar n);//与sendbyte函数构成I2C数据发送函数void I2C_start(void); //I2C 传输开始void sendbyte(uchar idata *ch);void checkack(void); //检查应答讯号void stop(void); //I2C传输结束void AMP_sendnbyte(uchar idata *sla,uchar numbyte_AMP);void key_scan(void); //键扫描void search_up(void); //接收频率向上加void search_down(void); //接收频率向下减void setByte1Byte2(void); //设置第一第二字节频率void LCMInit(void);//LCD初始void DelayMs(uint Ms);//1MS基准延时程序void WriteDataLCM (uchar WDLCM);//LCD模块写数据void WriteCommandLCM (uchar WCLCM,BuysC); //LCD模块写指令uchar ReadStatusLCM(void);//读LCD模块的忙标void DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置显示一个字符void LCDshow(void);void DelayMs(uint Ms);//*****************主程序******************************void main(void){numbyte = 5;numbyte_AMP=5;ADDRESS_SEND = 0xC0;// TEA5767写地址1100 0000ADDRESS_RECEIVE=0XC1;//TEA5767读地址1100 0001 ADDRESS_AMP=0X8E;init(); // 初始化TEA5767LCMInit();//LCD初始LCDshow();while(1){key_scan(); //键扫描}}//**************按键扫描程序**************************void key_scan(void){if(Key1==0){delay10ms();if(Key1==0){while(Key1==0);search_up(); //频率向上LCDshow();delay600ms();}}if(Key2==0){delay10ms();if(Key2==0){while(Key2==0);search_down(); //频率向下LCDshow();delay600ms();}}}//*********************LCD1602显示程序********************* void LCDshow(void){num1=FM_FREQ/100000000;num2=(FM_FREQ%100000000)/10000000;num3=(FM_FREQ%10000000)/1000000;num4=(FM_FREQ%1000000)/100000;DisplayOneChar(0, 4,'F');//DisplayOneChar(0, 5,'M');//DisplayOneChar(0, 6,'R');//DisplayOneChar(0, 7,'a');//DisplayOneChar(0, 8,'d');//DisplayOneChar(0, 9,'i');//DisplayOneChar(0, 10,'o');//DisplayOneChar(1, 4, tab1[num1]);DisplayOneChar(1, 5, tab1[num2]);DisplayOneChar(1, 6, tab1[num3]);DisplayOneChar(1, 7, '.');DisplayOneChar(1, 8, tab1[num4]);DisplayOneChar(1, 9,'M');//DisplayOneChar(1, 10,'H');//DisplayOneChar(1, 11,'Z');//}/*==================================================================== ==LCM初始化====================================================================== */void LCMInit(void){LCM_Data = 0;WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号DelayMs(5);WriteCommandLCM(0x38,0);DelayMs(5);WriteCommandLCM(0x38,0);DelayMs(5);WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); //关闭显示WriteCommandLCM(0x01,1); //显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0C,1); // 显示开及光标设置DelayMs(100);}//==============================LCD1602显示子程序================================================// 写数据函数: E =高脉冲RS=1 RW=0//===================================================================== =*/void WriteDataLCM(uchar WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;LCM_RS = 1;LCM_RW = 0;LCM_E = 0; //若晶振速度太高可以在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}/*==================================================================== 写指令函数: E=高脉冲RS=0 RW=0====================================================================== */void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCM(); //根据需要检测忙LCM_Data = WCLCM;LCM_RS = 0;LCM_RW = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;}/*==================================================================== 正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;DB7: 0 LCD控制器空闲,1 LCD控制器忙。
TEA5767完整收音机程序/*tea5767完整程序*///********************************************************* *******************************************/#include <reg52.h>#include <intrins.h>/********************************************************** *************************/#define max_freq 108000 //108Mhz#define max_pll 0x339b //108MHz时的pll.#define min_pll 0x299d //87.5MHz时的pll.#define Add_Freq 1#define Dec_Freq 0#define ATIIcxxDriverAddressW 0xC0#define ATIIcxxDriverAddressR 0xC1#define _Nop() _nop_(),_nop_(),_nop_(),_nop_(),_nop_() /*定义空指令*/#define LED P0void Initialization(void);void Get_Pll(void);void Get_Frequency(void);void Search(unsigned char mode);void Auto_Search(unsigned char mode);unsigned char GetKey();void Delay(unsigned char Time);void Led_Display(unsigned long i);void DelayD(unsigned char Time);unsigned char GetKey();void Delay(unsigned char Time);void ATIICxx_PWrite(unsigned char *McuAddress,unsigned char count);void ATIICxx_PRead(unsigned char *McuAddress,unsigned char count);void I2C_Send_Byte(unsigned char sendbyte);unsigned char I2C_Receive_Byte(void);void I2C_Start(void);void I2C_Stop(void);void I2C_Ack(void);void I2C_Noack(void);/********************************************************** ***********//* IIC读写程序芯片型号*/sbit I2C_SCK=P3^0; /*实时时钟时钟线引脚 */sbit I2C_SDA=P3^1; /*实时时钟数据线引脚 */sbit k1=P1^7;sbit k2=P1^6;sbit k3=P1^5;sbit k4=P1^4;/********************************************************** ***********//********************************************************** **************/sbit ge=P2^3;sbit shi=P2^2;sbit bai=P2^1;sbit qan=P2^0;unsigned chartab[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共阳//0, 1, 2 3 4 5 6 7 8 9/************************************************************************/unsigned char radio_write_data[5]={0x2d,0x56,0x20,0x11,0x00}; //初始化写入TEA5767的数据(FM89.8Mhz)unsigned char radio_read_data[5];unsigned int Pll_Data;unsigned long Frequency_Data;/***********************************************************************************/void Initialization(void){TMOD = 0x11;TH0 = 0x5d;TL0 = 0x3d;TR0 = 0; //25msTH1 = 0x5d;TL1 = 0x3d;TR1 = 0; //25msT2CON = 0x30;RCAP2H = 0xFE;TH2 = RCAP2H;RCAP2L = 0xFB;TL2 = RCAP2L;TR2 = 0; //2400bpsPCON = 0x00;SCON = 0xD0;IP = 0x14;EX0 = 1;IT0 = 1;ET0 = 1;EX1 = 1;IT1 = 1;ES = 0;EA = 0;}/********************************************************** *************************///读TEA5767状态,并转换成频率void Radio_Read(void){unsigned char temp_l,temp_h;Pll_Data = 0;ATIICxx_PRead(&radio_read_data[0],5);temp_l = radio_read_data[1];temp_h = radio_read_data[0];temp_h &= 0x3f;Pll_Data = temp_h*256+temp_l;Get_Frequency();}/********************************************************** *************************///由PLL计算频率void Get_Frequency(void){unsigned char hlsi;unsigned int npll = 0;npll = Pll_Data;hlsi = radio_read_data[2]&0x10;if (hlsi)Frequency_Data = (unsignedlong)((float)(npll)*(float)REFERENCE_FREQ*(float)0.25-225); //频率单位:KHzelseFrequency_Data = (unsignedlong)((float)(npll)*(float)REFERENCE_FREQ*(float)0.25+225); //频率单位:KHz}/********************************************************** *************************///由频率计算PLLvoid Get_Pll(void){unsigned char hlsi;hlsi = radio_read_data[2]&0x10;if (hlsi)Pll_Data = (unsignedint)((float)((Frequency_Data+225)*4)/(float)REFERENCE_FREQ); //频率单位:kelsePll_Data = (unsignedint)((float)((Frequency_Data-225)*4)/(float)REFERENCE_FREQ); //频率单位:k}/********************************************************** *************************///手动设置频率,mode=1,+0.1MHz; mode="0:-0".1MHz ,不用考虑TEA5767用于搜台的相关位:SM,SUDvoid Search(unsigned char mode){Radio_Read();if(mode){Frequency_Data += 100;if(Frequency_Data > max_freq)Frequency_Data = min_freq;}else{Frequency_Data -= 100;if(Frequency_Data < min_freq)Frequency_Data = max_freq;}Get_Pll();radio_write_data[0] = Pll_Data/256;radio_write_data[1] = Pll_Data%256;radio_write_data[2] = 0x41;radio_write_data[3] = 0x11;radio_write_data[4] = 0x40;ATIICxx_PWrite(&radio_write_data[0],5);}/********************************************************** *************************///自动搜台,mode=1,频率增加搜台; mode="0:频率减小搜台". void Auto_Search(unsigned char mode){Radio_Read();Get_Pll();if(mode){radio_write_data[2] = 0xb1;if(Pll_Data > max_pll){Pll_Data = min_pll;}}else{radio_write_data[2] = 0x41;if(Pll_Data < min_pll){Pll_Data = max_pll;}}radio_write_data[0] = Pll_Data/256+0x40;radio_write_data[1] = Pll_Data%256;radio_write_data[3] = 0x11;radio_write_data[4] = 0x40;ATIICxx_PWrite(&radio_write_data[0],5);Radio_Read();while(!(radio_read_data[0]&0x80)) //RF电台就绪标志{Radio_Read();}}/********************************************************** *************************/void main(void){//0x2d,0x56,0x20,0x11,0x00unsigned long temp;Initialization();radio_write_data[0] =0x2A;radio_write_data[1] =0xB6;radio_write_data[2] =0x41;radio_write_data[3] =0x11;radio_write_data[4] =0x40;ATIICxx_PWrite(&radio_write_data[0],5);//初始化TEA5767(89.8Mhz)Frequency_Data = 89800;while(1){ temp= Frequency_Data;Led_Display(Frequency_Data);if( k1 == 0){ DelayD(2);while(k1 == 0);//等待键松开Search(Add_Freq);}if( k2 == 0){ DelayD(2);while(k2 == 0);//等待键松开Search(Dec_Freq);}if( k3 == 0){ DelayD(2);while(k3 == 0);//等待键松开Auto_Search(Add_Freq);}if( k4 == 0){ DelayD(2);while(k4 == 0);//等待键松开Auto_Search(Dec_Freq);}}}/********************************************************** ***********/struct bytedata_2{unsigned char ByteH;unsigned char ByteL;};union int2byte{unsigned int IntData;struct bytedata_2 ByteData;};/********************************************************** ***********///启动I2C总线,退出时SCL为低void I2C_Start(void){I2C_SDA=1; /*发送起始条件的数据信号*/_Nop();I2C_SCK=1;_Nop();_Nop();_Nop();_Nop();_Nop();/*起始条件建立时间大于4.7us,延时*/I2C_SDA=0; /*发送起始信号*/_Nop();_Nop();_Nop();_Nop();_Nop(); /* 起始条件锁定时间大于4μs*/I2C_SCK=0; /*钳住I2C总线,准备发送或接收数据 */_Nop();_Nop();_Nop();_Nop();_Nop();/*起始条件建立时间大于4.7us,延时*/}//*停止I2C总线void I2C_Stop(void){I2C_SCK=0;I2C_SDA=0; /*发送结束条件的数据信号*/_Nop(); /*发送结束条件的时钟信号*/I2C_SCK=1; /*结束条件建立时间大于4μs*/_Nop();_Nop();_Nop();_Nop();_Nop();I2C_SDA=1; /*发送I2C总线结束信号*/}//MCU等待应答位(返回0表示应答)bit I2C_WaitAck(void){unsigned char ucErrTime = 200; //因故障接收方无ACK,超时值。
多媒体收音机操作方法
1. 打开收音机,并确保电源插头已连接到电源插座。
2. 选择收音模式,一般来说,多媒体收音机有AM、FM调频和DAB数字广播等收音模式,需要根据自己所在的地区和需要收听的电台选择相应的收音模式。
3. 搜索电台,多数收音机可以通过自动搜索或手动搜索找到所需的电台频率。
手动搜索是指使用频率调谐旋钮或数字键盘来逐步扫描频率范围,以找到电台。
而自动搜索则是收音机自动扫描频率范围,找到电台后停止搜索。
4. 手动调节音量。
通过旋钮或按键调节收音机的音量大小。
5. 使用附带的耳机或扬声器播放电台节目。
多数多媒体收音机配备了内置的扬声器,可以直接播放电台节目,也可以连接耳机用于个人收听。
6. 更改音质设置,一些多媒体收音机具有音效、均衡器和音调等调节功能,可以根据个人偏好更改各种音质设置。
* 晶振:8M*/#include <reg52.h>#include <string.h>#define ChannelCount 50 //最多支持多少个台,因为常驻内存,多了RAM放不下#define uchar unsigned char#define uint unsigned inttypedef struct{uchar Freq;uchar Rssi;}ChannelInfo;sbit SDA = P2^0;sbit SCL = P2^1;sbit key1 = P3^4;sbit key2 = P2^7;sbit key3 = P2^6;sbit key4 = P2^5; // P3^7;sbit LcdEn = P3^4;sbit LcdRs = P3^5;uchar Channel = 0;uchar FreqTune = 0;const uint MinFreq = 870; //起始频率* 100KHzconst uint MaxFreq = 1080; //最高频率* 100KHzconst uchar FmAddr = 0×22; //FM模块IIC 地址const uchar EpAddr = 0xA0; //24C02 EPPRom 的地址uchar RSSI = 0; //信号强度uchar ChannelTune[ChannelCount];uchar code LevlChar[5][8] ={{0x1F,0×11,0x0A,0×04,0×04,0×04,0×04,0×04},{0×00,0×00,0×00,0×00,0×00,0×00,0×06,0x1E},{0×00,0×00,0×00,0×00,0×06,0x1E,0x1E,0x1E}, //显示型号强度的自定义字符{0×00,0×00,0×06,0x1E,0x1E,0x1E,0x1E,0x1E},{0×06,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E}};uchar vol = 0×8; //音量0~0xFuchar Func = 0×0; //当前功能号bit AutoScan = 0; //标记当前是不是在自动搜台bit Mute = 0; //标记是否被静音uchar KeyNumber = 0;void OpenIIC();void CloseIIC();void IICWrite(uchar uaddr, uchar romaddr, uint rdata,bit _i6b);void IICWriteByte( uchar byte );uint IICRead(uchar uaddr, uchar romaddr,bit _i6b);uchar IICReadByte(bit next);void FM_SetFreq();void FM_SetVolume();uint FM_ReadReg(uchar regAddr); //读取FM模块的寄存器void FM_WriteReg(uchar regAddr,uint dat); //写FM模块的寄存器uchar FM_GetRSSI(); //获取当前的信号强大void Delay(uint c);bit KeyScan();void BeginScan();void Lcd_DispNumber(uint number);void Lcd_Init();void Lcd_Comm(uchar cmd);void Lcd_Data(uchar dat);void Lcd_String(char* dat);void Lcd_DispRssi();void Lcd_DispFreq();void Lcd_Refresh();void Lcd_DispDiscript();void Eprom_LoadInitData();uint Eprom_Read(uchar addr,bit _16bit);void Eprom_Write(uchar addr,uint dat,bit _16bit);void main(){P3 = 0xff;P2 = 0xff;Delay(10000); //延时,等待外部FM模块的启动Eprom_LoadInitData(); //从EppRom 加载频道音量等信息 FM_WriteReg(2,0xd281); //启动FM模块FM_SetVolume(); //设置启动音量FM_SetFreq(); //设置默认频道的频率Lcd_Init();Lcd_Refresh();while(1){if( KeyScan()){Lcd_Refresh();}}}void Eprom_LoadInitData(){uint result = 0;int i=0;result =Eprom_Read(0,0);if(result>0){ vol = (uchar)result –1;}result =Eprom_Read(1,0);Channel = (uchar)result;for(i=0;i<ChannelCount;i++){result =Eprom_Read(i * 2 + 2,1);ChannelTune[i] = result;}FreqTune = ChannelTune[Channel];}void Eprom_Write(uchar addr,uint dat,bit _16bit) {IICWrite(EpAddr,addr,dat,_16bit);}uint Eprom_Read(uchar addr,bit _16bit){return IICRead(EpAddr,addr,_16bit);}uint FM_ReadReg(uchar regAddr){return IICRead(FmAddr,regAddr,1);}void FM_WriteReg(uchar regAddr,uint dat) {IICWrite(FmAddr,regAddr,dat,1);}void FM_SetFreq(){FM_WriteReg(3,(FreqTune<<6) | 0×10);}void FM_SetVolume(){uint reg2H;if(vol>0){if(Mute){reg2H = FM_ReadReg(2);reg2H |= 0×4000;FM_WriteReg(2,reg2H);}FM_WriteReg(5,vol);}else{Mute = 1;reg2H = FM_ReadReg(2);reg2H &= 0xBFFF;FM_WriteReg(2,reg2H);}Eprom_Write(0,vol+1,0);}void Lcd_Init(){uchar CGRamAddr = 0×40;int i,j;LcdEn = 0;Lcd_Comm(0×38);Lcd_Comm(0x0c);Lcd_Comm(0×06);Lcd_Comm(0×01);for(j=0;j<5;j++){Lcd_Comm(CGRamAddr + 8 * j); //建立自定义字符(显示信号强度的) for(i=0;i<8;i++){Lcd_Data(LevlChar[j][i]);Delay(510);}}}void Lcd_Comm(uchar cmd){LcdRs =0;P0 = cmd;Delay(50);LcdEn = 1;Delay(50);LcdEn = 0;}void Lcd_Data(uchar dat){LcdRs = 1;P0 = dat;LcdEn = 1;Delay(50);LcdEn = 0;}void Lcd_String(char* dat){char *p;int j, i=strlen(dat);for(j=0;j<i;j++){p=dat + j;Lcd_Data(*p);}}void Lcd_DispRssi(){int i;Lcd_Comm(0×80);for(i=0;i<5;i++){Lcd_Data(‘‘);}RSSI = FM_GetRSSI();Lcd_Comm(0×80);Lcd_Data(0×00);if(RSSI>=1) Lcd_Data(0×01);if(RSSI>=2) Lcd_Data(0×02);if(RSSI>=3) Lcd_Data(0×03);if(RSSI>=4) Lcd_Data(0×04);}void Lcd_DispFreq(){uint curFreq = MinFreq + FreqTune;int i;Lcd_Comm(0×85);for(i=5;i<16;i++){Lcd_Data(‘‘);}Lcd_Comm(0×80+6);if(curFreq>=1000)Lcd_Data(48 +curFreq /1000 % 10); Lcd_Data(48 +curFreq /100 % 10);Lcd_Data(48 +curFreq /10 % 10);Lcd_Data(‘.’);Lcd_Data(48 + curFreq % 10);Lcd_Data(‘M’);Lcd_Data(‘H’);Lcd_Data(‘Z’);}void Lcd_DispDiscript(){int i;Lcd_Comm(0×80+0×40);for(i=0;i<15;i++){Lcd_Data(‘‘);}Lcd_Comm(0×80+0×40);switch(Func){case 0:Lcd_String(“Channel:”);Lcd_DispNumber(Channel+1);break;case 1:Lcd_String(“Volume:”);Lcd_DispNumber(vol);break;case 2:Lcd_String(“Tune”);break;case 3:Lcd_String(“Auto Scan”);}}void Lcd_Refresh(){Lcd_DispRssi();Lcd_DispFreq();Lcd_DispDiscript();}void Lcd_DispNumber(uint number){int i=0,len;char str[6]={‘\0′,’\0′,’\0′,’\0′,’\0′,’\0′}; char temp;dostr[i++] = ’0′+ (number % 10); number /= 10;}while(number) ;len = strlen(str);for(i=0;i<len/2;i++){temp = str[i];str[i] = str[len-i-1];str[len-i-1] = temp;}Lcd_String(str);}bit KeyScan(){bit keyRel = 0; //按键释放检测char value=0;int i;uint temp;if(AutoScan) return 0;if(KeyNumber==0){if(key3==0){Delay(50);if(key3==0){KeyNumber =3;}}if(key4==0){Delay(50);if(key4==0){KeyNumber=4;}}if(key2==0){Delay(50);if(key2==0)KeyNumber=2;}}return 0;}else{switch(KeyNumber){case 1:if(key1==1)keyRel = 1; break;case 2:if(key2==1)keyRel = 1; break;case 3:if(key3==1)keyRel = 1; break;case 4:if(key4==1)keyRel = 1; break;}if(keyRel){switch(KeyNumber){case 2:Func++;if(Func>3) Func = 0;break;case 3:value = -1;break;case 4:value = 1;break;}if(KeyNumber>2){if(Func==0){if((value > 0 && Channel<ChannelCount) || (value<0 && Channel > 0)) {Channel+=value;FreqTune= ChannelTune[Channel];FM_SetFreq();Eprom_Write(1,Channel, 0);}else if(Func==1){if((value > 0 && vol<0xF) || (value<0 && vol > 0)){vol+=value;FM_SetVolume();}}else if(Func==2){if((value > 0 && FreqTune<0xd2) || (value<0 && FreqTune > 0)) {FreqTune+=value;ChannelTune[Channel] = FreqTune;FM_SetFreq();Eprom_Write(Channel * 2 + 2 ,FreqTune,1);}}else if(Func==3) //开始自动扫描{AutoScan = 1;BeginScan();AutoScan = 0;Channel = 0;FreqTune = ChannelTune[0];Func = 0;FM_SetFreq();//覆盖EppRom中的所有的频道for(i=0;i<ChannelCount;i++){temp = ChannelTune[i];Eprom_Write(i * 2+2,temp,1);}Eprom_Write(0×01,0,0); //重置EPPROM中的频道号为0}}KeyNumber=0;}return keyRel;}}//全自动搜索void BeginScan(){uint state;int i=0,count=0;bit cmp = 0;uint seekth = 0×8; //灵敏度0~127,默认为8 灵敏度越低越可能搜索到假台,高了可能一些信号弱一点的频道被跳过。
RDA5807m驱动程序+ IIC 程序/****************************************************************************** ************ 介绍: RD5807M收音机程序供电3.3v 主控使用51单片机显示使用LCD1602** 作者: 胖子** 时间:2016-1-5** 地点:桂林电子科技大学******************************************************************************* **********/#include <reg51.h>#include <string.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define ulint unsigned long int#define lint long intuchar code xian[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};uchar code hang[]={0xfe,0xfd,0xfb,0xf7}; //矩阵键盘扫描使用//RDA 的寄存器地址#define RDA_R00 0X00 //读出16个位的ID =0X5800#define RDA_R02 0X02 //DHIZ[15],DMUTE[14]静音,MONO[13]声道,BASS[12]重低音,SEEKUP[9],SEEK[8],SKMODE[7],CLK_MODE[6:4]时钟源选择,SOFTRESET[1]软复位,ENABLE[0]电源使能#define RDA_R03 0X03 //CHAN[15:6],TUNE[4],BAND[3:2],SPACE[1:0] 设置频率带宽步长#define RDA_R04 0X04 //STCIEN[14],DE[11],I2Senable[6],#define RDA_R05 0X05 //INT_MODE[15],SEEKTH[14:8](设定自动搜索信号强度阀值),LNA_PORT_SEL[7:6]=0b10,LNA_ICSEL_BIT[5:4],VOLUME[3:0]音量;#define RDA_R0A 0X0A //STC[14]seek complete SF[13]seek fail readchan[9:0]当前频道#define RDA_R0B 0X0B //RSSI[15:9],FM TRUE[8]当前频道是一个节目台#define RDA_READ 0X23 //读RDA5807#define RDA_WRITE 0X22 //写RDA5807//IO操作函数sbit SDA=P2^1;sbit SCL=P2^0;sbit RW =P1^1;sbit RS=P1^0;sbit EN=P2^5;uchar code a[]="FM: . ";uchar code b[]="Vol: RSSI: ";uchar code shu[]="0123456789";uchar num ;void delayms(uint x) //延迟程序uint i,j;for(i=x;i>0;i--)for(j=113;j>0;j--);}/*********************************************** 矩阵键盘程序********************************************************************/uchar ScanKey() //矩阵键盘扫描返回值是当前按键数值如没按下则返回值为零{uint x,y;for(x=0;x<4;x++){uchar temp,gaowei;P3=hang[x]; //分行置零temp=P3&0xf0;if(temp!=0xf0){delayms(10);if(temp!=0xf0){gaowei=P3/16; //判断是第几列的按键按下,将数据装入高四位switch(gaowei){case 0xe:y=0; break;case 0xd:y=1; break;case 0xb:y=2; break;case 0x7:y=3; break;}while(temp!=0xf0){temp=P3&0xf0;}return xian[x][y];}}}return 0;}/******************************************************* LCD1602程序************************************************************************/void write_com(unsigned char com)RS=0;P0=com;delayms(5);EN=1;delayms(5);EN=0;}void write_data(unsigned char date){RS=1;P0=date;delayms(5);EN=1;delayms(5);EN=0;}void init_1602(){P0=0xc0;RW =0;EN=0;write_com(0x38); //éè??16*2??ê?£?5*7μ??ó£?8??êy?Y?úwrite_com(0x0c); //éèa??ê?£?2ê?1a±êwrite_com(0x06); //D′ò×?·?oóμ??·ó1write_com(0x01); //??êá?£?êy?Yá?}void DisplayFrq(float Frq) //显示频率{uint F;F=Frq*10;write_com(0x80+3);write_data(shu[F/1000]);delayms(1);write_data(shu[F/100%10]);delayms(1);write_data(shu[F/10%10]);delayms(1);write_com(0x80+7);write_data(shu[F%10]);delayms(1);}void DisplayVol(uint Vol) //显示音量{write_com(0x80+0x40+4);write_data(shu[V ol/10]);delayms(1);write_data(shu[V ol%10]);delayms(1);}void Display_mute() //显示静音{write_com(0x80+0x40+4);write_data('x');delayms(1);write_data('x');delayms(1);}void Display_RSSI(uint RSSI) //显示信号强度{write_com(0x80+0x40+14);write_data(shu[RSSI/10]);delayms(1);write_data(shu[RSSI%10]);delayms(1);}/*----------------------------------------IIC通信程序---------------------------------------------------*/ void IIC_delayms() //用于IIC延时{_nop_();_nop_();_nop_();_nop_();}void OpenIIC() //IIC启动信号{SDA=1;SCL=1;IIC_delayms();SDA=0;IIC_delayms();SCL=0;}void CloseIIC() //IIC停止信号{SCL=0;SDA=0;IIC_delayms();SCL=1;SDA=1;IIC_delayms();}uchar IIC_Wait_Ack(void) //IIC发送字节后等待从机发送响应信{uchar ucErrTime=0;SDA=1;IIC_delayms();SCL=1;IIC_delayms();while(SDA==1){ucErrTime++;if(ucErrTime>250){CloseIIC();return 1;}}SCL=0;return 0;}void IIC_Ack(void) //发送应答信号{SCL=0;SDA=0; //0±íê?ó|′eIIC_delayms();SCL=1;IIC_delayms();SCL=0;}void IIC_NAck(void) //IIC 非应答信号{SCL=0;SDA=1;IIC_delayms();SCL=1;IIC_delayms();SCL=0;}void IICsendByte(uchar txd) //IIC·写一个字节{uchar t;SCL=0;for(t=0;t<8;t++){if(((txd&0x80)>>7)==1)SDA=1;elseSDA=0;txd<<=1;IIC_delayms();SCL=1;IIC_delayms();SCL=0;IIC_delayms();}}uchar IICReadByte(unsigned char ack) //IIC读一个字节{unsigned char i,receive=0;SDA=1; //51单片机讲引脚置高可设为输入引脚for(i=0;i<8;i++ ){SCL=0;IIC_delayms();SCL=1;receive<<=1;if(SDA==1)receive++;IIC_delayms();}if (!ack)IIC_NAck();elseIIC_Ack();return receive;}uint ReadReg(uchar regAddr) //芯片读寄存器{uint buf;OpenIIC();IICsendByte(RDA_WRITE); //发送芯片地址方向为写IIC_Wait_Ack();IICsendByte(regAddr); //发送寄存器地址IIC_Wait_Ack();OpenIIC();IICsendByte(RDA_READ); // 发送芯片地址方向为读IIC_Wait_Ack();buf = IICReadByte(1);buf = buf<<8;buf =buf|IICReadByte(0);CloseIIC();return buf;}void WriteReg(uchar regAddr,uint val) //芯片写寄存器{OpenIIC();IICsendByte(RDA_WRITE); //发送芯片地址方向为写IIC_Wait_Ack();IICsendByte(regAddr); //发送寄存器地址IIC_Wait_Ack();IICsendByte(val>>8);IIC_Wait_Ack();IICsendByte(val&0XFF);IIC_Wait_Ack();CloseIIC();}void Vol_Set(uchar vol) //音量设置0~15{uint temp=0;temp=ReadReg(RDA_R05);temp&=0xfff0;WriteReg(0x05,vol|temp) ;}void Mute_Set(uchar mute) //静音设置1为静音0为不静音{uint temp=0;temp=ReadReg(0X02);if(!mute)temp|=1<<14;else temp&=~(1<<14);WriteReg(0X02,temp) ;}void Bass_Set(uchar bass) //频带设置{uint temp=0;temp=ReadReg(0X02);if(bass)temp|=1<<12;else temp&=~(1<<12);WriteReg(0X02,temp) ;}uchar Rssi_Get(void) //信号强度获取0~63{uint temp=0;temp=ReadReg(0X0B);temp=(temp>>9)&0x7f;return temp;}void Seekth_Set(uint rssi) //自动搜台信号阈值强度0~15 默认为8 数值越低搜到的台越多{uint temp;rssi = rssi & 0xf;temp=ReadReg(0X05);temp&=~(0xf<<8);temp|= rssi<<8;WriteReg(0X05,temp) ;}void Seek_direction(uchar direction) //搜台方向1向上搜索0向下搜索{uint temp;temp=ReadReg(RDA_R02);temp&=~(1<<9);if(direction == 1)temp|= 1<<9;// if(direction == 0)// temp|= 0<<9;WriteReg(0X05,temp) ;}void Freq_Set(uint freq) //频率设置单位是:10KHz 6500~10800{uint temp;uchar spc=0,band=0;uint fbtm,chan;temp=ReadReg(0X03);temp&=0X001F;band=(temp>>2)&0x03;spc=temp&0x03;if(spc==0)spc=10;else if(spc==1)spc=20;else spc=5;if(band==0)fbtm=8700;else if(band==1||band==2)fbtm=7600;else{fbtm=ReadReg(0X53);fbtm*=10;}if(freq<fbtm)return;chan=(freq-fbtm)/spc;chan&=0X3FF;temp|=chan<<6;temp|=1<<4;WriteReg(RDA_R03,temp) ;delayms(20);// while((ReadReg(0X0B)&(1<<7))==0);}unsigned int seek_channel(void) //半自动搜台{unsigned long temp;temp=ReadReg(RDA_R02);temp |= (1<<8);WriteReg(RDA_R02,temp) ; //SEEK位置一使能自动搜台while( (ReadReg(RDA_R0A)&(1<<14)) == 0 ) // 等待STC位置一表示搜索完成{delayms(10); //?óê±10ms}temp = ((ReadReg(RDA_R0A)&0x3FF) * 100000 + 87000000)/10000 ; //获取当前频率return temp; //返回搜到电台频率单位是:10Khz}void FM_enable(uchar flag) //1 使能芯片0 禁用芯片{uint temp;temp=ReadReg(RDA_R02);if(flag ==1 )temp |=1;if(flag == 0)temp &= ~0x1;WriteReg(RDA_R02,temp);}void RDA_Init(void) //RDA3?ê??ˉ{WriteReg(RDA_R02,0x0002); //软复位delayms(30);WriteReg(RDA_R02,0xd081); //?§32.768Khz ?òé÷??μíò? á¢ì?éùSKMODE = 1÷μ?±??μê±í£?1WriteReg(RDA_R03,0x0000); //?μ?êéè?a87MHz £?2100Khz ?μ′??a87M~108MWriteReg(RDA_R04,0x0040); //?ù±WriteReg(RDA_R05,0X8882); //ò?á?éèavol=2 ÷·§?μ?a8FM_enable(1); //??Dé?μ?Seekth_Set(8); //自动搜台信号阈值强度0~15 默认为8 数值越低搜到的台越多}void display_1602(){write_com(0x80);for(num=0;num<34;num++){write_data(a[num]);delayms(5);}write_com(0x80+0x40);for(num=0;num<34;num++){write_data(b[num]);delayms(5);}}void main(){unsigned char Key_num=0,V ol=1,RSSI=0,mute=1;unsigned int RXFreq=8830,time=0;unsigned int Diantai[40]={8830};char Num=0,station=1;unsigned int test=7896;unsigned int temp=10;init_1602();display_1602();RDA_Init(); //RDA5807初始化Freq_Set(8830); //频率设置V ol_Set(2) ;DisplayFrq(88.3);DisplayVol(2); //显示音量while (1){time++;if(time>1000)Display_RSSI(Rssi_Get()); //显示信号强度Key_num=ScanKey();switch(Key_num){case 1: { if(RXFreq==8800)RXFreq=8800; //频率减else RXFreq-=10;Freq_Set(RXFreq);DisplayFrq(RXFreq/100.0);while(0!=ScanKey()); //按键释放break;}case 2:{ if(RXFreq==10800)RXFreq=10800;//频率加else RXFreq+=10;DisplayFrq(RXFreq/100.0);while(0!=ScanKey()); //按键释放break;}case 5: { //声音减if(V ol==0)V ol=0;elseV ol-=1;Vol_Set(V ol);DisplayV ol(V ol); //显示音量while(0!=ScanKey()); //按键释放break;}case 6:{ if(V ol==15)V ol=15; //声音加else V ol+=1;V ol_Set(V ol);DisplayV ol(V ol); //显示音量while(0!=ScanKey()); //按键释放break;}case 7:{ if(mute==1) //静音{Mute_Set(1);Display_mute(); //显示静音while(0!=ScanKey()); //按键释放mute=0;break;}if(mute==0){Mute_Set(0);DisplayV ol(V ol); //取消静音显示音量mute=1;}while(0!=ScanKey());break;}case 9:{ //电台减但是必须先按9进行电台搜索while(0!=ScanKey()); //按键释放Seek_direction(0); //向下搜索RXFreq = seek_channel(); //搜索下一个频道DisplayFrq(RXFreq/100.0);break;}case 10:{ //电台加但是必须先按11进行电台搜索while(0!=ScanKey()); //按键释放Seek_direction(1); //向上搜索RXFreq = seek_channel(); //搜索下一个频道Freq_Set(RXFreq);DisplayFrq(RXFreq/100.0);break;}default:break;}}}// case 9:{ //电台减但是必须先按11进行电台搜索// if(station==0)break;// if(Num>0)Num-=1;// else Num=station-1;// Freq_Set(Diantai[Num]);// DisplayFrq(Diantai[Num]/100.0);// RXFreq=Diantai[Num];// Display_now(1) ; //显示当前电台号// while(0!=ScanKey()); //按键释放// break;// }// case 10:{ if(station==0)break; //电台加但是必须先按11进行电台搜索// if(Num<(station-1))Num+=1;// else Num=0;// Freq_Set(Diantai[Num]);// DisplayFrq(Diantai[Num]/100.0);// RXFreq=Diantai[Num];// Display_now(Num); //显示当前电台号// while(0!=ScanKey()); //按键释放// break;// }//// case 11:{ //自动搜台并且存储按9 或者10 可以上下变换电台。
最简单的数字收音机成都信息工程学院刘建睿五个按键、一个电感,三个电容,一个晶振、一个耳机插口、一块芯片。
相信吗?只要上面的元件,再加上一块电路板,不超过10块钱,就能制作出一台数字FM调频收音机,没错收音机就是这么简单。
如果你曾经因为复杂的电路和痛苦的调试过程而对自己组装收音机望而却步,那么今天RDA7088单片DSP收音机芯片一定能实现你的梦想。
RDA7088是锐迪科微电子生产的单片收音机芯片,主要安装在MP4,手机等设备上实现收音机功能,由于不能回传频道数据,不能接收任意频道,实际使用较少,淘宝售价不到2元一片。
RDA7088相关参数:●芯片电压要求:1.8-3.6V●封装:SOP16●FM频率覆盖76MHz-108MHz●自动搜台●软开/关机功能●末组电台记忆功能●定频接收功能●全频道搜索时间:<5秒●最大工作电流20mA●立体声管脚功能:1.PDN:电源使能2.GND:地3.GND:地4.FMIN:FM信号输入5.GND:地6.VDD:电源正7.SEEK-:频道加8.SEEK+:频道减9.VOL-:声音加10.VOL+:声音减11.GND:地12.ROUT:右声道输出13.LOUT:左声道输出14.GND:地15.VDD:电源正16.RCLK:32.768k参考频率输入电路使用耳机地作为天线(很多MP4,手机等收音机都是这样做的),L1与C2组成谐振网络,旁边二极管是防止天线意外输入大信号损坏芯片的,在一般使用使用环境下可以取消,使用电池供电时,C1电容也可以取消。
使用操作: 开机:按下POWER 键开机; 搜台:按下SEEK+、SEEK- 分别为加频道和减频道; 音量调节:按下VOL+、VOL-分别是加、减音量; 关机:开机状态下按下POWER 键23412345678910111213141516JP1R DA7088Y132.768K VCCVCC S1SEEK-S5SEEK+S3VOL-S4VOL+S2POWERL1100n HC 124PC 2223R OUT LOUTR OUTLOUTC 347uF C 447uF123J2LM1117+5VCC12J3DC IN+5J1PHONEJ AC K212J42V-3VVCC原理图PCB 图。
基于51单片机的数字FM收音机设计与实现摘要现在人们常使用的收音机为手动调频收台,使用较为麻烦,而且由于接收灵敏度不高,所接收的频段较窄。
TEA5767具有高性能的RF AGC电路,其接收灵敏度高、参考频率选择灵活、可实现自动搜台。
本课题采用STC89C52单片机和TEA5767为核心器件,用I2C通信方式联接单片机与TEA5767,实现数字FM 收音机系统。
通过编写软件利用单片机控制TEA5767实现手动活自动调频,收到的信号通过TAD2822功放器件放大后,再用扬声器输出信号。
在调频的过程中可以通过LCD1602液晶显示屏来随时查看信号的频率。
关键词:数字调频; STC89C52; TEA5767; TDA2030ABSTRACTNowadays people usually use the radio for manual FM accept , it is much trouble, and because the rx sensitivity is not high, the frequency band received is very narrow。
TEA5767 has high-performance RF AGC circuit, high sensitivity receiving, reference frequency selection flexible and it can be the realization of automatic search platform。
So in this designing I will use the STC89C52 single-chip microcomputer and TEA5767 as the core components of digital FM radio system and Use the I2C communication to connect between STC89C52 and TEA5767 chip。
//******************************************************//功能:以LCD1602为显示的TEA5767模块的收音机//编译软件:KELI C#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define DELAY5US _nop_();_nop_();_nop_();_nop_();_nop_();//**************TEA5767模块接线方法********************sbit SDA=P2^7;sbit SCL=P2^6;//*************频率调节按键接线************************sbit Key1=P3^2;sbit Key2=P3^3;//==============LCD1602接口连接方法=====================/*-----------------------------------------------------|DB0-----P0.0 | DB4-----P0.4 | RW-------P2.3 ||DB1-----P0.1 | DB5-----P0.5 | RS-------P2.4 ||DB2-----P0.2 | DB6-----P0.6 | E--------P2.2 ||DB3-----P0.3 | DB7-----P0.7 |---------------------------------------------------*///================================================*/#define LCM_Data P0 //LCD1602数据接口#define Busy 0x80 //用于检测LCM状态字中的Busy标识sbit LCM_RW = P1^2; //读写控制输入端,LCD1602的第五脚sbit LCM_RS = P1^1; //寄存器选择输入端,LCD1602的第四脚sbit LCM_E = P1^3; //使能信号输入端,LCD1602的第6脚//*****************参数定义***************************** unsigned long int FM_FREQ; //频率unsigned short int FM_PLL; //PLLuchar idata sbuf[5]; // 数据发送缓冲区uchar idata numbyte;uchar idata numbyte_AMP;uchar idata ADDRESS_AMP;uchar idata ADDRESS_SEND; //TEA5767发送地址uchar idata ADDRESS_RECEIVE; //TEA5767接收地址uchar idata rbuf[5]; // 数据接收缓冲区uchar idata ampint[5];uchar bdata PLL_HIGH;uchar bdata PLL_LOW; //设定用于搜索和预设的可编程频率合成器uchar bdata I2C_byte1;//发送的五字节TEA5767可位寻址的设置值uchar bdata I2C_byte2;uchar bdata I2C_byte3;uchar bdata I2C_byte4;uchar bdata I2C_byte5;sbit MUTE =I2C_byte1^7;//如果MUTE=1,则左右声道被静音;MUTE=0,左右声道正常工作sbit SM = I2C_byte1^6; //SM=1,则处于搜索模式;SM=0,不处于搜索模式sbit SUD=I2C_byte3^7; //SUD=1,增加频率搜索;SUD=0,减小频率搜索uchar byte1;uchar byte2;uchar byte3;uchar byte4;uchar byte5;uchar num1,num2,num3,num4;uchar tab1[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};bit bdata NACK; // 错误标志位//**********相关函数声明**************************************void init(void); //TEA5767初始化void delay600ms(void); //延迟600msvoid delay100ms(void); //延迟100msvoid delay10ms();void delay1ms(void); //延迟1msvoid sendnbyte(uchar idata *sla, uchar n);//与sendbyte函数构成I2C数据发送函数void I2C_start(void); //I2C 传输开始void sendbyte(uchar idata *ch);void checkack(void); //检查应答讯号void stop(void); //I2C传输结束void AMP_sendnbyte(uchar idata *sla,uchar numbyte_AMP);void key_scan(void);//键扫描void search_up(void); //接收频率向上加void search_down(void); //接收频率向下减void setByte1Byte2(void); //设置第一第二字节频率void LCMInit(void);//LCD初始void DelayMs(uint Ms);//1MS基准延时程序void WriteDataLCM (uchar WDLCM);//LCD模块写数据void WriteCommandLCM (uchar WCLCM,BuysC); //LCD模块写指令uchar ReadStatusLCM(void);//读LCD模块的忙标void DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置显示一个字符void LCDshow(void);void DelayMs(uint Ms);//*****************主程序******************************void main(void){numbyte = 5;numbyte_AMP=5;ADDRESS_SEND = 0xC0;// TEA5767写地址1100 0000ADDRESS_RECEIVE=0XC1;//TEA5767读地址1100 0001ADDRESS_AMP=0X8E;init(); // 初始化TEA5767LCMInit();//LCD初始LCDshow();while(1){key_scan(); //键扫描}}//**************按键扫描程序**************************void key_scan(void){if(Key1==0){delay10ms();if(Key1==0){while(Key1==0);search_up(); //频率向上LCDshow();delay600ms();}}if(Key2==0){delay10ms();if(Key2==0){while(Key2==0);search_down(); //频率向下LCDshow();delay600ms();}}}//*********************LCD1602显示程序********************* void LCDshow(void){num1=FM_FREQ/100000000;num2=(FM_FREQ%100000000)/10000000;num3=(FM_FREQ%10000000)/1000000;num4=(FM_FREQ%1000000)/100000;DisplayOneChar(0, 4,'F');//DisplayOneChar(0, 5,'M');//DisplayOneChar(0, 6,'R');//DisplayOneChar(0, 7,'a');//DisplayOneChar(0, 8,'d');//DisplayOneChar(0, 9,'i');//DisplayOneChar(0, 10,'o');//DisplayOneChar(1, 4, tab1[num1]);DisplayOneChar(1, 5, tab1[num2]);DisplayOneChar(1, 6, tab1[num3]);DisplayOneChar(1, 7, '.');DisplayOneChar(1, 8, tab1[num4]);DisplayOneChar(1, 9,'M');//DisplayOneChar(1, 10,'H');//DisplayOneChar(1, 11,'Z');//}/*======================================================================LCM初始化======================================================================*/void LCMInit(void){LCM_Data = 0;WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号DelayMs(5);WriteCommandLCM(0x38,0);DelayMs(5);WriteCommandLCM(0x38,0);DelayMs(5);WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); //关闭显示WriteCommandLCM(0x01,1); //显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0C,1); // 显示开及光标设置DelayMs(100);}//==============================LCD1602显示子程序================================================// 写数据函数: E =高脉冲RS=1 RW=0//======================================================================*/void WriteDataLCM(uchar WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;LCM_RS = 1;LCM_RW = 0;LCM_E = 0; //若晶振速度太高可以在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}/*==================================================================== 写指令函数: E=高脉冲RS=0 RW=0======================================================================*/ void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCM(); //根据需要检测忙LCM_Data = WCLCM;LCM_RS = 0;LCM_RW = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;}/*==================================================================== 正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;DB7: 0 LCD控制器空闲,1 LCD控制器忙。