基于STM32F103+TEA5767的收音机实现

您所在的位置:网站首页 收音机set 基于STM32F103+TEA5767的收音机实现

基于STM32F103+TEA5767的收音机实现

2024-06-26 06:55:29| 来源: 网络整理| 查看: 265

#申请原创#@21小跑堂 源码回复下载: 游客,如果您要查看本帖隐藏内容请回复 前言

前段时间给表弟捯饬了一个基于TEA5767模块的收音机,虽说目前收音机本身已经在市场没啥存在感了,但是技术的运用还是具有一定的研究意义,特别是对我这种技术新人来说,做一次简易的小玩意,可熟悉单片机的一些基础外设,同时可通过这个小玩意锻炼一下自己的画板能力,不得不说,画板真是我的硬伤,**大佬看到我的PCB图下手轻点。

一、方案选型l 主控:STM32F103C8T6,主要考虑使用之前最熟练的单片机,在画板和代码编写上更为自由方便。l 收音机模块:TEA5767收音机模块,因为本人硬件水平欠佳,直接买了模组,使用IIC接口进行通信。l 音频功放:LM386D。l 显示器:0.96 OLED 二、功能概述l 通过0.96 OLED液晶实时显示收音机的频率。l 2、通过按键可以调节频率,当调制解调成功后,喇叭输出广播或者通过耳机进行收听,喇叭音量可通过可调电阻进行控制。l 3、频率调节范围:87.5MHZ--108MHZ。l 4、可一键自动搜台。三、系统结构

5987165321fe048c67.png (24.45 KB )

下载附件

2023-10-20 14:36 上传

因手头9V的电源很多,所以此处电源的输入为9V DC电源,通过降压电路将9V的电源降至5V和3.3V,5V给TEA5767收音机模块、音频功放电路和OLED的显示,3.3V给单片机供电。STM32F103通过IIC和TEA5767通信,音频输出可以通过耳机或者通过音频功放电路通过喇叭进行输出,喇叭输出电路可通过可调电阻进行调节,通过按键进行频道的加减,也可通过自动搜台按键自动搜索可用频道,当前的频道可通过OLED进行显示。

四、硬件电路设计1. STM32最小系统

761626532201bd1bd5.png (135.58 KB )

下载附件

2023-10-20 14:37 上传

STM32最小系统的电路包括复位电路,晶振电路和电源电路,同时添加一颗LED用于显示供电状态。

2. 电源电路

4349565322041ac515.png (44.69 KB )

下载附件

2023-10-20 14:37 上传

电源输入为9V直流电源,通过78L05将电压将至5V,再通过HT7533将至3.3V,同时也添加滤波。

3. 按键电路

992956532206e8ac1b.png (42.83 KB )

下载附件

2023-10-20 14:38 上传

按键一共三个,分别是加频道、减频道和自动搜台。4. TEA5767模块电路

39333653220912b838.png (40.69 KB )

下载附件

2023-10-20 14:39 上传

5. 0.96寸OLED电路

38577653220a732710.png (14.72 KB )

下载附件

2023-10-20 14:39 上传

6.完整电路

25230653220b7ecd81.png (182.71 KB )

下载附件

2023-10-20 14:39 上传

7.PCB

15177653220c5086a2.png (118.33 KB )

下载附件

2023-10-20 14:40 上传

13270653220cd5457d.png (118.82 KB )

下载附件

2023-10-20 14:40 上传

