做了个高颜值fm收音机,电路代码全开源

闲来无事,制作了一个高颜值gsm-fm桌面收音机

它拥有7大功能网络时钟、FM广播、天气预报、B站数据统计、老黄历、背光调节、定时关机。


硬件说明

  • 主控:ESP32-S3FM
  • 芯片:RDA5807
  • 音频芯片:CS4344 I2S
  • 采集整机工作电流:INA199
  • 交互:一个旋转编码器


设计说明

将设计图分为6个部,并依次讲解:ESP32-S3电路、电源自动切换电路、软件开关机电路、USB转串口电路+自动烧录电路、PCB设计、外壳设计。

1.ESP32-S3电路

芯片选用内部带8MRAM+外接16M FLAM


2.电源自动切换电路

Q1是一个PMOS管,BAT+是电池,5V是充电器输入。

当充电器未接入时Q1导通,BAT+流过Q1给VCC供电,当充电器介入时,Q1截至5V流过D1给VCC供电。


3.软件开关机电路

U1是一个输出为3.3V的稳压芯片,该芯片带有使能功能。

即第3(CE)脚,给该引脚输入高电平,打开输出,输入低电平,关闭输入。VCC_KEY是按键脚,一端接到电源(VCC),另一端连接到单片机引脚(KEY_POWER),和U1使能脚电路。

接下来讲解按键开机过程、充电开机过程、关机过程的原理

按键开机过程

在未插入充电时。

按键按下后,VCC流过VCC_KEY、D4,给CE脚一个高电平使能3.3V输出,此时整个系统得电单片机开始运行。程序首先检测KEY_POWER脚电平,如果该电压为高电平,说明是按键开机控制POWER_IO脚输出高电平锁定CE脚电平。这时松开手,由于POWER_IO为高电平会继续使能U1输出。

充电开机过程

在未按下按键时。

插入充电器,此时5V得电,经过D3给CE脚高电平使能3.3V,输出单片机运行,程序开始检测KEY_POWER电平。由于内部配置下拉输入,所以识别到为低电平程序判断案件为按下时运行即充电开机。

关机过程

进入关机功能,确认关机后,系统拉低POWER_IO使能3.3输出。


4.USB转串口电路+自动烧录电路

ESP32-S3支持串口下载。由于电脑没有TTL串口接口,所以需要一个USB转串口芯片

U7型号是CH340C,该芯片支持一路usb转串口ttl,带有RTS、DTR控制引脚,内部集成晶振大大简化了外部电路。

根据ESP3S3数据手册,进入串口下载模式,需要在上电前拉低IO0。

上面介绍了CH340C带有RTS、DTR引脚,可以加入开关控制电路来实现自动复位和拉低IO0

如图,Q6芯片型号是UMH3N,该芯片内部带有两个三极管并且集成偏置电压,再利用CH340C的RTS、DTR引脚可以实现自动下载程序


5.PCB设计

整个项目使用一张双层PCB,如图6、图7。


6.外壳设计

外壳使用Autodesk Fusion 360设计制作。


安装说明

屏幕通过双面胶贴在PCB上,PCB卡在外壳的内壁槽里,通过一颗螺丝固定。

天线通过外壳孔槽插入内部,使用螺丝固定导线到外壳上。

扬声器直接卡在外壳槽里。

电池放在内部空余空间。

设计好外壳后使用3d打印,然后使用自喷漆更换外壳颜色。


软件说明

硬件电路设计并焊接完成后就可以开始编写代码了,这个项目使用的是乐鑫官方的ESP-IDF5.0。

本章节着重讲解——开机动画部分。

开机动画使用的LVGL GIF库,在开发过程中使用VS模拟器可以正常播放

但你有可能会遇见这种问题:

当移植到ESP32播放时,开机动画会持续卡死,且把动画剪切成了两部分,缩小时长还是不行。

解决方法

可以使用预加载到PSRAM解决该问题。

上述情况的具体实现代码如下:

定义两个空指针
char *p_gif1 = NULL;
char *p_gif2 = NULL;
加载gif
load_gif(&p_gif1,"/spiffs/power_on_gif_01.gif");
load_gif(&p_gif2,"/spiffs/power_on_gif_02.gif");
加载过程
bool load_gif(char **p,char *file)
{
    bool r_dat = false;
    long size=0,r_size=0;
    main_debug("加载文件:%s",file);
    FILE* f = fopen(file, "r");
    if (f != NULL)
    {
        main_debug("打开成功");
        size = get_file_size(f);
        main_debug("文件大小:%ld",size);
        *p = malloc(size);
        if(*p != NULL)
        {
            main_debug("内存申请成功");
            r_size = fread(*p, 1, size, f);
            if(r_size == size)
            {
                main_debug("读取成功");
            }
            r_dat = true;
        }else
        {
            main_debug("内存申请失败");
        }
        fclose(f);
    }
    return r_dat;
}
使用
lv_gif_create_from_data(lvgl_power_on_data.cont_main, p_gif1);
lv_gif_create_from_data(lvgl_power_on_data.cont_main, p_gif2);
使用完释放内存
free(p_gif1);
free(p_gif2);

如果你需要完整的带注释的代码、电路、外壳源文件,可以自取,无偿分享的:
https://oshwhub.com/yeshengchengxuyuan/gsm-fm-5-0


看到这里,你会想动手DIY一个这样的高颜值收音机吗?


文章资料参考来源:立创开源硬件平台《gsm-fm桌面收音机》作者:野生程序员

https://oshwhub.com/yeshengchengxuyuan/gsm-fm-5-0


如果你认为这篇文章还不错,欢迎点赞、关注、收藏、转发~

我会持续更新优质开源项目

相关文章

C语言错误处理不当详解

在C语言编程中,错误处理是一个至关重要的方面,但常常被忽视或处理不当。忽略函数返回值、不检查错误代码或未能从错误中优雅恢复,都可能导致程序行为不可预测、数据损坏、安全漏洞甚至程序崩溃。什么是错误处理不...

C语言控制标准I/O的5个函数

与底层I/O相比,标准I/O包除了可移植以外还有两个好处。第一,标准I/O有许多专门的函数简化了处理不同I/O的问题。例如,printf()把不同形式的数据转换成与终端相适应的字符串输出。第二,输入和...

C语言之文件操作

文件操作是C语言中非常重要的功能,用于读取和写入文件中的数据。C语言提供了一组标准库函数(如 fopen、fclose、fread、fwrite 等)来实现文件操作。以下是针对C语言初学者的详细讲解。...

35岁非科班出身程序员写下C语言文件读写操作(详解),牛

数据流和缓冲区是什么?文件类型和文件存取方式都有啥?数据流就C程序而言,从程序移进,移出字节,这种字节流就叫做流。程序与数据的交互是以流的形式进行的。进行C语言文件的读写时,都会先进行“打开文件”操作...

C语言这些常见标准文件该如何使用?很基础也很重要

谈到文件,先了解下什么是文本文件和二进制文件的区别吧!1、文本文件:存储时是将字符的ASCII值存在磁盘中,取的时候将数值(ASCII)翻译成对应的字符;2、二进制文件:存取的都是二进制;文件流指针:...

初学者指南——文件包含(LFI / RFI)

在C语言中文件包含是指一个源文件可以将另一个源文件的全部内容包含进来。该命令的作用是在预编译时,将指定源文件的内容复制到当前文件中。文件包含是C语言预处理命令三个内容之一。一个大程序,通常分为多个模块...