基于51单片机FM数字收音机设计

2024-06-20 05:28

本文主要是介绍基于51单片机FM数字收音机设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于51单片机FM数字收音机

(程序+原理图+PCB+设计报告)

功能介绍

具体功能:

该系统利主要由STC89C51单片机、液晶显示器、按键、调频收音模块TEA5767、功放LM386组成。

1.收音芯片采用TEA5767模块,采用LM386芯片放大音频功率;

2.LCD1602液晶显示当前所收听的FM频道;

3.可以通过按键进行调换,实现87.5MHz~108MHz调频广播的接收;

​演示视频:

基于51单片机FM数字收音机设计 

添加图片注释,不超过 140 字(可选)

程序

/**************************************************************** 
/***公众号:木子单片机****
工程名称:数字收音机
功能: 以LCD1602为显示的TEA5767模块的收音机***************************************************************/#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 0000ADDRESS_RECEIVE=0XC1;//TEA5767读地址 1100 0001ADDRESS_AMP=0X8E;init();      //  初始化TEA5767show();     //开机问候语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不能大于1if (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--);}
}
//******************************************
void init(void)
{ uchar idata sbuf[5]={0XF0,0X2C,0XD0,0X10,0X40};  //FM模块预设值uchar idata rbuf[5]={0X00,0X00,0X00,0X00,0X00};uchar idata ampint[5]={0X27,0X40,0X42,0X46,0XC3};FM_PLL=0X302C;FM_FREQ=97000000; //开机预设频率 PLL_HIGH=0;PLL_LOW=0;delay100ms();delay100ms();P1=0XFF;P2=0XFF;I2C_byte1=0XF0;  //FM模块预设值I2C_byte2=0X2C;I2C_byte3=0XD0;I2C_byte4=0X10;byte1=0X27;  byte2=0X40;byte3=0X42;byte4=0X46;sendnbyte(&ADDRESS_SEND,numbyte);delay100ms();AMP_sendnbyte(&ADDRESS_AMP,numbyte_AMP);
}
//************************************************
//送n字节数据子程序 
void sendnbyte(uchar idata *sla, uchar n)
{          uchar idata *p;sbuf[0]=I2C_byte1;sbuf[1]=I2C_byte2;sbuf[2]=I2C_byte3;sbuf[3]=I2C_byte4;I2C_start();			// 发送启动信号sendbyte(sla);    		// 发送从器件地址字节checkack();    			// 检查应答位if(F0 == 1){ NACK = 1;return;    		// 若非应答表明器件错误置错误标志位NACK}p = &sbuf[0];while(n--){ sendbyte(p);checkack();    	// 检查应答位if (F0 == 1){NACK=1;return;    	// 若非应答表明器件错误置错误标志位NACK}p++;}stop();    			// 全部发完则停止
}
//***********************************************
延迟100ms
void delay100ms()				
{uchar i;for(i=100;i>0;i--){delay1ms();}
}
//**********************************************
//延迟1msvoid delay1ms(void)	          	
{uchar i;for(i=1000;i>0;i--){;}
}
//*************************************************
//在SCL为高时,SDA由高变低即为I2C传输开始
void I2C_start(void)   
{SDA=1;SCL=1;DELAY5US;SDA=0;}
//****************************************************
//发送一个字节数据子函数
void sendbyte(uchar idata *ch){ uchar idata n = 8;  uchar idata temp;temp = *ch;while(n--){ if((temp&0x80) == 0x80)    // 若要发送的数据最高位为1则发送位1{SDA = 1;    // 传送位1SCL = 1;DELAY5US;}else{  SDA = 0;    // 否则传送位0SCL = 1;DELAY5US;SCL = 0;  }temp = temp<<1;    // 数据左移一位}
}
//发送n字节数据子程序
void AMP_sendnbyte(uchar idata *sla, uchar n)
{          uchar idata *p;ampint[0]=byte1;ampint[1]=byte2;ampint[2]=byte3;ampint[3]=byte4;ampint[4]=byte5;	I2C_start();			// 发送启动信号sendbyte(sla);    		// 发送从器件地址字节checkack();    			// 检查应答位if(F0 == 1){ NACK = 1;return;    		// 若非应答表明器件错误置错误标志位NACK}p=&ampint[0];while(n--){ sendbyte(p);checkack();    	// 检查应答位if (F0 == 1){NACK=1;return;    	// 若非应答表明器件错误置错误标志位NACK}p++;																		  }stop();    			// 全部发完则停止
}
//****************************************

硬件设计

使用元器件:

单片机:STC89C51;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

9*15万用板;40脚IC座;

LCD1602液晶;103电位器(蓝白);

16P排阵;16脚液晶IC座;

220uf电解电容;100uf电解电容;

10k电阻;10uf电容;30pf电容*2;

12M晶振;轻触按键*3;

TEA5767模块;104pf*2;

103电位器(精密大号);

耳机插口;伸缩天线;

LM386;8脚IC座;

2P白色插口;红黑并线;

8欧5W喇叭;

导线:若干;

添加图片注释,不超过 140 字(可选)

流程图:

 

设计资料

01原理图

本系统原理图采用Altium Designer19设计,具体如图!

添加图片注释,不超过 140 字(可选)

02PCB

本系统pcb采用Altium Designer19设计,具体如图!

添加图片注释,不超过 140 字(可选)

03程序

本设计使用软件Keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

04设计报告

一万两千字设计报告,具体如下!

添加图片注释,不超过 140 字(可选)

05设计资料

        资料获取请关注同名公众号,全部资料包括程序(含注释)、AD原理图、PCB、设计报告、流程图、答辩PPT、实物图、元件清单等。具体内容如下,全网最全! !

 

可以关注下方公众号!

点赞分享一起学习成长。

这篇关于基于51单片机FM数字收音机设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1077222

相关文章

Python中的可视化设计与UI界面实现

《Python中的可视化设计与UI界面实现》本文介绍了如何使用Python创建用户界面(UI),包括使用Tkinter、PyQt、Kivy等库进行基本窗口、动态图表和动画效果的实现,通过示例代码,展示... 目录从像素到界面:python带你玩转UI设计示例:使用Tkinter创建一个简单的窗口绘图魔法:用

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

从去中心化到智能化:Web3如何与AI共同塑造数字生态

在数字时代的演进中,Web3和人工智能(AI)正成为塑造未来互联网的两大核心力量。Web3的去中心化理念与AI的智能化技术,正相互交织,共同推动数字生态的变革。本文将探讨Web3与AI的融合如何改变数字世界,并展望这一新兴组合如何重塑我们的在线体验。 Web3的去中心化愿景 Web3代表了互联网的第三代发展,它基于去中心化的区块链技术,旨在创建一个开放、透明且用户主导的数字生态。不同于传统

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (

day-51 合并零之间的节点

思路 直接遍历链表即可,遇到val=0跳过,val非零则加在一起,最后返回即可 解题过程 返回链表可以有头结点,方便插入,返回head.next Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}*

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

SprinBoot+Vue网络商城海鲜市场的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质创作者,全网30w+

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订

Spring的设计⽬标——《Spring技术内幕》

读《Spring技术内幕》第二版,计文柯著。 如果我们要简要地描述Spring的设计⽬标,可以这么说,Spring为开发者提供的是⼀个⼀站式的轻量级应⽤开发框架(平台)。 作为平台,Spring抽象了我们在 许多应⽤开发中遇到的共性问题;同时,作为⼀个轻量级的应⽤开发框架,Spring和传统的J2EE开发相⽐,有其⾃⾝的特点。 通过这些⾃⾝的特点,Spring充分体现了它的设计理念:在