尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
ESP32做SDR:二十元开发板实现软件定义无线电接收
1. 从一块二十块钱的开发板说起ESP32做SDR这件事到底靠不靠谱第一次在群里看到有人甩出一句“ESP32能当SDR用了”我的反应和大多数人一样——眩晕瘫坐不至于但确实愣了几秒。ESP32这块芯片玩嵌入式的人太熟了二十来块钱一片双核240MHz带WiFi和蓝牙平时干的是读传感器、点灯、驱动屏幕、跑个小车的活儿。SDR是什么软件定义无线电传统印象里那是需要高速ADC、FPGA、动辄几百兆采样率的东西跟一个主打低功耗物联网的MCU怎么看都不像能扯上关系。但仔细扒了一圈资料、翻了几个开源项目之后我发现这事没那么玄乎也没那么简单。说它“能当SDR”准确的理解应该是ESP32可以在极其有限的条件下实现特定频段、特定带宽的无线电信号接收与简单解调而不是替代一台RTL-SDR或者Airspy。这个区别非常关键直接决定了你对这个项目的预期也决定了你会不会花了两天时间最后骂骂咧咧地放弃。这篇文章适合几类人看手里有ESP32开发板、对无线电感兴趣但没接触过SDR的嵌入式玩家玩过RTL-SDR、想看看MCU能做到什么程度的无线电爱好者以及单纯好奇“这玩意儿到底怎么实现的”的技术围观群众。我会从原理层面讲清楚为什么ESP32能做这件事、它的物理极限在哪里然后给出可复现的实操路径最后把我踩过的坑和排查经验整理出来。不管你是刚点亮第一块ESP32的新手还是已经用ESP-IDF写过不少项目的老手应该都能从中找到有用的东西。2. 核心原理拆解ESP32凭什么能碰SDR的边2.1 先搞清楚SDR到底在干什么要理解ESP32能不能做SDR得先弄明白SDR的本质。传统无线电接收机的信号链路是硬件搭出来的天线收到信号经过滤波、放大、混频、检波最后出来音频或者数据。每一级都是固定的电路想换个频段就得换硬件。SDR的思路是把尽可能多的处理搬到软件里天线信号经过最少的模拟前端通常就是一个宽带放大器加一个高速ADC数字化之后滤波、混频、解调全部用代码算出来。这里面的核心瓶颈是ADC。根据奈奎斯特采样定理你要接收中心频率为f、带宽为B的信号ADC的采样率至少要到2B以上实际中还要考虑过采样和抗混叠。FM广播带宽约200kHz那采样率至少400ksps航空波段AM信号带宽窄一些大概几十ksps就够。所以SDR对ADC的要求取决于你想接收什么信号。RTL-SDR之所以便宜好用是因为它用了R820T2这颗调谐芯片把射频信号先降到中频再用一颗8bit、2.4Msps的ADC采样通过USB把IQ数据送到电脑上处理。关键点在于真正的高速采样和下变频是硬件芯片干的电脑只负责后面的数字信号处理。2.2 ESP32的硬件底子到底够不够ESP32的射频部分本来是为WiFi和蓝牙设计的支持2.4GHz频段内部有射频收发链路。但问题在于这条链路是封闭的你没法直接拿到原始IQ数据。ESP32的ADC是SAR型标称12位实际有效位数大概9到10位采样率理论上最高2Msps但这是在特定条件下的极限值实际用起来受WiFi蓝牙共存、DMA带宽、CPU负载影响很大。那为什么还有人做出来了关键在于思路的转变不去碰2.4GHz的WiFi射频链路而是用ESP32的ADC直接采样外部输入的模拟信号。也就是说你需要外接一个简单的模拟前端——一根天线、一个合适的带通滤波器、可能再加一级LNA——把信号送到ESP32的ADC引脚上。ESP32负责的是采样和后续的数字信号处理射频前端的工作交给了外部电路。这个方案的本质是ESP32充当了一个低速ADC加DSP处理器的角色。它的采样率决定了能处理的信号带宽它的算力决定了能跑多复杂的解调算法。根据社区里几个开源项目的实测数据ESP32在稳定工作的情况下ADC采样率大概能跑到1Msps左右对应理论带宽500kHz。实际上考虑到抗混叠和算法开销能有效处理的带宽大概在100到200kHz之间。2.3 为什么这件事值得折腾你可能会问花这么大劲就为了接收一两百kHz带宽的信号有什么意义直接买个RTL-SDR不好吗这个问题我认真想过。从纯功能角度ESP32做SDR确实打不过任何一款入门级SDR接收机。但它有几个独特的价值点第一它是一个完全独立的嵌入式方案不需要连接电脑可以做成一个巴掌大的独立接收设备配上屏幕和电池就能户外使用第二它的成本极低一块ESP32加上几个分立元件总成本可能不到三十块钱第三也是最重要的一点它是一个极好的学习平台。当你亲手用ADC采样、用代码实现FFT、用算法解调出第一个信号的时候你对SDR的理解会发生质的变化这是插上RTL-SDR点开SDR#软件永远得不到的体验。注意ESP32做SDR接收接收频段取决于你外接的模拟前端。ESP32本身不负责调谐它只是采样。你想接收什么频段就需要对应的前端电路把信号搬移到ADC能处理的范围内。3. 实操前的准备工作硬件选型和软件环境搭建3.1 硬件清单与选型逻辑动手之前先把东西备齐。我列一个最小系统的清单然后解释每一项为什么这么选。组件推荐型号选型理由大致成本主控板ESP32-WROOM-32最通用的型号社区资料多ADC引脚引出方便15-25元天线拉杆天线或自制偶极子根据目标频段裁剪长度短波用长线FM用半波振子5-20元带通滤波器自制LC或成品滤除目标频段外的强信号防止ADC饱和5-15元低噪放可选MMIC如BGA2801弱信号时提升信噪比强信号时不需要3-10元偏置器自制给LNA供电同时隔离射频和直流2-5元显示屏SSD1306 OLED 128x64显示频谱和解调信息I2C接口省引脚8-15元连接线杜邦线、SMA转接线射频连接尽量短减少损耗和干扰若干关于ESP32型号的选择我建议用ESP32-WROOM-32或者ESP32-S3。WROOM-32的好处是资料最全ADC引脚在GPIO32到GPIO39之间其中GPIO34到GPIO39是输入-only适合做ADC输入。S3的话算力更强有向量指令可以加速FFT但价格稍贵资料相对少一些。如果你是第一次做这个项目从WROOM-32开始最稳妥。天线这块要重点说一下。很多人随便拿一根杜邦线就当天线用结果什么信号都收不到然后怀疑是代码问题。天线的长度和形式直接决定了你能否有效接收目标频段的信号。一个简单的计算公式半波振子长度米等于150除以频率MHz。比如你想接收100MHz附近的FM广播半波振子大概1.5米接收短波7MHz那就要20米左右了。实际中受空间限制可以用四分之一波长或者加感线圈来缩短。3.2 软件环境搭建从Arduino IDE到ESP-IDF软件环境这块我推荐两条路线根据你的经验水平来选。如果你之前主要用Arduino IDE开发ESP32那继续用Arduino框架是最快上手的路径。需要安装的东西Arduino IDE 2.x版本、ESP32开发板支持包建议用2.0.11或2.0.14版本稳定性好、以及必要的库。安装ESP32支持包的时候国内网络环境下载可能比较慢可以找离线包手动安装。具体操作是在Arduino IDE的“首选项”里填入开发板管理器地址然后在开发板管理器里搜索esp32安装。如果下载速度实在受不了去社区找对应版本的离线包解压到Arduino的hardware目录下也能用。如果你追求性能和底层控制那就上ESP-IDF。ESP-IDF是乐鑫官方的开发框架对ADC、DMA、I2S的控制更直接做高速采样的时候优势明显。安装ESP-IDF推荐用VSCode加ESP-IDF插件的方式比纯命令行友好很多。安装过程中会下载工具链和Python环境同样可能遇到网络慢的问题可以配置国内镜像源加速。安装完成之后用idf.py create-project创建一个新项目就可以开始了。提示不管用哪个框架都建议先把一个最简单的ADC采样程序跑通用串口打印原始数据确认硬件连接和基础功能没问题再往上叠加SDR相关的代码。这样出问题的时候排查范围小很多。3.3 采样率与时钟配置的关键参数这是整个项目最核心的技术点之一。ESP32的ADC时钟源来自APB时钟默认80MHz通过分频器产生ADC的工作时钟。在Arduino框架下analogRead()函数的采样率大概只有几十ksps远远不够。要跑到1Msps左右必须用底层寄存器操作或者I2S DMA的方式。用I2S DMA采ADC数据是社区里比较成熟的方案。原理是把ADC配置成连续采样模式通过I2S外设的DMA通道把数据搬运到内存缓冲区CPU只需要处理缓冲区里的数据不用管采样时序。这样可以把采样率做到比较高同时CPU还有余力做信号处理。具体的配置参数I2S采样率设置为1MHzDMA缓冲区大小设为1024或2048个采样点双缓冲模式。ADC衰减设为11dB对应输入范围0到3.3V左右分辨率设为12位。实际有效位数大概9到10位所以信噪比不会太好但对于接收较强的广播信号来说够用了。这里有个坑要注意ESP32的ADC在WiFi开启的时候噪声会明显增大。如果你不需要WiFi功能在采样期间把WiFi关掉信噪比会好很多。如果确实需要WiFi尽量把采样和WiFi传输在时间上错开。4. 从采样到解调完整信号链的实现过程4.1 模拟前端电路的设计与搭建ESP32的ADC输入范围是0到3.3V衰减11dB时而且只能接受正电压。射频信号是交流信号有正有负所以需要加一个直流偏置电路把信号抬升到1.65V左右让交流信号在1.65V上下摆动这样ADC才能正确采样。最基本的偏置电路用两个等值电阻分压产生1.65V然后通过一个隔直电容把射频信号耦合进来。但这样做的缺点是输入阻抗不够稳定而且没有滤波。更好的做法是用一个运算放大器搭一个偏置加法电路同时兼做低通抗混叠滤波。运放选带宽足够的型号比如NE5532或者OPA2350增益带宽积至少要到几十MHz。带通滤波器根据你的目标频段来设计。以接收FM广播88到108MHz为例你需要一个中心频率98MHz、带宽20MHz左右的带通滤波器。可以用LC集总参数做但98MHz的频率下电感电容的值很小手工焊接比较困难。更实际的做法是用一个成品FM带通滤波器或者用传输线结构的滤波器。如果目标频段更低比如短波或者中波LC滤波器的实现就容易得多。低噪放这块如果信号比较强比如本地FM广播可以不加。如果信号弱加一级MMIC放大器会有明显改善。注意LNA的增益不要太高否则强信号会让ADC饱和产生严重的互调失真。我一般会加一个可调衰减器或者用PIN二极管做AGC但这就复杂了新手可以先不加根据实际接收效果再决定。4.2 采样数据的预处理去偏置与数字滤波ADC采到的原始数据是0到4095之间的整数对应0到3.3V。信号的中心在1.65V左右对应ADC读数大概2048。第一步预处理就是把直流偏置去掉把数据变成以0为中心的有符号数。这个操作很简单每个采样值减去2048就行。接下来是数字滤波。虽然模拟前端已经有抗混叠滤波但ESP32的ADC采样率是1MHz而实际有用的信号带宽可能只有100kHz所以还需要数字低通滤波来进一步抑制带外噪声。在ESP32上跑FIR滤波是可行的但要注意算力开销。一个64阶的FIR滤波器在240MHz主频下处理1Msps的采样流大概占用不到10%的CPU。如果阶数太高比如256阶那CPU占用就会很明显了。更高效的做法是用CIC滤波器或者简单的滑动平均。滑动平均本质上是一个FIR滤波器系数全为1实现起来只需要加减法不需要乘法速度极快。比如16点滑动平均可以把采样率从1MHz降到62.5kHz同时滤除高频噪声。降采样之后的数据量小了后续FFT和解调的负担也轻了。实操心得预处理阶段的数据类型选择很重要。用float做运算方便但慢用int16_t做定点运算快但要注意溢出。我建议在滤波和降采样阶段用int32_t累加输出用int16_tFFT阶段再转float。这样兼顾速度和精度。4.3 FFT频谱分析与信号识别有了预处理后的IQ数据实际上ESP32做的是实数采样严格来说只有I路没有Q路但可以通过希尔伯特变换或者直接对实数做FFT来获取频谱下一步就是做FFT看频谱。ESP32上跑FFT推荐用乐鑫官方提供的esp-dsp库里面有针对ESP32优化的FFT函数支持实数FFT和复数FFT速度比手写的快很多。FFT的点数选择要权衡频率分辨率和时间分辨率。1024点FFT在62.5kHz采样率下频率分辨率是61Hz时间窗口约16ms。对于看FM广播的频谱来说这个分辨率足够了。2048点的话分辨率翻倍但计算量也翻倍。我一般用1024点在ESP32上跑一次大概几百微秒完全跟得上实时显示。频谱出来之后你可以通过找峰值来确定信号的中心频率。比如在88到108MHz范围内经过下变频后对应到基带的0到20MHz再经过采样和降采样后对应到0到31.25kHz找到幅度最大的几个峰那就是电台信号。然后根据峰值的位置把信号搬移到零频附近做进一步解调。4.4 FM解调的实现细节FM解调的核心是求瞬时频率。对于实数采样信号可以先做希尔伯特变换得到解析信号然后求相邻采样点的相位差相位差就对应瞬时频率。另一种更简单的方法是对信号做反正切鉴频把信号延迟一个采样周期然后计算原信号和延迟信号的叉积与点积叉积除以点积的反正切就是相位差。在ESP32上实现FM解调我推荐用第二种方法因为计算量小不需要做希尔伯特变换。具体步骤是对预处理后的信号x[n]计算x[n]和x[n-1]的叉积cross等于x[n]乘以x[n-1]的共轭的虚部对于实数信号cross等于x[n]乘以x[n-1]的延迟版本这里需要先构造解析信号或者用近似方法点积dot等于x[n]乘以x[n-1]的实部。然后相位差等于atan2(cross, dot)。这个相位差就正比于瞬时频率偏移也就是解调出来的音频信号。解调出来的音频信号还需要经过低通滤波和去加重。去加重是FM广播的标准处理时间常数一般是75微秒美国或50微秒欧洲。去加重的实现就是一个简单的一阶高通滤波器用代码几行就能搞定。最后把音频信号通过DAC输出或者通过I2S送到外部DAC芯片就能听到声音了。ESP32自带两个8位DAC引脚GPIO25和GPIO26可以直接输出音频。但8位分辨率对于音频来说有点低会有明显的量化噪声。更好的方案是用I2S接一个外部DAC比如MAX98357或者PCM5102音质会好很多。如果只是听个响内置DAC也凑合能用。5. 常见问题与排查技巧实录5.1 采样数据全是噪声怎么办这是最常见的问题十有八九是模拟前端的问题。排查步骤按顺序来先用示波器或者万用表确认ADC输入引脚的直流电平是不是在1.65V左右。如果偏差太大检查偏置电路的分压电阻是不是焊错了或者虚焊。然后确认天线有没有接好天线和ADC输入之间的耦合电容是不是合适。如果这些都正常那可能是信号太弱需要加LNA或者换更好的天线。还有一个容易被忽略的点ESP32开发板上的ADC引脚可能被其他功能占用了。比如GPIO34在某些板子上接了摄像头或者SD卡。用之前查一下开发板的原理图确认引脚是空闲的。另外ADC2的引脚在WiFi开启时是不能用的只能用ADC1的引脚GPIO32到GPIO39。5.2 频谱显示有信号但解调不出声音这种情况通常是解调参数不对。首先确认你解调的信号确实是FM信号而不是AM或者数字信号。FM广播的信号带宽大概200kHz在频谱上看起来是一个比较宽的峰而AM信号是一个窄峰。如果确认是FM检查鉴频器的参数延迟采样点数是不是1atan2的计算是不是正确去加重的截止频率是不是设对了。另一个可能的原因是采样率不够。如果ADC实际采样率只有500kHz那能处理的信号带宽只有250kHz对于200kHz带宽的FM信号来说勉强够用但边缘可能会失真。可以试着降低目标信号的带宽要求或者提高采样率。5.3 编译速度慢和烧录失败的处理用Arduino IDE编译ESP32项目尤其是带WiFi和蓝牙库的项目编译时间可能长达几分钟。加快编译速度的方法有几个关闭不需要的库用预编译的库文件升级电脑的CPU和内存这个最直接但成本高或者换用PlatformIO。PlatformIO的编译缓存机制比Arduino IDE好很多第二次编译同样的项目会快很多。烧录失败的话先检查USB线是不是数据线有些线只能充电不能传数据然后确认开发板驱动装好了。ESP32烧录的时候需要进入下载模式有些板子自动下载电路做得不好需要手动按住BOOT键再按RESET键。如果串口一直显示“等待上电同步”大概率是这个问题。问题现象可能原因排查方法解决方案采样全是噪声偏置电压不对万用表测ADC引脚电压调整分压电阻确认在1.65V频谱无信号峰天线未接好检查天线连接和长度重新裁剪天线确保接触良好解调无声音鉴频参数错误检查延迟和atan2计算调整延迟点数验证去加重编译超时库太多查看编译日志移除无用库换PlatformIO烧录失败未进入下载模式观察串口输出手动按住BOOT再复位WiFi开启后噪声大ADC2与WiFi冲突确认使用的ADC通道换用ADC1引脚或关闭WiFi5.4 提升接收效果的几个实用技巧第一个技巧是给ADC输入加一个简单的RC低通滤波器截止频率设在采样率的一半以下。比如采样率1MHzRC截止频率设500kHz。这个滤波器可以滤除高频噪声改善信噪比。电阻选1kΩ电容选300pF左右。第二个技巧是用多个ADC引脚做时间交织采样。ESP32有两个ADC理论上可以交替采样把等效采样率翻倍。但实际中两个ADC之间的一致性不好需要校准实现起来比较复杂。新手不建议尝试。第三个技巧是在FFT之前加窗函数。不加窗的话频谱泄漏会比较严重弱信号可能被强信号的旁瓣淹没。汉宁窗或者汉明窗都是不错的选择计算量也不大。esp-dsp库里有现成的窗函数可以调用。6. 这个项目的边界在哪里理性看待ESP32 SDR的能力折腾了这么久我对ESP32做SDR的能力边界有了比较清晰的认识。它能做的事情接收本地强信号的FM广播、接收航空波段AM信号、接收气象卫星的APT信号需要合适的天线和前端、做简单的频谱监测。它不能做的事情接收弱信号、处理宽带信号、替代专业SDR接收机、做高精度的信号分析。如果你追求的是实用性想稳定接收各种信号那还是买一台RTL-SDR或者更好的接收机。但如果你追求的是学习价值想真正理解SDR的工作原理那ESP32这个平台能给你的东西远超它的价格。当你第一次从自己焊的电路上、从自己写的代码里听到电台主持人的声音时那种成就感是插上成品设备永远体会不到的。最后分享一个我在调试过程中总结的小经验每次修改代码之后先用一个已知的信号源比如信号发生器或者另一个ESP32发射的测试信号验证接收链路是否正常再去接收真实信号。这样可以快速区分是代码问题还是信号问题省去很多瞎猜的时间。另外把关键的中间数据通过串口打印出来比如ADC原始值、滤波后的值、FFT的峰值位置比盯着屏幕上的最终结果瞎调要高效得多。
RELATED

