#include <reg51.h>
#include <intrins.h>
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();_nop_();};
//系统晶振频率为12MHz
#define uchar unsigned char
#define uint unsigned int
#define max_freq 1080
#define min_freq 875
#define Disdata P0 //段码输出口
#define discan P1 //扫描口
void delayms(uint ms); //函数声明
void get_pll(void);
void get_freq(void);
void fm_xing();
void search();
void auto_search();
void iic_start(void);
void iic_stop(void);
void slave_ACK(void);
void slave_NOACK(void);
void check_ACK(void);
void IICSendByte(uchar ch);
uchar IICreceiveByte(void);
void write_5byte();
void read_5byte();
void delay(uint);
void ow_reset(void);
void write_byte(uchar);
uchar read_byte(void);
void read_temp();
void work_temp();
char code reserve [3] _at_ 0x3b; //保留0x3b开始的3个字节
uchar data fm_w[5]={0x00,0x00,0x31,0x17,0x00};//这是要写入的数据
uchar data fm_r[5]={0,0,0,0,0}; //这里放读出的数据
//uchar code tabduan[]
uchar code tabduan[]={0xd7,0x14,0xcd,0x5d,0x1e,0x5b,0xdb,0x15,0xdf,0x5f,0x9F,0xDA,0xC3,0xDC,0xCB,0x8B,0x00};
/**左边LED四位 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F" "不亮"
共阴数码管段码表 (按图接法的编码)**/
uchar code tabduan1[]={0x5F,0x41,0x9D,0xd5,0xC3,0xD6,0xDE,0x45,0xDF,0xD7,0xCF,0xDA,0x1E,0xD9,0x9E,0x8E,0x00};
/**右边LED四位 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F" "不亮"
共阴数码管段码表 (按图接法的编码)**/
uchar dis_7[12]={0xd7,0x14,0xcd,0x5d,0x1e,0x5b,0xdb,0x15,0xdf,0x5f,0x00,0x08};
/**共阴LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-" **/
uchar data temp_data[2]={0x00,0x00}; //读出温度暂存放
uchar data display[5]={0x00,0x00,0x00,0x00,0x00}; //显示单元数据,共4个数据,一个运算暂存用
bit RF,SystemError,STEREO,mode,HLSI=1;
//RF=1收到台或搜到头,STEREO=1立体声
uchar zhong=0,IF,LEV; //IF为中频值,LEV电台信号强度
uint PLL,freq1;
uint frequency=1043; //频率frequency是按0.1MHz为单位,如98.0MHz,frequency=980
sbit k1=P2^3; //向上手动搜台
sbit k2=P2^2; //向下手动搜台
sbit k3=P2^1; //向上自动搜台
sbit k4=P2^0; //向下自动搜台
//sbit k7=P3^4; //未用
//sbit k8=P3^5; //未用
sbit SDA=P2^6; //接FM模块DATA
sbit SCL=P2^7; //接FM模块CLK
sbit DQ=P2^4; //温度输入口
sbit DIN=P0^5; //小数点
uint t;
uint h;
//--------------------------------------
void delayms(uint ms) //延时,如用12MHz晶振,则延时约1ms
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<123;j++); //延时约~1000机器周期
}
/*******************11μs延时器******************/
//
void delay(uint t)
{
for(;t>0;t--);
}
//--------------------------------------
void get_pll(void) //由频率计算PLL
{
unsigned long freq,y=frequency;
freq=y*100000; //如显示频率y=980,实际频率为y*100 000=98 000 000Hz
PLL=((freq+225000)*4)/32768;//频率单位:Hz
//如98MHz: ((98000000+225000)*4)/32768==11990=0x2ed6
}
//--------------------------------------
void get_freq(void) //由PLL计算频率
{
unsigned long y; //uint y;
y=PLL; //x=y*8192-225000; freq1=x/100000;以0.1MHz计
freq1=(y*8192-225000)/100000; //以100kHz,或说0.1MHz计
}
/*
//--------------------------------------
void fm_xing()//FM收音芯片数据刷新一次
{
get_pll(); //计算PLL,
fm_w[0]=PLL/256;
fm_w[1]=PLL%256;
fm_w[2]=0x31; //HLSI=1高本振注入
fm_w[3]=0x17; //32.768kHz
fm_w[4]=0x00;
if(mode)fm_w[2]|=0x80;//给SUD=1,向上搜索模式
else fm_w[2]&=0x7f;//给SUD=0,向下搜索模式
write_5byte();//送入到5767里面
delayms(50);//送进PLL值后,要等50ms再去读TEA5767里面的数据
read_5byte();
RF=fm_r[0]&0x80;
IF=fm_r[2]&0x7f;//去掉最高位就是IF值
LEV=fm_r[3];//高四位为电台信号电平值
LEV>>=4;
STEREO=fm_r[2]&0x80;//最高位就是STEREO值
}
*/
//--------------------------------------
//手动设置频率的函数,mode=1,+0.1MHz; mode=0:-0.1MHz ,
//不用考虑TEA5767用于搜台的相关位:SM,SUD
void search() //给频率+/-1,实+/-100kHz
{
if(mode)
{ frequency+=1;
if(frequency>max_freq)
frequency=min_freq;
}
else
{ frequency-=1;
if(frequency<min_freq)
frequency=max_freq; }
get_pll(); //计算PLL,
fm_w[0]=PLL/256;
fm_w[1]=PLL%256;
fm_w[2]=0x31;
fm_w[3]=0x17;
fm_w[4]=0x00;
if(mode)fm_w[2]|=0x80;//给SUD=1,向上搜索模式
else fm_w[2]&=0x7f;//给SUD=0,向下搜索模式
write_5byte();//送入到5767里面
PLL=0;
delayms(50);//送进PLL值后,要等50ms
read_5byte();
PLL=fm_r[0]&0x3f;
PLL=PLL*256+fm_r[1];
get_freq();
}
//--------------------------------------
//自动搜台函数,mode=1,频率增加搜台; //mode=0:频率减小搜台
void auto_search()
{
get_pll(); //计算PLL
fm_w[2]=0x31; //高本振注入、电平>5的电台也算台
fm_w[3]=0x17;
fm_w[4]=0x00;
if(mode)
{PLL=PLL+24; //考虑到取整等,先加0.2MHz
fm_w[0]=PLL/256;
fm_w[0]|=0x40; //设置为自动搜索模式
fm_w[1]=PLL%256;
fm_w[2]|=0x80;} //给SUD=1,向上搜索模式
else
{fm_w[0]=PLL/256;
fm_w[0]|=0x40; //设置为自动搜索模式
fm_w[1]=PLL%256;
fm_w[2]&=0x7f; } //给SUD=0,向下搜索模式
write_5byte();//送入到5767里面
delayms(50);//送进PLL值后,要等50ms再去读TEA5767里面的数据
do{ read_5byte();
RF=fm_r[0]&0x80; //字节可以送给位?
PLL=fm_r[0]&0x3f;
PLL=PLL*256+fm_r[1];
get_freq();
delayms(500); //等500ms再去读TEA5767里面的数据
}while(!RF&(freq1>875)&(freq1<1080)); //搜到台或到头停止
// IF=fm_r[2]&0x7f;//去掉最高位就是IF值
// LEV=fm_r[3];//高四位为电台信号电平值
// LEV>>=4;
// STEREO=fm_r[2]&0x80;//最高位就是STEREO值
// }while((IF>0x3e)|(IF<0x31)|(LEV<7)|(!STEREO)|(!RF)); //搜台成功标志
frequency=freq1;//新搜到的频率作为老频率
}
/**********主函数**********************/
main(void)
{
delayms(300);//等待电源稳定后再发数据
EA=1;
ET1=1;
TMOD=0x10;
TH1=(65536-5000)/256;
TL1=(65536-5000)%256;
TR1=1;
frequency=1043;//默认收台为104.3MHz
while(1)
{
if(!k1) //如k1=0(按下)手动向上搜台,每按一次增0.1MHz
{
delayms(15); //消抖
if(!k1)
{
while(!k1); //等松手
mode=1;
search();
delayms(100);
}
}
if(!k2) //如k2=0(按下)手动向下搜台,每按一次减0.1MHz
{
delayms(15);
if(!k2)
{
// while(!k2); //等松手,去掉此句就是一直减
mode=0;
search();
delayms(100);
}
}
if(!k3) //如k3=0(按下)自动向上搜台,搜到台停止
{
delayms(15);
if(!k3)
{
mode=1;
auto_search();
while(!k3); //等松手
}
}
if(!k4) //如k4=0(按下)自动向下搜台,搜到台停止
{
delayms(15);
if(!k4)
{
mode=0;
auto_search();
while(!k4); //等松手
}
}
} //while-end
} //main-end
/*********数码管显示,用定时刷新方法来实现*************/
void time1() interrupt 3
{
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
zhong++;//选哪位数码管亮
P0=0x00;//全灭、消余亮
switch(zhong)
{
case 0:{read_temp(); //读出DS18B20温度数据
work_temp();}
break; //处理温度数据
case 1: P0=dis_7[display[0]];
P1=0xf3;; //-----第4位数码管(个位) (即实现y3=0)
break;
case 2: P0=dis_7[display[1]];
DIN=1; //加小数点
P1=0xf4; //----第3位数码管(十位) (即实现y4=0)
break;
case 3: P0=dis_7[display[2]];
P1=0xf5; //-----第2位数码管(百位)
break;
case 4: P0=dis_7[display[3]];
P1=0xf6;//---- -第1位数码管(千位)
break;
//以下为右起第1位--第4位是读出频率值
case 5: P0=tabduan1[freq1%10];
P1=0xf2;; //-----第8位数码管(个位)
break;
case 6: P0=tabduan1[freq1%100/10];
DIN=1; //加小数点
P1=0xf7;; //-----第7位数码管(十位)
break;
case 7: P0=tabduan1[freq1%1000/100];
P1=0xf0;; //-----第6位数码管(百位)
break;
case 8: if(freq1/1000==0)P0=0x00;
else P0=tabduan1