基于ESP32-S3的双模收音机设计:从FM广播到GSM信号监测

📅 2026/7/28 7:23:24 👁️ 阅读次数 📝 编程学习
基于ESP32-S3的双模收音机设计:从FM广播到GSM信号监测

1. 项目概述:为什么是ESP32-S3与GSM-FM?

几年前,我还在用传统的DSP芯片折腾收音机,调试I2C、写寄存器、焊天线,过程繁琐不说,功能也单一。直到ESP32-S3这颗芯片进入视野,事情开始变得有趣。它不仅仅是一个Wi-Fi/蓝牙的MCU,其强大的双核处理能力、充足的PSRAM和灵活的I2S/IO矩阵,让它成为了一个绝佳的“软件定义无线电”入门平台。而“GSM-FM桌面收音机”这个想法,就是想把两个看似不相关的频段——古老的调频广播和曾经无处不在的2G GSM信号——整合到一台精致的桌面设备里,让它既能回味经典的电波,又能窥见数字通信时代的底层脉搏。

这台收音机能做什么?核心是双模接收。FM波段(通常为87.5-108 MHz)让你收听本地广播电台,享受音乐和新闻。而GSM波段(这里主要指GSM-900的上行链路935-960 MHz)的接收,则是一种纯粹的“技术监听”。你无法解密或听懂通话内容(那是非法的),但可以“看到”信号的存在,观察场强变化,理解蜂窝网络的基础架构如何在你身边无声地运转。它适合谁?适合对无线电感兴趣、喜欢动手、不满足于黑盒消费电子产品的硬件爱好者、嵌入式开发者,以及任何想深入了解身边电磁环境的朋友。通过这个项目,你不仅能获得一台独一无二的桌面摆件,更能亲手触摸到从模拟到数字的无线电波。

2. 核心硬件选型与设计思路

做一台收音机,听起来简单,但涉及到射频(RF)前端,就需要格外谨慎。选型的核心原则是:在性能、复杂度和成本之间找到最佳平衡点,确保项目可重复、可调试。

2.1 主控芯片:为什么是ESP32-S3?

ESP32-S3并非为射频直接采样设计,但它有几个关键优势,使其成为本项目的“大脑”首选:

  1. 强大的计算与内存:双核Xtensa LX7处理器,主频高达240MHz,搭配外部PSRAM(我用了8MB),为实时处理I/Q数据流提供了充足的算力。FM解调和简单的GSM信号分析(如功率测量、频谱显示)都是计算密集型任务。
  2. 丰富的数字外设:关键的I2S接口,可以配置为接收来自射频芯片的数字化I/Q数据流。其DMA能力能极大减轻CPU负担。此外,充足的GPIO、SPI、I2C接口用于连接屏幕、编码器、存储等外围设备。
  3. 成熟的生态与开发体验:基于ESP-IDF框架,有Arduino core可选,社区资源丰富。PlatformIO或VSCode的调试体验远好于传统的单片机开发环境,这对于需要大量算法调试的项目至关重要。

注意:ESP32-S3的ADC采样率有限,无法直接对高频射频信号进行采样。因此,我们必须依赖专用的射频调谐器或收发器芯片来完成“下变频”和“模数转换”的工作。

2.2 射频前端方案:专用芯片 vs. SDR模块

这是项目的核心决策点。直接使用成熟的RTL-SDR USB棒最简单,但失去了“嵌入式”和“桌面一体机”的乐趣。我们需要一个能集成到PCB上的方案。

  1. 方案一:SI4732/4735 数字调谐芯片

    • 优点:专为AM/FM广播设计,集成度高,灵敏度好,自带数字音频输出(I2S),驱动成熟。对于纯FM收音机,这是最稳妥、性能最好的选择。
    • 缺点:频率范围有限(通常最高到230MHz),无法接收900MHz的GSM信号。这意味着要实现双模,必须额外增加GSM接收通道。
  2. 方案二:RDA5807/5808 FM芯片 + 独立GSM接收链路

    • 优点:成本极低,RDA5807系列是经典的FM接收芯片,通过I2C控制,音频输出简单。
    • 缺点:同样无法覆盖GSM频段,需要为GSM设计另一套接收机,增加了系统复杂性。
  3. 方案三:软件定义无线电(SDR)收发器芯片(如AD936x, LMS6002D)

    • 优点:频率覆盖极宽(70MHz – 6GHz),带宽大,真正的SDR,可以同时处理FM和GSM。
    • 缺点:电路极其复杂,需要高速时钟、多路电源、复杂的匹配网络,BGA封装焊接难度大,成本高昂(芯片本身可能就超过百元),远超爱好者项目范畴。
  4. 方案四:零中频接收器芯片(如TEA5767 FM + CC1101 433MHz)的变体思路

    • 我曾考虑过寻找能覆盖900MHz的通用射频芯片,如某些Sub-GHz收发器,但其调制解调方式通常针对特定通信协议(如FSK),不适合接收模拟FM广播和复杂的GSM信号。