相关推荐

基于2400源表与LabVIEW的自动化I-V测试系统设计与实操指南

基于2400源表与LabVIEW的自动化I-V测试系统设计与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/29 1:08:44
TPS259483AYWPR与TM4C129EKCPDT工业电源闭环防护设计

TPS259483AYWPR与TM4C129EKCPDT工业电源闭环防护设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/29 1:08:44
基于ESP32-S3的实时马赛克拼贴画显示终端设计与实现

基于ESP32-S3的实时马赛克拼贴画显示终端设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/29 1:08:44
MORE NEWS

更多资讯

📰

Linux FFmpeg深度解析之avdevice_list_input_sources调用流程与实战(六)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者 博主新书推荐:《Android系统多媒体进阶实战》🚀 Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀 Android多媒体专栏地址&a…

📰

硬盘数据恢复,这5个妙招汇总操作轻松,效果显著!

在数字信息时代,硬盘如同我们的数据宝库,存储着工作文档、生活照片、珍贵视频等重要内容。然而,意外总是防不胜防,误删除、病毒入侵、硬盘老化等问题,随时可能让数据丢失。当遭遇硬盘数据丢失困境时,掌握有…

📰

【StrongSort 03】多轨迹算法StrongSort改进点

Strongsort改进点 StrongSORT(论文 StrongSORT: Make DeepSORT Great Again)在 DeepSORT 基础上提出的四项在线改进 一项相机运动补偿。本工程全部实现为可开关参数,五项统一默认开启(测试脚本加对应 --no-nsa / --no-ema / --n…

📰

华为云码道本地部署手册

1. 扫描下方二维码或点击超链 👉👉👉 海量tokens等你来领。 勾选服务声明,点「免费开通」,开通华为云码道CodeArts代码智能体。 2. 下载安装码道IDE,体验本地开发与调试。 3. 登录码道IDE,领取积…

📰

Java 后端落地上下文工程:LLM 窗口四元组预算分配器与三级降级的可复现实现

解决什么问题:把一个「越大越容易把自己淹死」的上下文窗口,变成可计量、可分配、可降级、可审计的运行时资源池。 适合谁:已经在跑多步 Agent / 长对话后端,遇到 context_length_exceeded 或响应随步数变慢的 Java 工程师。 能收…

📰

Folia 完整安装部署指南:从零跑通全屏歌词动画

Folia 完整安装部署指南:从零跑通全屏歌词动画 【免费下载链接】folia-major 专注于绚丽的歌词动画效果的本地音乐/navidrome/第三方多平台在线音乐播放器 项目地址: https://gitcode.com/GitHub_Trending/fo/folia-major Folia 全屏歌词动画播放器&#xff…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