工业控制 | 能源技术 | 汽车电子 | 通信网络 | 安防监控 | 智能电网 | 移动手持 | 无线技术 | 家用电器 | 数字广播 | 消费电子 | 应用软件 | 其他方案

电路设计->光电电路图->其他光电实用电路图->FM收音模块TEA5756程序设计与控制

FM收音模块TEA5756程序设计与控制

作者:沉默的offer时间:2018-08-07

//现在用830学习板来写FM收音板
//与手机对比收台的个数,比手机收的电台还要多,OK


#include reg52.h>

char code reserve [3] _at_ 0x3b; //保留0x3b开始的3个字节
//#include intrins.h>

#define uchar unsigned char
#define uint unsigned int

#define max_freq 1080
#define min_freq 875

uchar data fm_w[5]={0x00,0x00,0x31,0x17,0x00};//这是要写入的数据
uchar data fm_r[5]={0,0,0,0,0}; //这是放读出的数据

uchar code tabduan[]//不带点的数码管0-f
={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

uchar code tabduan1 []//带点的数码管0-9
={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,};

//位定义说明:u:=1向上自动搜台反之。。。

bit SM,SUD,RF,SystemError,STEREO,u,SD,HISI=1,mode;

uchar zhong,IF,ADC,ADC1;
uint fm,PLL,freq1;
uint Frequency=1043;

//#include"FM_PLL.h"//这里包涵的是FM收音的PLL值

sbit k3=P1^6;
sbit k4=P1^7;
sbit k2=P1^5;
sbit k1=P1^4;
sbit k7=P3^4;
sbit k8=P3^5;

sbit SDA=P3^5;
sbit SCL=P3^4;

delayms(uint ms)
{
uint i,j;
for(i=0;ims;i++)
for(j=0;j123;j++);
}

#include"iIC.h"

//由频率计算PLL
void get_pll(void)
{
unsigned long freq,y=frequency;
freq=y*10000;//我的显示频率980,所以要这里*100 000=98 000 000Hz
PLL=((freq+225000)*4)/32768;//频率单位:Hz
//如98MHz:((98000000+225000)*4)/32768==11990=0x2ed6
}

void get_freq(void)
{
unsigned long y;
//uint y;
y=PLL;
//x=y*8192-225000;
//freq1=x/100000;
freq1=(y*8192-225000)/10000;
}


void fm_xing()//FM收音芯片数据刷新一次
{

get_pll();//计算PLL,
fm_w[0]=PLL/256;
fm_w[1]=PLL%256;
fm_w[2]=0x30;
fm_w[3]=0x11;
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值
ADC=fm_r[3];//去掉最高位就是IF值
ADC>>=4;
STEREO=fm_r[2]0x80;//最高位就是STEREO值

}

//手动设置频率,mode=1,+0.1MHz; mode=0:-0.1MHz ,
//不用考虑TEA5767用于搜台的相关位:SM,SUD
void search()
{
//给频率+/-1,

if(mode)
{
frequency+=1;
if(frequency>max_freq)
frequency=min_freq;
}
else
{
frequency-=1;
if(frequencymin_freq)
frequency=max_freq;
}


fm_xing();
}

//自动搜台,mode=1,频率增加搜台; mode=0:频率减小搜台
void auto_search()
{
do{

if(mode)
fm_w[2]=0xa0;
else
fm_w[2]=0x20;

search();

fm_xing();

}while((IF>0x3e)|(IF0x31)|(ADC7)|(!STEREO)|(!RF)); //搜台成功标志}

/**********************************************************

**********************************************************/
main(void)
{
frequency=9801;//默认收台为104.3MHz
get_pll();//计算PLL,差不多要1ms
get_freq();
delayms(60);
HISI=1;
iicInit();
delayms(300);//等待电源稳定后再发数据

EA=1;
ET1=1;
TMOD=0x10;
TH1=(65536-5000)/256;
TL1=(65536-5000)%256;
TR1=1;

frequency=1043;//默认收台为104.3MHz
get_pll();//计算PLL
fm_xing();//给PLL写入TEA5767中,并读出其中的状态

while(1)
{

if(!k1)//向上搜台
{
delayms(15);
if(!k1)
{
// while(!k1);//等松手
mode=1;
search();
delayms(100);
}
}
if(!k2)//向上搜台
{
delayms(15);
if(!k2)
{
//while(!k3);//等松手
mode=0;
search();
delayms(100);
}
}


if(!k4)//向上搜台
{
delayms(15);
if(!k4)
{
while(!k4);//等松手
mode=1;
auto_search();
}
}
if(!k3)//向上搜台
{
delayms(15);
if(!k3)
{
while(!k3);//等松手
mode=0;
auto_search();
}
}


}//while-end
}//main-end

/**********************************************************/
void time1() interrupt 3
{
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;

zhong++;//用来数码管计数
P2=0xff;//消余亮
switch(zhong)
{
case 1: P0=tabduan[frequency%10];
P2=0xef; //--------------5
break;
case 2: P0=tabduan1[frequency%100/10];
P2=0xdf; //--------------十位6
break;
case 3: P0=tabduan[frequency%1000/100];
P2=0xbf; //--------------百位7
break;
case 4: if(frequency/1000==0)P0=0xff;
else P0=tabduan[frequency/1000];
P2=0x7f;//---------------千位8
// zhong=0;
break;

case 5: P0=tabduan[(IF%16)];
P2=0xfe; //--------------1位个
break;
case 6: P0=tabduan[(IF/16)];
P2=0xfd; //--------------2位
break;
case 7: P0=tabduan[ADC];
P2=0xfb; //--------------3位
break;
case 8: P0=tabduan[RF];
P2=0xf7; //--------------4位,
zhong=0;
break;

}

}//中断end
#include intrins.h>
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

//-------------------------------------------------------------------
// 函数名称: iic_start()
// 函数功能: 启动I2C总线子程序
//-------------------------------------------------------------------
void iic_start(void)
{ //时钟保持高,数据线从高到低一次跳变,I2C通信开始
SDA = 1;
SCL = 1;
delayNOP(); // 延时5us
SDA = 0;
delayNOP();
SCL = 0;
}
//-------------------------------------------------------------------
// 函数名称: iic_stop()
// 函数功能: 停止I2C总线数据传送子程序
//-------------------------------------------------------------------
void iic_stop(void)
{
SDA = 0; //时钟保持高,数据线从低到高一次跳变,I2C通信停止
SCL = 1;
delayNOP();
SDA = 1;
delayNOP();
SCL = 0;
}
//------------------------------------------------------------------
// 函数名称: iicInit_()
// 函数功能: 初始化I2C总线子程序
//------------------------------------------------------------------
void iicInit(void)
{
SCL = 0;
iic_stop();
}
//-------------------------------------------------------------------
// 函数名称: slave_ACK
// 函数功能: 从机发送应答位子程序
//-------------------------------------------------------------------
void slave_ACK(void)
{
SDA = 0;
SCL = 1;
delayNOP();
SCL = 0;
}
//-------------------------------------------------------------------
// 函数名称: slave_NOACK
// 函数功能: 从机发送非应答位子程序,迫使数据传输过程结束
//-------------------------------------------------------------------
void slave_NOACK(void)
{
SDA = 1;
SCL = 1;
delayNOP();
SDA = 0;
SCL = 0;
}
//-------------------------------------------------------------------
// 函数名称: check_ACK
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束
//-------------------------------------------------------------------
void check_ACK(void)
{
SDA = 1; // 将p1.1设置成输入,必须先向端口写1
SCL = 1;
F0 = 0;
delayNOP();
if(SDA == 1) // 若SDA=1表明非应答,置位非应答标志F0
F0 = 1;
SCL = 0;
}
//-------------------------------------------------------------------
// 函数名称: IICSendByte
// 入口参数: ch
// 函数功能: 发送一个字节
//-------------------------------------------------------------------
void IICSendByte(uchar ch){
unsigned char idata n=8; // 向SDA上发送一位数据字节,共八位

while(n--)
{
if((ch0x80) == 0x80) // 若要发送的数据最高位为1则发送位1
{
SDA = 1; // 传送位1
SCL = 1;
delayNOP();
// SDA = 0;
SCL = 0;
}
else
{
SDA = 0; // 否则传送位0
SCL = 1;
delayNOP();
SCL = 0;
}
ch = ch1; // 数据左移一位
}
}
//-------------------------------------------------------------------
// 函数名称: IICreceiveByte
// 返回接收的数据
// 函数功能: 接收一字节子程序
//-------------------------------------------------------------------
uchar IICreceiveByte(void)
{
uchar idata n=8; // 从SDA线上读取一上数据字节,共八位
uchar tdata=0;
while(n--)
{
SDA = 1;
SCL = 1;
tdata =tdata1; //左移一位
if(SDA == 1)
tdata = tdata|0x01; // 若接收到的位为1,则数据的最后一位置1
else
tdata = tdata0xfe; // 否则数据的最后一位置0
SCL = 0;
}

return(tdata);
}
//-------------------------------------------------------------------
// 函数名称: DAC_PCF8591
// 入口参数: slave_add从机地址,n要发送的数据个数
// 函数功能: 发送n位数据子程序
//-------------------------------------------------------------------
void write_5byte()
{
uchar i;
iic_start(); // 启动I2C
delayNOP();

IICSendByte(0xc0); // 发送地址位
check_ACK(); // 检查应答位
if(F0 == 1)
{
SystemError = 1;
return; // 若非应答,置错误标志位
}
for(i=0;i5;i++)
{

IICSendByte(fm_w[i]); //Control byte
check_ACK();
}


iic_stop(); // 全部发完则停止
delayNOP();
delayNOP();
delayNOP();
delayNOP();
}
//-------------------------------------------------------------------
// 函数名称: ADC_PCF8591
// 入口参数: controlbyte控制字
// 函数功能: 连续读入4路通道的A/D转换结果到receivebuf
//-------------------------------------------------------------------
void read_5byte()
{
uchar idata receive_da,i=0;

iic_start();

IICSendByte(0xc0); //收音机的名字
check_ACK();
if(F0 == 1)
{
SystemError = 1;
return;
}

iic_start(); //重新发送开始命令
IICSendByte(0xc1); //控制字
check_ACK();


for(i=0;i5;i++)
{
receive_da=IICreceiveByte();
fm_r[i]=receive_da;
slave_ACK(); //收到一个字节后发送一个应答位
}
slave_NOACK(); //收到最后一个字节后发送一个非应答位
iic_stop();
}


关键词:

评论

技术专区