五、软件代码设计1. IIC驱动TEA5767模块使用IIC协议通信,且对速率要求不高,此处采用软件模拟的方式进行。首先使用宏定义对GPIO和电平输入/输出进行定义:复制#define SDA_RCC                        RCC_APB2Periph_GPIOB #define SDA_GPIO                GPIOB #define SDA_GPIO_PIN        GPIO_Pin_7 #define SCL_RCC                        RCC_APB2Periph_GPIOB #define SCL_GPIO                GPIOB #define SCL_GPIO_PIN        GPIO_Pin_6 #define SCL_OUT() SCL_Set_Output() //置位scl #define SET_SCL() GPIO_SetBits(SCL_GPIO, SCL_GPIO_PIN) //置位scl #define CLE_SCL() GPIO_ResetBits(SCL_GPIO, SCL_GPIO_PIN)//清楚scl                      #define SDA_OUT() SDA_Set_Output() #define SDA_INT() SDA_Set_Input() #define SET_SDA() GPIO_SetBits(SDA_GPIO, SDA_GPIO_PIN)//置位sda #define CLE_SDA() GPIO_ResetBits(SDA_GPIO, SDA_GPIO_PIN)//清楚sda #define SDA_VAL() GPIO_ReadInputDataBit(SDA_GPIO, SDA_GPIO_PIN) #define SDA_V PBin(7) #define SDA PBout(7)         #define SCL PBout(6)        IIC初始化及相关功能函数定义:复制void SCL_Set_Output(void) {         GPIO_InitTypeDef  GPIO_InitStructure;                  RCC_APB2PeriphClockCmd(SDA_RCC,ENABLE);//使能时钟                  GPIO_InitStructure.GPIO_Pin = SCL_GPIO_PIN;                                          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                          GPIO_Init(SCL_GPIO, &GPIO_InitStructure);                                                                                  }         void SDA_Set_Output(void) {         GPIO_InitTypeDef  GPIO_InitStructure;                          RCC_APB2PeriphClockCmd(SDA_RCC,ENABLE);//使能时钟                  GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN;                                          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                          GPIO_Init(SDA_GPIO, &GPIO_InitStructure);                                                                                  }         void SDA_Set_Input(void) {         GPIO_InitTypeDef  GPIO_InitStructure;         RCC_APB2PeriphClockCmd(SCL_RCC,ENABLE);//使能时钟                 GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN;                                          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                           GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                          GPIO_Init(SDA_GPIO, &GPIO_InitStructure);                                          } //****************************************** void init(void) {                  SCL_OUT();     SDA_OUT();     numbyte = 5;         numbyte_AMP=5;     ADDRESS_SEND = 0xC0;// TEA5767写地址 1100 0000         ADDRESS_RECEIVE=0XC1;//TEA5767读地址 1100 0001     ADDRESS_AMP=0X8E;             FM_PLL=0X302C;     FM_FREQ=97000000; //开机预设频率      PLL_HIGH=0;     PLL_LOW=0;     delay_ms(100);// delay100ms();     delay_ms(100);//delay100ms();                     I2C_byte1=0XF0;  //FM模块预设值     I2C_byte2=0X2C;     I2C_byte3=0XD0;     I2C_byte4=0X10;     I2C_byte5=0X40;     byte1=0X27;       byte2=0X40;     byte3=0X42;     byte4=0X46;     byte5=0XC3;                     sendnbyte(&ADDRESS_SEND,numbyte);     delay_ms(100);//delay100ms();     AMP_sendnbyte(&ADDRESS_AMP,numbyte_AMP); } /** [url=home.php?mod=space&uid=247401]@brief[/url] CPU产生一个ACK信号 @param 无 [url=home.php?mod=space&uid=266161]@return[/url] 无 */ void IIC_Ack(void) {     SDA_OUT();         // SDA线输出模式        SDA=0;            // CPU驱动SDA = 0     delay_us(5);     SCL=1;            // CPU产生1个时钟     delay_us(5);     SCL=0;     delay_us(5);     SDA=1;            // CPU释放SDA总线 } /** [url=home.php?mod=space&uid=247401]@brief[/url] CPU产生一个时钟,并读取器件的ACK应答信号 @param 无 [url=home.php?mod=space&uid=266161]@return[/url] 返回0表示正确应答,1表示无器件响应 */ uint8_t IIC_WaitAck(void) {     uint8_t result = 0;         SDA_INT();          // SDA线输入模式       SDA = 1;            // CPU释放SDA总线     delay_us(5);     SCL = 1;            // CPU驱动SCL = 1, 此时器件会返回ACK应答     delay_us(5);     if(SDA_VAL())     {         result = 1;     }     else     {         result = 0;     }     SCL = 0;     delay_us(5);     return result;   } //************************************************ //送n字节数据子程序 void sendnbyte(uchar *sla, uchar n) {                  uchar *p;         sbuf[0]=I2C_byte1;         sbuf[1]=I2C_byte2;         sbuf[2]=I2C_byte3;         sbuf[3]=I2C_byte4;         I2C_start();                        // 发送启动信号         sendbyte(sla);                    // 发送从器件地址字节         checkack();                            // 检查应答位    if(foo == 1)         {                 NACK = 1;                 return;                    // 若非应答表明器件错误置错误标志位NACK         }         delay_us(5);                  p = &sbuf[0];         while(n--)         {                 sendbyte(p);                 checkack();            // 检查应答位                                 delay_us(5);                                 if (foo == 1)                 {                         NACK=1;                         return;            // 若非应答表明器件错误置错误标志位NACK                 }                 p++;         }         stop();                            // 全部发完则停止 } /** @brief CPU从I2C总线设备读取8bit数据 @param 无 @return 读到的数据 */ uint8_t IIC_ReadByte(void) {     uint8_t i = 0;     uint8_t value = 0;         SDA_INT();          // SDA线输入模式     for(i = 0; i < 8; i++)     {         value > 8)&0X3f);         //PLL高字节值    I2C_byte1=(I2C_byte1&0XC0)|PLL_HIGH;                 //I2C第一字节值    PLL_LOW=(uchar)FM_PLL;                                         //PLL低字节值    I2C_byte2= PLL_LOW;                                                 //I2C第二字节值    sendnbyte(&ADDRESS_SEND,numbyte);             //I2C数据发送    I2C_byte1 &= ~MUTEI2CB1;//MUTE=0;    delay_ms(100);//delay100ms();                                                  //延时100ms    sendnbyte(&ADDRESS_SEND,numbyte);          //I2C        数据发送    delay_us(5);//DELAY5US; }2.在主函数循环检测按键状态复制 int main(void) {                        RCC_ClocksTypeDef ClockInfo;         SystemInit();         delay_init();                     //延时函数初始化                  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 //        uart_init(115200);         //串口初始化为115200          LED_Init();                             //LED端口初始化         TIM3_Int_Init(499,7199);//10Khz的计数频率,计数到5000为500ms           RCC_GetClocksFreq(&ClockInfo);         init();                              //  初始化TEA5767         KEY_Init();         OLED_Init();                        //初始化OLED           OLED_Clear();         //上电初始化界面         num1=FM_FREQ/100000000;                                                //提取频率值         num2=(FM_FREQ%100000000)/10000000;         num3=(FM_FREQ%10000000)/1000000;         num4=(FM_FREQ%1000000)/100000;         OLED_ShowString(35,0,"TEA5767",16);         OLED_ShowString(0,3,"FM:",16);                           OLED_ShowNum(50,3,num1,1,16);         OLED_ShowNum(60,3,num2,1,16);         OLED_ShowNum(70,3,num3,1,16);         OLED_ShowString(80,3,".",16);         OLED_ShowNum(85,3,num4,1,16);         OLED_ShowString(100,3,"MHz",16);                           while(1)         {                 if((KEY0==0)||(KEY1==0)||(KEY2==0))//按键按下                 {                         {                                 delay_ms(10);//消除抖动                                 if(KEY0==0)                //按键显示切换                                 {                                         rekey = 1;                                         search_up();          //频率向上                                         delay_ms(200);//消除抖动                                 }                                 else  if(KEY1==0)                //按键显示切换                                 {                                         rekey = 1;                                         search_down();          //频率向上                                         delay_ms(200);//消除抖动                                 }                                 else  if(KEY2==0)                //按键显示切换                                 {                                         rekey = 1;                                         TEA5767_AutoSearch();          //自动搜台                                         delay_ms(200);//消除抖动                                 }                         }                                }                                                 }                                                                                             }         附录写数据