我的最终选择:折中与融合方案经过权衡,我决定采用一种“FM专用芯片 + GSM下行变频”的混合架构。这是平衡性能、难度和成本后的选择:

  • FM接收:采用SI4735。理由是其性能有保障,数字I2S输出可直接接入ESP32-S3,且其驱动库(如SI4735.h)非常成熟,能快速实现FM收音功能,包括RDS信息接收。
  • GSM接收:采用一个900MHz宽带下行变频器模块。这类模块通常由混频器、本振(LO)和滤波器构成,能将935-960MHz的信号下变频到一个较低的中频(IF),例如21.4MHz或更低。然后,这个中频信号再送入一个ADC芯片(如高速的ADS1015或专用音频ADC),由ESP32-S3通过I2C读取采样值,进行后续的软件处理。

这样,ESP32-S3的任务就很清晰了:通过I2C控制SI4735收听FM;同时,通过I2C或SPI读取来自GSM通道ADC的数据,在内部进行数字下变频(DDC)、滤波和解调分析。虽然无法解码GSM话音,但可以计算信号功率、绘制频谱图,实现“信号监测”的功能。

2.3 外围器件与结构设计

  1. 显示单元:一块1.3寸或1.54寸的IPS LCD(ST7789或ILI9341驱动),SPI接口。用于显示电台频率、信号强度、频谱瀑布图、时间等信息。
  2. 输入单元:一个旋转编码器(带按键),用于调节频率、音量、切换模式。这是桌面设备的灵魂,手感比按键好太多。
  3. 音频输出:SI4735的I2S输出直接连接到一颗小功率D类音频放大器(如PAM8403),驱动一个4Ω 3W的内置扬声器。同时保留一个3.5mm耳机接口。
  4. 天线系统:这是难点。FM需要约75Ω的单极天线,GSM需要900MHz的天线。我采用“FM拉杆天线 + GSM贴片天线”双天线设计,通过一个射频开关(或手动开关)进行切换。天线匹配网络需要根据实际PCB布局用矢量网络分析仪(VNA)或通过反复调试来优化,这是保证接收灵敏度的关键。
  5. 电源:采用Type-C接口输入5V,通过高效的DC-DC降压芯片(如MP1584)转换为3.3V为整个系统供电。内置一块小容量锂电池(如603048),实现断电短时间续航和时钟保持。

3. 核心电路设计与射频布局要点

画原理图不难,但让收音机“响”且“灵敏”,PCB布局和射频走线是决定成败的一步。这里分享几个踩过坑才明白的要点。

3.1 电源完整性设计

射频电路对电源噪声极其敏感。我的设计采用三级供电:

  1. 主电源层:5V转3.3V的DC-DC电路,布局在板边,电感下方务必净空,避免干扰。
  2. 数字电源层:使用一颗LDO(如AMS1117-3.3)从3.3V主电源派生一个干净的“模拟3.3V”(AVDD),专门供给SI4735的模拟部分和ADC芯片。
  3. 退耦电容布局:每个芯片的电源引脚附近,必须放置一个0.1uF的陶瓷电容(0402封装)和一个1-10uF的钽电容或陶瓷电容。“附近”指的是电容的过孔要尽可能靠近芯片引脚,形成最短的回流路径。对于SI4735,我在其AVDD和DVDD引脚旁各放置了一组。

