基于51单片机TEA5767的FM数字收音机原理图程序设计

链接:https://pan.baidu.com/s/10tXZyQjqkFi-KFaApVWgHw
提取码:r0bg

硬件设计

该系统利主要由STC89C52单片机、液晶显示器、按键、调频收音模块TEA5767、功放LM386组成[1]。实际运行时,用TEA5767搜索频率,利用单片机STC89C52控制处理,经LM386芯片放大音频功率同时再通过液晶显示器显示频率,最终实现87.5MHz~108MHz调频广播的接收

系统以STC89C52单片机作为控制模块,无线FM模块作为调频选台模块。系统框图如图1-1所示。
在这里插入图片描述
原理图:
在这里插入图片描述

程序设计

在这里插入图片描述

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

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define DELAY5US _nop_();_nop_();_nop_();_nop_();_nop_();
//**************TEA5767模块接线方法********************
sbit SDA=P1^0;     
sbit SCL=P1^1;
//*************频率调节按键接线************************
sbit Key1=P1^2;
sbit Key2=P1^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^6;  //读写控制输入端,LCD1602的第五脚
sbit    LCM_RS     = P2^5;  //寄存器选择输入端,LCD1602的第四脚
sbit    LCM_E      = P2^7;  //使能信号输入端,LCD1602的第6脚
//*****************参数定义*****************************
unsigned long int  FM_FREQ;  //频率
unsigned short int FM_PLL;   //PLL
uchar 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);  //延迟600ms
void    delay100ms(void);	//延迟100ms
void    delay10ms();
void    delay1ms(void);	//延迟1ms
void    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    show();     //开机问候语
//*****************主程序******************************
void main(void)
{   
	  
    numbyte = 5;
	  numbyte_AMP=5;
    ADDRESS_SEND = 0xC0;// TEA5767写地址 1100 0000
	  ADDRESS_RECEIVE=0XC1;//TEA5767读地址 1100 0001
    ADDRESS_AMP=0X8E;
    init();      //  初始化TEA5767
	  show();     //开机问候语
    LCMInit();//LCD初始
    LCDshow();
    while(1)
    {          
	    key_scan();			 //键扫描
    }

}

//**************开机问候语**************************
void show()
{
	     LCMInit();//LCD初始
	   
	     DisplayOneChar(0, 1,'H');//
       DisplayOneChar(0, 2,'e');//
       DisplayOneChar(0, 3,'l');//
       DisplayOneChar(0, 4,'l');//
       DisplayOneChar(0, 5,'o');//
       DisplayOneChar(0, 6, ',');
	     DisplayOneChar(0, 7,'W');//
       DisplayOneChar(0, 8,'e');//
       DisplayOneChar(0, 9, 'l');
       DisplayOneChar(0, 10, 'c');
       DisplayOneChar(0, 11, 'o');
       DisplayOneChar(0, 12, 'm');
       DisplayOneChar(0, 13, 'e');
       DelayMs(500);
	     
	     DisplayOneChar(1, 1,' ');// 显示姓名
	     DisplayOneChar(1, 2,' ');//
       DisplayOneChar(1, 3,' ');//
       DisplayOneChar(1, 4,' ');//
       DisplayOneChar(1, 5,' ');//
       DisplayOneChar(1, 6,' ');//
       DisplayOneChar(1, 7,' ');
	     DisplayOneChar(1, 8,' ');//
       DisplayOneChar(1, 9,' ');//
       DisplayOneChar(1, 10,' ');
       DisplayOneChar(1, 11,' ');
       DisplayOneChar(1, 12,' ');
       DisplayOneChar(1, 13,' ');
       DisplayOneChar(1, 14,' ');
	     
	     DelayMs(500);
	
	    
  
}
//**************按键扫描程序************************
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;
 DelayMs(1);
 LCM_RW = 0;
 DelayMs(1);
 LCM_E = 0; //若晶振速度太高可以在这后加小的延时
 LCM_E = 0; //延时
 DelayMs(1);
 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控制器忙。
  读状态
======================================================================*/
uchar ReadStatusLCM(void)
{
 LCM_Data = 0xFF;
 LCM_RS = 0;
 LCM_RW = 1;
 LCM_E = 0;
 LCM_E = 0;
 LCM_E = 1;
 while (LCM_Data & Busy); //检测忙信号  
 return(LCM_Data);
}
/*======================================================================
功 能:     在1602 指定位置显示一个字符:第一行位置0~15,第二行16~31
说 明:     第 X 行,第 y 列  注意:字符串不能长于16个字符
======================================================================*/
void DisplayOneChar( uchar X, uchar Y, uchar ASCII)
{
  X &= 0x1;
  Y &= 0xF; //限制Y不能大于15,X不能大于1
  if (X) Y |= 0x40; //当要显示第二行时地址码+0x40;
  Y |= 0x80; // 算出指令码
  WriteCommandLCM(Y, 0); //这里不检测忙信号,发送地址码
  WriteDataLCM(ASCII);
}
/*====================================================================
  设定延时时间:x*1ms
====================================================================*/
void DelayMs(uint Ms)
{
  uint i,TempCyc;
  for(i=0;i<Ms;i++)
  {
    TempCyc = 250;
    while(TempCyc--);
  }
}

.

.

  • 3
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值