调频模块:基于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; //PLLuchar 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); //延迟600msvoid delay100ms(void);//延迟100msvoid delay10ms();void delay1ms(void);//延迟1msvoid 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_FREQ0000000)/10000000; num3=(FM_FREQ000000)/1000000; num4=(FM_FREQ00000)/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--); }}

.

.

相关推荐

相关文章