3.2 射频走线黄金法则

  1. 阻抗控制:GSM 900MHz信号的波长约33cm,PCB上的走线已经需要视为传输线。我使用在线微带线计算器,基于FR4板材(Er≈4.2),将连接到GSM贴片天线和变频器输入输出的走线设计为50Ω阻抗。线宽大约在0.6mm(对于1.6mm板厚)。
  2. 最短路径:天线连接器到射频芯片/模块的路径必须最短,避免任何不必要的弯折。如果必须转弯,用45°角或圆弧,杜绝90°直角。
  3. 地平面完整性:在射频区域下方,必须保持完整、无分割的地平面。它为射频信号提供可靠的返回路径,并起到屏蔽作用。所有射频器件的接地过孔要多且近。
  4. 隔离与屏蔽:将FM接收部分(SI4735及其外围)和GSM下行变频/ADC部分在物理上尽量分开。如果空间允许,可以用一条接地的“隔离带”将它们隔开。最理想的情况是为GSM变频模块设计一个金属屏蔽罩,但在手工制作中很难实现,所以布局隔离就尤为重要。

3.3 天线接口与切换电路

我使用了一个微型射频开关(如SKY13317-373LF)来实现ESP32-S3控制下的天线切换。开关的射频指标(插入损耗、隔离度)在900MHz下要仔细挑选。开关的控制线要远离射频走线。 作为备选方案,也可以使用一个手动拨动开关,让用户在FM和GSM模式间物理切换天线,这样成本更低,且没有开关带来的插入损耗。

实操心得:第一次打样时,我忽略了天线匹配网络。直接连接天线后,GSM信号接收效果极差。第二次,我在GSM天线输入端预留了一个Pi型匹配网络(C-L-C)的焊盘。通过焊接不同值的电容和电感(使用0402封装的射频电感),并用一个简易的场强计观察,最终调试出了最佳的匹配点。没有VNA的情况下,这是一个“土法炼钢”但有效的方法。

4. 固件开发:双模接收与信息显示的实现

软件部分是让硬件“活”起来的关键。整个固件基于ESP-IDF框架,采用FreeRTOS任务来管理不同功能模块,确保UI响应和射频数据处理都不阻塞。

4.1 任务架构设计

我创建了四个主要任务,优先级从高到低:

  1. Radio Control Task:负责处理编码器输入、控制SI4735(FM模式)或设置ADC采样率(GSM模式)。它通过消息队列接收用户输入事件。
  2. Audio/Data Process Task:这是核心数据处理任务。在FM模式下,它接收来自SI4735的I2S音频数据,可进行简单的软件音效处理(如均衡)。在GSM模式下,它从ADC读取I/Q采样数据(虽然我的方案是实信号,但可视为I路),进行FFT计算,得到频谱数据。
  3. Display Task:负责刷新屏幕。它从共享内存或队列中获取当前频率、信号强度(RSSI)、频谱数据数组,并绘制UI。使用LVGL图形库可以大大简化界面开发。
  4. System Monitor Task:低优先级任务,负责监测电池电压、温度、记录日志等后台工作。

4.2 FM接收功能的实现

使用SI4735.h库可以快速上手。关键步骤如下:

#include <SI4735.h> SI4735 radio; void setup_radio() { Wire.begin(I2C_SDA, I2C_SCL); if (!radio.begin(SI473X_ANALOG_AUDIO, 0, 0, SI473X_CRYSTAL_32768)) { // 初始化失败处理 } radio.setVolume(45); radio.setFM(8700, 10800, 10300, 10); // 从87.0MHz到108.0MHz,初始103.0MHz,步进10kHz radio.setAudioMuteMcuPin(AUDIO_UNMUTE); // 如果硬件连接了静音控制 }

通过编码器调整频率,并读取RSSI和SNR(信噪比)来显示信号质量:

int rssi = radio.getCurrentRSSI(); int snr = radio.getCurrentSNR();

注意事项:SI4735的I2S输出需要正确配置ESP32-S3的I2S外设。要确保I2S的时钟(BCK、WS)与SI4735输出的格式(I2S标准、左对齐等)和采样率(通常32kHz或48kHz)匹配。配置错误会导致无声或杂音。

4.3 GSM信号监测功能的实现

