磁动力电子网-雕刻机DIY论坛,单片机论坛,CNCDIY,DIYCNC

 找回密码
 加入磁动力

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 4967|回复: 8

[51单片机] TEA5767数码管显示的调频收音机

  [复制链接]
发表于 2012-5-12 21:24:56 | 显示全部楼层 |阅读模式
34.jpg 33.jpg 22.jpg 模块正面接线图.jpg
直上完整程序
/***************************************************************************************
       AT89S52+12MHZ+TEA5767的数码管显示调频收音机
本程序使用数码管显示频率  晶振是用12M  已通过测试,收音机的频率调节是用计算的方法  将显示的频率算好后写到TEA5767
芯片里面实现调节的  两个按键实现自加或自减频率  加了连续加减功能!
使用的是在淘宝上买的4.5元/片的简化版的TEA5767模块.
                    2012-05-08
/************************************************************************************/
#include  < reg51.h >
#define uchar unsigned char
#define uint unsigned int  
/*************************************************************************************/      
sbit SDA = P3^0;  //接在TEA5767的数据端口
sbit SCL = P3^1;  //接在TEA5767的时钟端口      
sbit KEY1 = P3^4;  //频率增加按键端口     
sbit KEY2 = P3^5;  //频率减小按键端口
sbit KEY3 = P3^6;  //频率增加按键端口     
sbit KEY4 = P3^7;  //频率减小按键端口      
#define duan P0   //频率显示的数码管段选P0端口   
//#define gy   //使用共阴极时屏蔽这行
sbit dula=P2^6;
sbit wela=P2^7;
uchar IF,ADC,CH;
//bit  RF,STEREO;
#ifdef gy
unsigned char code dispbit[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//显示位码
unsigned char code dispcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//数码管显示编码
#else
/*******************************************************************************************/
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00}; //数码管显示编码         
unsigned char code dispbit[]={0x7e,0x7d,0x7b,0x77,0x6f,0x5f};/*定义点亮的数码管与数组的关系*/
#endif
/*******************************************************************************************
unsigned char radio_write_data[5] = {0x2c,0xe1,0x70,0x16,0x80}; //频率为93.9MHz  广东音乐电台
unsigned char radio_write_data[5] = {0x30,0x5c,0x70,0x16,0x80}; //频率为101.2MHz 广东电台音乐之声
unsigned char radio_write_data[5] = {0x31,0x38,0x70,0x16,0x80}; //频率为103.0MHz 广东珠江经济电台
unsigned char radio_write_data[5] = {0x31,0xd7,0x70,0x16,0x80}; //频率为104.3MHz 宝安广播电台
unsigned char radio_write_data[5] = {0x32,0x20,0x70,0x16,0x80}; //频率为104.9MHz 中央人民广播电台华夏之声
unsigned char radio_write_data[5] = {0x33,0x2d,0x70,0x16,0x80}; //频率为107.1MHz 中国国际广播电台环球资讯
/********************************************************************************************/
unsigned char radio_read_data[5];
unsigned char radio_write_data[5];
unsigned long frequency = 104900; //开机初始化的电台频率为104.9MHz中央民广播电台华夏之声
unsigned int PLL;     //计算频率合成时用的变量
/***************************************************************************************/
void Delayus(unsigned char x)
{
for(;x > 0;x--);
}
/************************************************************************************/
void iic_start()  //启动总线传输
{
SDA = 1;
Delayus(4);
SCL = 1;
Delayus(4);
SDA = 0;
Delayus(4);
SCL = 0;
Delayus(4);
}
/*********************************************************************************************/
void iic_stop()  //结束总线传输
{
SCL = 0;
Delayus(4);
SDA = 0;
Delayus(4);
SCL = 1;
Delayus(4);
SDA = 1;
Delayus(4);
}
/********************************************************************************************/
void iic_ack()  //发送应答位
{
SDA = 0;
Delayus(4);
SCL = 1;
Delayus(4);
SCL = 0;
Delayus(4);
SDA = 1;
Delayus(4);
}
/*****************************************************************************************/
bit iic_testack()
{
bit ErrorBit;
SDA = 1;
Delayus(4);
SCL = 1;
Delayus(4);
ErrorBit = SDA;
Delayus(4);
SCL = 0;
return ErrorBit;
}
/***************************************************************************************/
void iic_write8bit(unsigned char input) //写一个字节的数据到总线上
{
unsigned char temp;
for(temp = 8;temp > 0;temp--)
{
  SDA = (bit)(input & 0x80);
  Delayus(4);
  SCL = 1;
  Delayus(4);
  SCL = 0;
  Delayus(4);
  input = input << 1;
}
}
/****************************************************************************************/
uchar iic_rdbyt() //从总线上读取一个字节的数据
{
uchar a = 0,i = 0;
for(i = 0;i < 8;i++)
{
  SDA = 1;
  SCL = 1;
  if(SDA == 1)
  {
   a = (a << 1) + 1;
   SCL = 0;
  }
  else if(SDA == 0)
  {
   a = a << 1;
   SCL = 0;
  }
}
return(a);
}
/****************************************************************************************/
void delays (unsigned char b) //按键消抖用的延时程序
{
unsigned char i;
for(b;b > 0;b--)
for(i = 0;i < 250;i++);
}
/*************************************************************************************/
void radio_write(void) //写入TEA5767
{
unsigned char i;
iic_start(); //启动总线传输
iic_write8bit(0xc0);        //TEA5767写地址
if(!iic_testack())
{
  for(i = 0;i < 5;i++)
  {
   iic_write8bit(radio_write_data); //写一个字节的数据到总线上
   iic_ack();   //发送应答位
  }
}
iic_stop();  //结束总线传输     
}
/************************************************************************************/
//将显示的频率算好后写到TEA5767芯片里面实现调节,不用考虑TEA5767用于搜台的相关位:SM,SUD
//写模式
//数据字节1 数据字节2 数据字节3 数据字节4 数据字节5
void search()
{        
PLL = (unsigned int)((float)((frequency + 225)) / (float)8.192);    //计算合成频率数据  频率单位:k
/*********************************************************************************************/
//数据字节1的格式 radio_write_data[0]
//位7(高位)  位6  位5  位4  位3  位2  位1  位0(低位)
// MUTE   SM   PLL13  PLL12  PLL11 PLL10  PLL9   PLL8
//7 MUTE 如果MUTE=1  则左右声道被静音;MUTE=0  左右声道正常工作。
//6 SM   如果SM=1  则处于搜索模式  SM=0  不处于搜索模式。
//5到0   PLL[13:8] 设定用于搜索和预设的可编程频率合成器。
radio_write_data[0] = PLL / 256; //将算好的频率高位数据存入将要TEA5767的数组里
/******************************************************************************************/
//数据字节2的格式 radio_write_data[1]
//位7(高位)  位6  位5  位4  位3  位2  位1  位0(低位)
// PLL7   PLL6  PLL5  PLL4  PLL3  PLL2  PLL1   PLL0
//PLL[7:0] 设定用于搜索和预设的可编程频率合成器。
radio_write_data[1] = PLL % 256; //将算好的频率低位数据存入将要TEA5767的数组里
/**********************************************************************************************/
//数据字节3的格式 radio_write_data[2]
//位7(高位) 位6  位5  位4  位3  位2  位1  位0(低位)
// SUD   SSL1  SSL0  HLSI  MS   ML   MR     SWP1
//SUD SUD=1 增加频率搜索  SUD=0  减小频率搜索。
//SLL[1:0] 搜索停止标准:见下表1。
//SSL0 SSL1 搜索停止标准
// 0    0   在搜索模式下禁止  
// 0    1   低:ADC输出大小为5
// 1    0   中:ADC输出大小为7
// 1    1   高:ADC输出大小为10
//HLSI 高/低充电电流切换:HLSI=1  高充电电流   HLSI=0  低充电电流。
//MS 立体声/单声道:MS=1  单声道  MS=0  立体声。
//ML 左声道静音:ML=1  左声道静音并置立体声  ML=0  左声道正常。
//MR 右声道静音:MR=1  右声道静音并置立体声  MR=0  右声道正常。
//SWP1 软件可编程端口1:SWP1=1  端口1高电平  SWP1=0  端口1低电平。
radio_write_data[2] = 0x70;   //这是TEA5767开立体声  关静音
/************************************************************************************/
//数据字节4的各个位描述  radio_write_data[3]
//位7(高位) 位6  位5  位4  位3  位2  位1  位0(低位)
// SWP2  STBY  BL  XTAL  SMUTE  HCC  SNC     SI
//SWP2 软件可编程端口2:SWP2=1,端口2高电平;SWP2=0,端口2低电平。
//STBY 等待:STBY=1  处于待机模式,STBY=0,退出待机模式。
//BL 波段制式:BL=1  日本调频制式  BL=0,美国/欧洲调频制式。
//XTAL 如果XTAL=1  那么fxtal=32.768KHz;如果XTAL=0  那么fxtal=13MHz。
//SMUTE 软件静音:SMUTE=1  软静音打开;SMUTE=0,软静音关闭。
//HCC 白电平切割:HCC=1  高电平切割打开  HCC=0  高电平切割关闭。
//SNC 立体声噪声去除:如果SNC=1,立体声消噪除打开,如果SNC=0,立体声消噪除关闭。
//SI 搜索标志位:SI=1  SWPORT1输出准备好信号   SI=0  SWPORT1作为软件可编程端口1用。
radio_write_data[3] = 0x16;   //中国制式  采用32768晶振  软静音关  立体声消噪声开
/*****************************************************************************************/
//数据字节5的格式 radio_write_data[4]
//位7(高位)  位6  位5  位4  位3  位2  位1  位0(低位)
// PLLREF   DTC  --    --    --  --   --    --
//若PLLREF=1  6.5MHz的锁相环参考频率启用;若PLLREF=0  6.5MHz的锁相环参考频率关闭。
//若DTC=1  去加重时间常数为75us;若DTC=0  去加重时间常数为50us。
//位5到0  未用  状态不必考虑。
radio_write_data[4] = 0x80;   //6.5M锁相环开  去加重时间50US
/*******************************************************************************************/
radio_write();      //写入TEA5767
}
/*******************************************************************************************
//读模式
//数据字节1 数据字节2 数据字节3 数据字节4 数据字节5
//数据字节1的格式
//位7(高位)  位6   位5   位4   位3   位2  位1   位0(低位)
// RF    BLF  PLL13  PLL12  PLL11  PLL10  PLL9   PLL8
//7 RF 准备好标志:RF=1  有一个频道被搜到或者一个制式已经符合;RF=0  没有频道被搜到。
//6 BLF 波段制式:BLF=1  一个制式已经符合   BLF=0  没有制式已经符合。
//5到0 PLL[13:8] 用于搜索和预设后的可编程频率合成器设定结果。
//数据字节2的格式
//位7(高位)   位6   位5   位4   位3   位2   位1  位0(低位)
// PLL7   PLL6  PLL5  PLL4  PLL3  PLL2  PLL1   PLL0
//数据字节2的各个位描述
//PLL[7:0] 设定用于搜索和预设后的可编程频率合成器设定结果。
//数据字节3的格式
//位7(高位)  位6  位5   位4  位3  位2  位1  位0(低位)
// STEREO   IF6  IF5  IF4  IF3  IF2  IF1   IF0
//7 STEREO 立体声标志位:STEREO=1  立体声接收  STEREO=0  单声道接收。
//6到0 IF[6:0] 中频计数器结果。
//数据字节4的格式
//位7(高位) 位6  位5  位4  位3  位2  位1  位0(低位)
// LEV3   LEV2  LEV1  LEV0  CI3  CI2  CI1   0
//7到4 LEV[3:0] ADC的输出。
//3到1 CI[3:1] 芯片验证号。
//0 ------ 该位内部置0。
//数据字节5的格式
//位7(高位)  位6  位5  位4  位3  位2  位1  位0(低位)
//   0    0    0    0    0    0    0    0
//7到0 ------ 预留为扩展用  由内部置0。
/*************************************************************************************/
void delay()
{
uchar k;
for(k = 0;k < 100;k++);
}
/***********************************************************************************/
void desplay(uint aa)
{
/*****************************************************************************************
duan = tab[aa / 1000] | 0x80;  //关这位数码管的小数点
led1 = 0;
delay();
led1 = 1;
duan = tab[aa % 1000 / 100] | 0x80;  //关这位数码管的小数点
led2 = 0;
delay();
led2 = 1;
duan = tab[aa % 100 / 10] & 0x7f; //点亮这位数码管的小数点
led3 = 0;
delay();
led3 = 1;
duan = tab[aa % 10] | 0x80;  //关这位数码管的小数点
led4 = 0;
delay();
led4 = 1;
/**********************************************************************************************/
dula = 0;
if((aa / 1000) == 0)
duan = dispcode[aa / 1000 + 10]; //这位为0数码管不显示
else
duan = dispcode[aa / 1000];   //这位数码管显示频率百位
dula = 1;
dula = 0;
wela = 0;
duan = dispbit[2];
wela = 1;
wela = 0;
delay();
delay();
delay();
delay();
delay();
delay();
dula = 0;

duan = dispcode[aa % 1000 / 100];  //这位数码管显示频率十位
dula = 1;
dula = 0;
wela = 0;
duan = dispbit[3];
wela = 1;
wela = 0;
delay();
delay();
delay();
delay();
delay();
delay();
dula = 0;
#ifdef gy
duan = dispcode[aa % 100 / 10] & 0x7F;  //这位数码管显示频率百位  开数码管的小数点
#else
duan = dispcode[aa % 100 / 10] | 0x80;  //这位数码管显示频率百位  开数码管的小数点
#endif
dula = 1;
dula = 0;
wela = 0;
duan = dispbit[4];
wela = 1;
wela = 0;
delay();
delay();
delay();
delay();
delay();
delay();
dula = 0;
   
duan = dispcode[aa % 10];  //这位数码管显示频率小数位
dula = 1;
dula = 0;
wela = 0;
duan = dispbit[5];
wela = 1;
wela = 0;
delay();
delay();
delay();
delay();
delay();
delay();
}
/*******************************************************************************/
//由频率计算PLL
void get_pll(void)
{
    unsigned char hlsi;
    unsigned int twpll = 0;
    hlsi = radio_write_data[2] & 0x10;
    if (hlsi)
  PLL = (unsigned int)((float)((frequency + 225) * 4) / (float)32.768);    //频率单位:k
    else
        PLL = (unsigned int)((float)((frequency - 225) * 4) / (float)32.768);    //频率单位:k
}
/***************************************************************************************/
//由PLL计算频率
void get_frequency(void)//读TEA5767状态,并转换成频率
{
    unsigned char hlsi;
    unsigned int npll = 0;
    npll = PLL;
    hlsi = radio_write_data[2] & 0x10;
    if (hlsi)
        frequency = (unsigned long)((float)(npll) * (float)8.192 - 225);    //频率单位:KHz
    else
        frequency = (unsigned long)((float)(npll) * (float)8.192 + 225);    //频率单位:KHz
}
/******************************************************************************************/
//读TEA5767状态,并转换成频率
void radio_read(void)//读收音机芯片数据
{
    unsigned char i;
    unsigned char temp_l,temp_h;
    PLL = 0;
iic_stop();  //结束总线传输
    iic_start(); //启动总线传输
    iic_write8bit(0xc1);        //TEA5767写地址
    if(!iic_testack())
    {
        for(i = 0;i < 5;i++)
        {
            radio_read_data = iic_rdbyt();//从总线上读取一个字节的数据
            iic_ack();  //发送应答位
        }
    }
    iic_stop();  //结束总线传输
//RF = radio_read_data[0] & 0x80;
IF = radio_read_data[2] & 0x7f;  //去掉最高位就是IF值
ADC = radio_read_data[3]; //去掉最高位就是IF值
ADC >>= 4;
//STEREO = radio_read_data[2] & 0x80; //最高位就是STEREO值
    temp_l = radio_read_data[1];
    temp_h = radio_read_data[0];
    temp_h &= 0x3f;
    PLL = temp_h * 256 + temp_l;
    get_frequency(); //读TEA5767状态,并转换成频率
}
/*****************************************************************************************/
#define max_freq 108000
#define min_freq 87500
//自动搜台,mode=1,频率增加搜台; mode=0:频率减小搜台
void auto_search(uchar dec)
{
int k = 0;
//unsigned char aa[6] = {0};
radio_write();//写收音机芯片数据
if(dec)//自动搜台,mode=1,频率增加搜台
{
  while(frequency < max_freq)//如果当前频率小于最大频率上限值
  {   
   get_pll();//由频率计算PLL
   radio_write_data[0] = PLL / 256;
   radio_write_data[1] = PLL % 256;
   radio_write_data[2] = 0xA0;  //增加频率搜索,低:ADC输出大小为5,高充电电流
   radio_write_data[3] = 0x11;  //fxtal=32.768KHz,软件静音开
   radio_write_data[4] = 0x80;  //6.5MHz的锁相环参考频率开,去加重时间常数为50us。
   radio_write_data[0] |= 0x40; //0100 0000 = SM / SM=1  则处于搜索模式
   radio_write();      //写入TEA5767
   desplay(frequency / 100);   //调用显示
   radio_read();     //读收音机芯片数据
   //if((radio_read_data[0] & 0x80))//如果有一个频道被搜到或者一个制式已经符合
   if((IF < 0x3e) && (IF > 0x31) && (ADC > 4))//&&(STEREO)&&(RF))//如搜到电台
   {
    frequency += 100;
    return;
   }
  }
  frequency = min_freq;//将最小频率下限值赋给当前频率
}
else//自动搜台, mode=0:频率减小搜台
{
  while(frequency > min_freq)//如果当前频率大于最小频率下限值
  {   
   get_pll();//由频率计算PLL
   radio_write_data[0] = PLL / 256;
   radio_write_data[1] = PLL % 256;
   radio_write_data[2] = 0x20;  //减小频率搜索,低:ADC输出大小为5,高充电电流
   radio_write_data[3] = 0x11;  //fxtal=32.768KHz,软件静音开
   radio_write_data[4] = 0x80;  //6.5MHz的锁相环参考频率开,去加重时间常数为50us。
   radio_write_data[0] |= 0x40; //0100 0000 = SM / SM=1  则处于搜索模式
   radio_write();      //写入TEA5767  
   desplay(frequency / 100);   //调用显示
   radio_read();//读收音机芯片数据
   //if((radio_read_data[0] & 0x80))//如果有一个频道被搜到或者一个制式已经符合
   if((IF < 0x3e) && (IF > 0x31) && (ADC > 4))//&&(STEREO)&&(RF))//如搜到电台
   {
    frequency -= 100;
    return;
   }
  }
  frequency = max_freq;//将最大频率上限值赋给当前频率
}
}
/*****************************************************************************************/
void main()
{
/*****************************************************************************************
//观察变量用
unsigned char B,D;
frequency = 104900;
PLL = (unsigned int)((float)((frequency + 225)) / (float)8.192);
B = PLL/256;
D = PLL % 256;
delay();
/****************************************************************************************/
delays(1000); //延时消抖
search();  //写入初始化电台频率
//radio_read();
while(1)
{
  if(!KEY1)  //手动设置频率, + 0.1MHz;
  {
   delays(250); //延时消抖
   frequency += 100;
   if(frequency > 108500)  //频率如果大于108.5MHz
   frequency = 87500;   //频率设定为87.5MHz
   search();     //将显示的频率算好后写到TEA5767芯片里面
   desplay(frequency / 100);   //调用显示
  }
/****************************************************************************************/
  if(!KEY2)   //手动设置频率,-0.1MHz;
  {
   delays(20); //延时消抖
   frequency -=100;
   if(frequency < 87500)  //频率如果小于87.5MHz
   frequency = 108500;   //频率设定为108.5MHz
   search();     //将显示的频率算好后写到TEA5767芯片里面
   desplay(frequency / 100);   //调用显示
  }
/***********************************************************************************/
  if(!KEY3)   //加频率
  {
   delays(250); //延时消抖
   if(!KEY3)
   {
     auto_search(1);//自动搜台,mode=1,频率增加搜台
   }
   while(!KEY3) desplay(frequency / 100);//调用显示
  }
/*****************************************************************************************/
  if(!KEY4)    //减频率
  {
   delays(20); //延时消抖
   if(!KEY4)
   {
     auto_search(0);//自动搜台mode=0:频率减小搜台
   }
   while(!KEY4) desplay(frequency / 100);//调用显示
  }
  desplay(frequency / 100);    //调用显示
}
}
/******************************************************************************************/
TEA5767资料.pdf (125.13 KB, 下载次数: 2010)

