资源描述
* 晶振:8M
*/
#include <reg52.h>
#include <string.h>
#define ChannelCount 50 //最多支持多少个台,因为常驻内存,多了RAM放不下
#define uchar unsigned char
#define uint unsigned int
typedef 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; //起始频率 * 100KHz
const uint MaxFreq = 1080; //最高频率 * 100KHz
const 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~0xF
uchar 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);
}
Mute = 0;
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;
Delay(50);
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;
do
{
str[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 灵敏度越低越可能搜索到假台,高了可能一些信号弱一点的频道被跳过。
uint reg5H;
uint tempTune = 0;
for(i=0;i<ChannelCount;i++) //清除原有的电台数据
{
ChannelTune[i]=0;
}
reg5H = FM_ReadReg(0×05);
reg5H = (reg5H & 0x80FF) | (seekth<<7);
FM_WriteReg(0×05,reg5H);
for(i=0;i<=MaxFreq – MinFreq;i++)
{
FreqTune = i;
FM_SetFreq();
Lcd_DispFreq();
do
{
state = FM_ReadReg(0x0B);
cmp = (state>> 7 ) & 0×1;
}while(!cmp);
Delay(100);
state = FM_ReadReg(0x0B);
cmp = (state >> 8 ) & 0×1;
if(cmp)
{
ChannelTune[count]=i;
count++;
}
if(count>=ChannelCount){ break; }
}
}
uchar FM_GetRSSI()
{
uint regVal =FM_ReadReg(0x0b);
regVal = regVal>>9;
return (uchar)(regVal/16);
}
void Delay(uint c)
{
int i=0;
for(i=0;i<c;i++);
}
uint IICRead(uchar uaddr, uchar ramAddr,bit _16b)
{
uint buf;
OpenIIC();
IICWriteByte(uaddr);
IICWriteByte(ramAddr);
OpenIIC();
IICWriteByte(uaddr | 0×01);
if(_16b)
{
buf = IICReadByte(1);
buf = buf<<8;
buf =buf | IICReadByte(0);
}
else
{
buf = IICReadByte(0);
}
CloseIIC();
return buf;
}
uchar IICReadByte(bit next)
{
uchar buf =0,i=0;
for(i=0;i<8;i++)
{
buf <<=1;
SCL = 1;
buf |= SDA;
Delay(5);
SCL = 0;
Delay(5);
}
if(next)
{
SDA = 0;
SCL = 1;
Delay(5);
SCL = 0;
Delay(5);
SDA = 1;
}
else
{
SDA = 1;
SCL = 1;
Delay(5);
SCL = 0;
Delay(5);
SDA=0;
}
return buf;
}
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();
}
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;
Delay(5);
SCL = 0;
Delay(5);
}
SCL = 1;
while(SDA && –f);
Delay(5);
SCL = 0;
Delay(5);
}
void CloseIIC()
{
SDA = 0 ;
SCL = 1;
Delay(5);
SDA = 1;
Delay(5);
SCL = 1;
SDA = 1;
Delay(150); //防止过快的读取造成EPPROM 来不及反应
}
void OpenIIC()
{
SDA = 1;
SCL = 1;
Delay(5);
SDA = 0;
Delay(5);
SCL = 0;
Delay(5);
}
/****************************************************************************************************************/
展开阅读全文