这是项目的难点,因为我们需要用软件处理射频采样数据。

  1. ADC采样:我选择了一颗支持连续转换模式的16位ADC(如ADS1115),通过I2C以最高采样率(约860 SPS)读取数据。虽然速率远低于GSM信号的2.17MHz符号率,但我们的目标不是解码,而是观察信号能量。采样率只需满足奈奎斯特定理对中频(IF)信号的要求。如果我的中频是1MHz,那么采样率至少需要2MSPS,这超出了普通ADC的能力。因此,实际中我将GSM信号下变频到了一个更低的频率,例如100kHz,这样几百kSPS的采样率就可以满足。
  2. 数字下变频(DDC)与FFT
    • 假设ADC以Fs的速率采样到一个实信号s[n],其中包含我们感兴趣的中频F_if
    • 在ESP32-S3中,我们通过软件生成一个本地振荡器数字序列:cos[n] = cos(2*pi*F_if/Fs * n)sin[n] = sin(2*pi*F_if/Fs * n)
    • 进行混频:I[n] = s[n] * cos[n],Q[n] = s[n] * sin[n]。这会产生高频和低频分量。
    • 使用低通滤波器(如FIR滤波器)滤除高频分量,得到基带的I、Q信号(在我们的应用里,更关注能量)。
    • 计算瞬时功率:P[n] = I[n]^2 + Q[n]^2
    • 为了显示频谱,可以对s[n]直接进行FFT运算。ESP32-S3有优化的数学库,可以计算256点或512点的FFT,实时显示频谱是可行的。
  3. 数据显示:将计算出的功率值(dBm)或FFT频谱数组发送给显示任务。频谱可以用柱状图或瀑布图的形式显示在屏幕上,直观地看到GSM信道上的信号活动。

实操心得:在ESP32-S3上做FFT,浮点运算速度是瓶颈。我最初使用arduinoFFT库,刷新率很低。后来切换到ESP-DSP库中的dsps_fft2r_fc32函数,并启用ESP32-S3的硬件浮点单元,同时将FFT点数从512降到256,才实现了较为流畅的频谱刷新(约10fps)。记住,在嵌入式系统里,优化算法和合理降级指标是常态

4.4 用户界面与交互

使用LVGL库创建界面。主界面分为两个区域:

  • 上半部信息区:大字体显示当前模式(FM/GSM)、频率/信道、信号强度条、电池图标。
  • 下半部动态区
    • FM模式:显示电台名称(RDS)、音量条。
    • GSM模式:显示实时频谱柱状图,以及一个可移动的游标,指示当前中心频率,并显示该频点的瞬时功率值。 通过短按编码器切换FM/GSM模式,长按进入菜单(设置亮度、扫描、存储电台等)。

5. 组装、调试与性能优化

当PCB焊接完毕,固件编译下载后,真正的挑战才刚刚开始。

5.1 上电与基础调试

  1. 电源检查:首先,不插主要芯片,上电测量所有电源点的电压是否准确(3.3V, 1.8V等)。确保无短路。
  2. 核心通信:焊接ESP32-S3和SI4735后,通过串口查看日志,确认I2C总线能正确扫描到SI4735的地址(通常0x11或0x63)。
  3. 音频通路:先不接天线,在FM模式下,让SI4735输出一个固定的测试音(有些芯片支持)。用耳机监听音频输出,确认从I2S到功放再到喇叭的整个通路是正常的。

5.2 射频接收调试

这是最需要耐心的一步。

  1. FM接收调试

    • 接上拉杆天线,搜索本地强信号电台。如果收不到,检查SI4735的晶振是否起振(可用示波器测),天线焊点是否虚焊。
    • 调整SI4735的setFM参数,特别是deemphasis(去加重,中国用50us)和seekThreshold(搜索阈值)。
    • 常见问题:只有噪音无台。大概率是天线匹配问题或SI4735的参考时钟不准。可以尝试在SI4735的ANT引脚串联一个小的可调电容(如1-10pF)到天线,微调一下。
  2. GSM接收调试

    • 这一步需要信号源。如果没有专业信号发生器,可以找一部旧的2G手机作为信号源。
    • 将GSM手机靠近天线,拨打一个电话(或让其不断搜索网络)。在频谱显示界面上,你应该能看到在935-960MHz范围内有突起的“尖峰”,这些就是GSM载波。
    • 如果看不到信号,首先检查下行变频器模块是否工作(供电、本振信号)。用示波器测量其中频输出端口,在手机活动时应该能看到波形幅度的变化。
    • 调整ADC的采样率和软件中DDC的本振频率F_if,确保目标信号被“搬移”到基带并被正确捕获。