评分

参与人数 1金钱 +35 收起 理由
明浩 + 35 很给力!

查看全部评分

回复

使用道具 举报

发表于 2012-5-12 22:37:37 | 显示全部楼层
哇,好东西,可以听收音机了,而且好像来自于深圳~~~。
回复 支持 反对

使用道具 举报

发表于 2012-5-13 16:12:43 | 显示全部楼层
{:soso_e100:}
回复 支持 反对

使用道具 举报

发表于 2012-5-14 13:54:57 | 显示全部楼层
{:soso_e179:}不错,支持大家玩DIY
回复 支持 反对

使用道具 举报

发表于 2012-5-15 07:56:32 | 显示全部楼层
羡慕啊, 不容易的动手玩家
回复 支持 反对

使用道具 举报

发表于 2012-6-6 20:14:52 | 显示全部楼层
可以上原理图吗?
回复 支持 反对

使用道具 举报

发表于 2012-12-9 10:36:21 | 显示全部楼层
谢谢楼主分享,什么时候也diy个
回复 支持 反对

使用道具 举报

发表于 2013-4-30 22:14:27 | 显示全部楼层
谢谢楼主,怎么无法生成HEX文件,提示有一个错误[color=Red].(...\源代码.C(380): 错误 C213: left side of asn-op not an lvalue)不知是什么原因,希望楼主给与帮助。谢谢。
回复 支持 反对

使用道具 举报

发表于 2013-12-8 19:54:51 | 显示全部楼层
谢谢楼主分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入磁动力

本版积分规则

QQ|小黑屋|手机版|Archiver|www.cdle.net 磁动力电子网 2001-2017 ( 粤ICP备10098153号

粤公网安备 44040402000001号

GMT+8, 2019-3-20 05:41

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.