向TEA5767 写入数据时,地址的最低位是0,即写地址是C0。读出数据时地址的最低位是1,即读地址是C1。TEA5767的控制寄存器要写入5个字节,每次写入数据时必须严格按照下列顺序进行:

地址、字节1、字节2、字节3、字节4、字节5。

每个字节的最高位首先发送。在时钟的下降沿后写入的数据生效。上电复位后,设置为静音,所有其它位均被置低,必须写入控制字初始化芯片。

TEA5767内部有一个5个字节的控制寄存器,在IC上电复位后必须通过总线接口向其中写入适当的控制字,它才能够正常工作。寄存器介绍如下

数据字节1的格式

537616532224af198d.png (13.76 KB )

下载附件

2023-10-20 14:46 上传

数据字节1各位的说明

787665322266cec92.png (22.57 KB )

下载附件

2023-10-20 14:47 上传

数据字节2的格式

6699653222a5157ab.png (12.77 KB )

下载附件

2023-10-20 14:48 上传

数据字节2各位的说明

83769653222bae4b78.png (15.83 KB )

下载附件

2023-10-20 14:48 上传

数据字节3的格式

72588653222e23acca.png (13.08 KB )

下载附件

2023-10-20 14:49 上传

数据字节3各位的说明

12693653222f025216.png (45.45 KB )

下载附件

2023-10-20 14:49 上传

搜索停止电平设定

57160653223054533c.png (17.87 KB )

下载附件

2023-10-20 14:49 上传

数据字节4的格式

5026532233360a3c.png (13.91 KB )

下载附件

2023-10-20 14:50 上传

数据字节4各位的说明

178396532233e5bd6c.png (56.33 KB )

下载附件

2023-10-20 14:50 上传

数据字节5的格式

21378653223490cf6c.png (11.76 KB )

下载附件

2023-10-20 14:50 上传

数据字节5各位的说明

4919653223573dff4.png (26.12 KB )

下载附件

2023-10-20 14:51 上传

读数据

和写数据类似,从TEA5767 读出数据时,也要按照“地址、字节1、字节2、字节3、字节4、字节5”这样的顺序读出,读地址是C1。

63134653223907b408.png (47.94 KB )

下载附件

2023-10-20 14:52 上传

97803653223b49df41.png (131.41 KB )

下载附件

2023-10-20 14:52 上传

600653223b4cfb7e.png (131.41 KB )

下载附件

2023-10-20 14:52 上传

举例根据上面的算法,以106.8的天津交通台为例,它的PLL为32d1H,第一个字节的BIT7=0非静音,BIT6=0不搜索,第三个字节的BIT4=0低本振,第四个字节的BIT5=0欧美制式,BIT4=1用32768晶振,其余位的设置无所谓,可任意。


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