5.3 性能优化与稳定性提升

  1. 降低噪声:如果背景噪音大,检查电源地线是否干净。可以在模拟电源入口增加磁珠。确保射频部分的地平面完整。
  2. 提高灵敏度:优化天线匹配网络。对于FM,拉杆天线的长度理论上应为波长的1/4(约75cm),但桌面设备不可能这么长。可以尝试在天线根部加绕一个磁环作为加感线圈,提升电长度。
  3. 软件抗干扰:在读取ADC数据时,采用均值滤波或中值滤波,消除突发干扰。对于频谱显示,可以加入多次平均,让图像更稳定。
  4. 功耗管理:在待机时,通过代码关闭屏幕背光、将ESP32-S3进入Light-sleep模式、关闭射频前端供电,可以大幅降低整机功耗,延长电池续航。

6. 常见问题与排查实录

在制作过程中,我遇到了各种各样的问题,这里记录下最典型的几个及其解决方法。

问题现象可能原因排查步骤与解决方案
ESP32-S3无法烧录程序1. 接线错误(RX/TX反接)。
2. 开发板未进入下载模式(GPIO0下拉)。
3. 串口驱动问题或端口被占用。
1. 确认USB转串口模块的TX接ESP32的RX(GPIO44),RX接TX(GPIO43)。
2. 按住BOOT键不放,再按一下RST键,然后松开RST,再松开BOOT,进入下载模式。
3. 更换USB口,重启IDE,检查设备管理器中的端口号。
I2C扫描不到SI47351. I2C上拉电阻未接或阻值过大(通常用4.7kΩ)。
2. 电源电压不对。
3. 芯片损坏或焊接不良。
1. 用万用表测量SDA/SCL线电压,上电时应为3.3V,按下拉时应有变化。
2. 测量SI4735的VDD引脚电压是否为3.3V。
3. 重新焊接芯片,或用热风枪补焊。
FM能搜台但声音断续或杂音大1. 信号弱。
2. 天线接触不良或匹配不佳。
3. I2S时钟配置错误。
4. 音频功放自激。
1. 尝试在室外或窗口接收。
2. 检查天线连接器,微调天线匹配电容。
3. 核对ESP32-S3 I2S配置与SI4735输出格式是否完全匹配。
4. 在功放输入输出端并联小电容(如100pF)到地,或检查电源滤波。
GSM模式频谱无反应1. 下行变频器未工作。
2. ADC采样率或配置错误。
3. 软件中频(F_if)设置错误。
4. 天线未切换到GSM通路。
1. 测量变频器供电电压,用示波器探头(需注意阻抗匹配)探测本振和中频输出端是否有信号。
2. 用函数发生器产生一个已知频率的正弦波输入ADC,测试软件是否能正确采集并显示峰值。
3. 根据实际变频器的本振频率和中频输出,精确计算并设置软件中的F_if。
4. 检查射频开关控制逻辑或手动开关位置。
屏幕显示闪烁或花屏1. SPI时钟速率过高。
2. 电源带载能力不足。
3. 屏幕与主板连接线接触不良(特别是FPC排线)。
4. 内存不足,显示缓冲区溢出。
1. 在LVGL初始化代码中降低SPI时钟频率(如从40MHz降到20MHz)。
2. 测量屏幕背光开启时,3.3V电源的电压是否被拉低。
3. 按压排线接口,或重新插拔。
4. 优化图形缓冲区,减少同时刷新的区域,使用LVGL的内存监控工具。
整机工作时发热严重1. 音频功放静态电流大或效率低。
2. 射频芯片或LDO未进入低功耗模式。
3. 存在短路或轻微短路。
1. 更换为效率更高的D类功放,或在无音频输出时使能功放的关断引脚。
2. 在待机代码中,确认SI4735等芯片进入了睡眠模式。
3. 用热成像仪或手触摸查找发热源,重点检查电源芯片和功率器件。

最后的建议:射频项目调试,仪器很重要。即使没有频谱仪和矢量网络分析仪,一个普通的示波器、一个万用表和一个能发射简单信号的发生器(甚至可以用另一个ESP32配合DDS库来产生)也能解决大部分问题。关键在于系统地、分模块地验证,从电源到数字通信,再到模拟信号链,一步一步缩小问题范围。每一次成功的调试,都是对电磁波世界多一分理解。这台GSM-FM桌面收音机,最终摆在桌上,不仅是一个能响的设备,更是这段探索旅程的实体见证。