自制简便型2.4G频谱仪:从射频前端到FFT频谱显示实战

发布时间:2026/9/2 4:05:21
自制简便型2.4G频谱仪:从射频前端到FFT频谱显示实战 简介这是一份面向航模玩家与嵌入式开发者的简便型2.4G频谱仪开源资料基于Arduino与CC2500射频芯片实现用于实时监测2.4G频段信号分布、排查遥控干扰并辅助飞行前场地检测。资源共10个文件以ino源码含Scanner主程序与GraphicsTest图形测试、h头文件CC2500寄存器配置、jpg/png实物接线图、md/txt说明文档为主附带gitignore、gitattributes等工程配置整体仅419KB轻量便携。已有350人学习下载。资料中不仅包含Arduino Nano/OLED SSD1306接线参考与HiLetGo Wifi Kit 32引脚图还提供了OLED频谱显示、扫描逻辑等核心源码适合希望深入理解频谱扫描原理或直接动手复刻的爱好者。通过该项目可以掌握2.4G频段扫描、信号强度可视化与干扰源定位的基本思路也能根据自身需求修改频段范围或显示模式用于航模场地排查、无线环境监测等场景。1. 为什么简便型是2.4G频谱仪的合理取舍做射频这行的人上手第一件事就是学会看频谱。但正经的台式频谱仪动辄几万块实验室里排队预约是常态想随时盯着WiFi信道有没有被干扰、蓝牙跳频跳得正不正常根本轮不上。所以不少同行会选择自己动手做一台够用就好的2.4G频谱仪这也是简便型这三个字的由来——不追求实验室级别的动态范围和相位噪声只求能看到2.4G频段里的信号长什么样、占多宽、大致多强。2.4G频段是个很有意思的频段WiFi、蓝牙、ZigBee、无线鼠标、航模遥控器全挤在这83.5MHz带宽里。实际调试无线产品的时候最常遇到的问题就是信号不稳定但又说不清是干扰还是自身问题。这时候手头有一台能看频谱的工具扫一眼就知道哪个信道被占满了比任何软件工具都直观。我做的这台设备就是把看频谱这件事做到了成本和体积上的极致。这台设备解决的核心问题很明确便携、低成本、实时看频谱。它适合几类人——做无线产品调试的嵌入式工程师、搞WiFi覆盖的网络运维人员、以及想入门射频测量的学生。它的能力边界也非常清楚能看到2400MHz到2483.5MHz整个频段的信号分布、粗略功率大小、信号占用带宽但测不了精确的频率误差也测不了调制质量。这些指标留给实验室仪器去干日常排查干扰和验证无线环境它完全够用。设备的核心架构并不复杂天线接收2.4G信号经过低噪声放大和下变频送到ADC采样再交给MCU做FFT运算最后把频谱画在SPI接口的TFT屏幕上。整机功耗控制在150mA左右用一节18650电池就能连续工作五六个小时揣在口袋里随时能用。2. 核心器件选型从天线灵敏度到ADC采样率的通盘考虑2.1 射频前端的架构选择做2.4G频谱仪第一个绕不开的问题就是射频前端怎么搭。市面上有很多方案从最简单的二极管检波器到大名鼎鼎的RTL-SDR电视棒方案都有。我对比了三条技术路线各有取舍。最省事的是RTL-SDR方案几十块钱的USB电视棒核心芯片是RTL2832U加R820T2直接覆盖25MHz到1.7GHz改改驱动就能当频谱仪用。但它有两个问题一是体积大拖着USB线不方便二是软件依赖电脑不是独立的仪器。既然是简便型我更倾向于做成一个独立的手持设备。第二种是零中频方案用ADI的AD9361或者国产的SX1255这类射频收发芯片内置混频器和ADC集成度高但芯片本身价格偏高做样机打样成本不划算。第三种就是我自己采用的分立方案——超外差单次变频。用一颗2.4G低噪声放大器LNA加一颗本振源把2.4G信号下变频到低中频再用一颗中频ADC采样。好处是每一级的链路都可以单独调试出问题了好排查而且核心物料成本控制在50块钱以内。2.2 具体芯片怎么挑我选的是这几颗料供参考LNA用的是ATF-54143砷化镓工艺的耗尽型晶体管2.4G频段噪声系数能做到0.5dB以下增益约15dB。这管子是安华高的老型号了市面上还有库存注意买到的是不是翻新件。本振源用SI5351这个时钟芯片可以输出10kHz到160MHz的信号三路独立输出。但SI5351的最高频率不够直接做2.4G本振所以后面要加一个三倍频器。混频器用SA612A这是个经典的双平衡混频器工作频率可以到500MHz关键在于它只需要很低的功耗适合电池供电的设备。ADC用MCP3202或者直接MCU内置的12位ADC采样率1MSPs就够了配合300kHz的中频信号正好满足奈奎斯特采样定理。射频链路设计有个核心原则逐级优化噪声系数和增益分配。整个链路的噪声系数主要取决于第一级LNA所以LNA要选噪声系数低的增益则要均匀分配不能让某一级过载。我的链路设计是天线进来先过LNA增益15dB再进混频器降频到中频300kHz中频放大器再补20dB增益最后进ADC。这样整个链路的增益大约35dB噪声系数优于2dB实际测下来灵敏度在-90dBm左右。注意SA612A的输入引脚比较脆弱焊接时温度不要超过350度而且它周边的电阻电容要尽量靠近引脚放置否则容易自激。我第一次画板子时把匹配网络的电阻放远了结果一上电就在频谱上看到一大片自激信号排查了整整一个晚上。2.3 MCU怎么选MCU的选择直接决定了FFT运算的流畅度和屏幕渲染的帧率。我选的是ESP32理由是它内置了240MHz的双核处理器跑FFT够用而且片上有512KB SRAM能存下比较长的采样序列。ESP32还有一个天然优势它本身就带2.4G WiFi射频前端。有朋友可能会问能不能直接用ESP32的WiFi模块做频谱分析答案是只能看RSSI看不到完整的频谱细节。因为ESP32的WiFi模块内部只实现了信道能量检测给出来的RSSI值是一个信道的整体能量不是频谱分布。不过这个RSSI值倒是可以用来做个粗校准的参考后面我会讲到。MCU跑FFT的方案有两种选择一是直接用ESP32的CPU做浮点FFT二是用ESP32内置的硬件FFT加速器实际上ESP32并无硬FFT这里应改为用ESP32的CPU跑定点FFT我的实践是用ESP32的CPU跑定点FFT256点复杂度不高单次计算在5ms以内加上窗函数计算和屏幕刷新整体帧率能跑到10FPS在视觉上已经非常流畅了。3. 蛇形天线与射频PCB布板最容易被新手低估的两道坎3.1 蛇形天线不是随便绕几圈就行网上搜2.4G蛇形天线PCB布板会看到大量成品模块的拆解图但很少有人讲清楚蛇形天线的设计逻辑。很多新手以为蛇形天线就是在PCB上画几条蛇形线这是个大误区。PCB蛇形天线本质上是个微带天线它的谐振频率由导体的总长度决定理论上等于四分之一波长2.4G频段在FR4板材上的四分之一波长约为31mm考虑板材介电常数4.4后打六折大约在18mm左右蛇形只是为了在有限的空间里把这个长度折叠起来。但折叠不是简单的蛇形绕线有几个关键点必须注意蛇形走线的拐角要做45度斜切不能是直角直角会导致阻抗突变辐射效率变差蛇形走线线与线之间的间距至少要保持线宽的3倍否则相邻线段之间会形成耦合电容等效于缩短了天线的谐振长度导致中心频率偏高蛇形天线的周围要留净空区也就是铺铜要挖掉净空距离至少3mm让天线有空间辐射。这一点最容易被忽略——很多人在天线旁边铺了一圈地结果天线辐射效率掉了一半。我的天线设计参数是这样的走线宽度1.2mm对应50欧姆特性阻抗在1.6mm厚FR4板材上蛇形段共11个折返总长度16.8mm末端留一个2mm宽的辐射贴片输入端的匹配网络预留一个π型网络的位置。这样设计出来的天线在2.45G附近实测驻波比在1.5以下基本够用。3.2 射频走线的地过孔与黄金参考层PCB布板是整个项目里最容易翻车的环节。2.4G频段的波长只有12.5cm板子上任何一段走线只要长度超过波长的十分之一就必须当成传输线来设计。我的经验总结成几条硬性规则写在这里供参考第一射频走线必须做50欧姆阻抗控制。在1.6mm厚的FR4板材上微带线50欧姆的线宽大约是2.9mm但板上空间有限我改用了共面波导结构在走线两侧各留0.5mm间隙的接地铜皮这样线宽可以压到1.2mm。走线要尽量短而直避免过孔因为过孔会引入寄生的电感和电容对50欧姆特性阻抗是很大的破坏。第二地过孔的布置要密。射频板的地回流路径是最容易被忽略的。我的做法是沿着板边每1.5mm打一个过孔形成一圈地栅栏把整个射频区域围起来。同时在微带线的两侧打一排平行的地过孔相当于用金属过孔做成了一条屏蔽墙防止信号泄漏到板子其他区域。第三射频走线周围三倍线宽以内不要走其他信号线。特别是不要走SPI数据线和高频数字线否则数字信号的谐波会耦合进射频链路在频谱上表现为一堆毛刺。3.3 电源噪声是隐性杀手这个坑我踩得很深。第一版板子做好之后接USB供电频谱上总会出现一个固定的尖峰一开始以为是环境里的干扰源后来把USB拔了换电池供电尖峰立刻消失了。一查原因USB的5V电源经过AMS1117稳压到3.3V但这个LDO在100kHz以上的电源纹波抑制比只有40dB左右USB电源上的噪声直接耦合进了射频链路。解决方案是在LDO输出端加一级LC滤波电感用1uH的陶瓷电感电容用10uF和100nF并联。同时把模拟地和数字地在ADC的接地引脚处单点连接避免数字噪声通过地回流串进射频链路。整改之后底噪电平明显干净了尖峰消失。经验之谈射频电路里电源和地的处理优先级永远高于信号走线。信号走线影响的是性能上限电源和地影响的是能不能正常工作。4. 固件实现从ADC采样到屏幕渲染的完整链路4.1 采样策略与FFT参数匹配频谱仪的固件核心是采样和FFT。首先要明确一个概念分辨率带宽RBW它决定了能分辨出的最小频率间隔。RBW 采样率 / FFT点数。我的系统里ADC采样率是1MSPsFFT做256点那么RBW就是1MHz/256 3.9kHz。这个分辨率对于看WiFi信道信道带宽20MHz来说绰绰有余蓝牙的信道带宽1MHz也看得出来。但要注意ADC采样的是300kHz的中频信号不是直接采2.4G射频。所以FFT的结果需要做一个频谱搬移实际频率 射频中心频率 - 中频 FFT频率。我的射频中心频率是2442MHz覆盖2.4G到2.4835G需要41.5MHz的扫描范围分成10个频段段每段5M带宽扫描然后拼接。这里我遇到一个设计修正原本计划一次采样覆盖全段但SI5351的本振精度和工作范围限制只能分段扫描再拼接。具体流程是MCU设置SI5351的本振频率经过三倍频器之后送到混频器ADC开始采样256个点做FFT映射到屏幕上然后切换本振频率到下一个频段继续采样。10个频段扫完一遍屏幕正好画满整个2.4G频谱。每段扫描时间约50ms整个周期约0.5s刷新率2FPS实际观看体验还可以接受。4.2 窗函数不要小看频域泄露FFT处理里最容易犯的错误是直接对截断的信号做FFT不做加窗——这样频域会出现严重的频谱泄露导致明明是一个单频信号频谱上却拖出很长的尾巴把旁边的信号都盖住了。解决办法是加窗函数。我的选择是汉宁窗它是通用性最好的窗函数主瓣宽度适中旁瓣衰减够用而且对扫频观察友好。汉宁窗的公式是 w(n) 0.5 * (1 - cos(2πn/(N-1)))。在MCU上实现很简单预先算好256个窗系数存成查表采样的时候对每个点乘上窗系数再做FFT。实际测试下来加了汉宁窗之后WiFi信号的频谱轮廓清晰多了旁瓣从-13dB压到了-31dB。4.3 屏幕渲染让64色TFT画出像样的频谱我用的屏幕是1.8寸ST7735驱动的TFT屏分辨率128x160色深64K色。屏幕本身不算惊艳但好在ST7735的驱动代码非常成熟ESP32有现成的库改改引脚就能用。屏幕渲染的核心是把128个频率点映射到128列像素上。每一列代表约0.65MHz的频率宽度83.5MHz / 128这个分辨率下WiFi的20MHz带宽能看到明显的拱形包络。关键实现细节用光谱图模式每一行像素代表一次扫描的频谱颜色映射从蓝色低能量到红色高能量这样可以看到信号随时间的变化趋势。这对观察蓝牙跳频特别有用——能直观看到跳频点在不同信道间跳动的轨迹。峰值保持功能把当前扫描结果和历史最大值做比较屏幕上显示一条最大值保持线方便看信号的最大占位。触屏交互不是必须的但加了一个按键切换通道中心频率的功能方便聚焦到某个WiFi信道上细看。4.4 关键代码示例下面这段是核心的FFT和频谱映射代码ESP32 ESP-IDF环境下开发关键逻辑都注释了void spectrum_task(void *arg) { float adc_samples[FFT_SIZE]; float windowed[FFT_SIZE]; float magnitude[FFT_SIZE / 2]; // 汉宁窗系数预计算 float window_coeffs[FFT_SIZE]; for (int i 0; i FFT_SIZE; i) { window_coeffs[i] 0.5f * (1.0f - cosf(2.0f * M_PI * i / (FFT_SIZE - 1))); } while (1) { for (int band 0; band NUM_BANDS; band) { // 设置本振频率 set_lo_freq(band_start_freq[band]); vTaskDelay(pdMS_TO_TICKS(20)); // 等待本振稳定 // 采集ADC样本 for (int i 0; i FFT_SIZE; i) { adc_samples[i] adc1_get_raw(ADC1_CHANNEL_3); adc_samples[i] - 2048.0f; // 去除直流偏置 } // 加窗 for (int i 0; i FFT_SIZE; i) { windowed[i] adc_samples[i] * window_coeffs[i]; } // 做FFT do_fft(windowed, magnitude, FFT_SIZE); // 频谱搬移、映射到屏幕 render_spectrum(band, magnitude); } // 刷新屏幕 tft_swap_buffers(); // 更新峰值保持线 update_peak_hold(); } }代码里的注释只是骨架实际项目还要加上状态机处理按键事件、电池电压检测、本振频率切换时的静音处理等。但核心的FFT和频谱映射就是这几行。5. 装配调试与实地测量看到WiFi信道才是真的成功了5.1 检查底噪平台和本振泄漏板子焊好之后第一次上电调试不要急着看频谱先做两个基本的检查第一检查底噪电平。把天线输入端用50欧姆负载短路屏幕上应该是一条平坦的底噪线波动不超过2dB。如果底噪线是倾斜的或者有明显凸起说明链路里有谐振点常见原因是对地电容过大或电感自谐振需要逐级检查匹配网络。第二检查本振泄漏。不接天线把设备放在离频谱仪1米远的地方观察屏幕正中心位置是否有一个固定尖峰。如果有说明本振信号从混频器泄漏到了天线端口。这个尖峰在正常使用时会被天线接收到的信号掩盖一部分但如果尖峰太高高出底噪25dB以上会压缩ADC的动态范围。整改办法是在混频器的RF输入端加一个高通的π型滤波网络把低于本振频率的信号滤掉。5.2 用路由器做定量校准没有专业信号源的时候最方便的校准源就是家里的WiFi路由器。路由器的发射功率一般是15dBm到20dBm但是信号经过墙壁和距离的衰减之后到达频谱仪天线的功率大致在-40dBm到-70dBm之间。我们不需要精确知道具体数值只需要一个相对稳定的参考信号。校准步骤是这样的把频谱仪放在路由器旁边1米位置屏幕上应该能看到一个明显的拱形包络中心在信道12412MHz或信道62437MHz或信道112462MHz取决于路由器配置。如果看到的拱形位置和路由器实际信道对不上说明本振频率有偏差需要校准SI5351的晶振频率。SI5351的频率精度取决于外部晶振偏差可能在几十ppm对应2.4G频段就是几十kHz到上百kHz的偏移。校准方法是测量屏幕上信号峰的位置与预期信道中心频率的偏差然后在固件里做频率偏移补偿。我在固件里预留了一个校准因子变量每次开机读EEPROM更新这个偏移量这样换晶振也不需要重新编译固件。5.3 实测2.4G拥挤环境下的信号画像在地铁站、商场、办公楼这种高密度无线环境下2.4G频段的拥挤程度是超乎想象的。我拿着这台设备去了一趟市中心的写字楼楼道里扫一圈频谱上几乎整个频段都有信号几个拱形叠在一起。仔细辨别的话能看到三四个WiFi路由器的信号叠加蓝牙耳机的跳频点在信道间快速跳动还有微波炉泄漏的宽带信号2.45GHz附近一个宽而平缓的升底噪音。实地测量过程中你很快会意识到2.4G频段为什么这么多人讨厌它各种非WiFi设备的干扰信号让哪怕是最新款的WiFi6路由器也只能在3个非重叠信道之间艰难求生。这台设备的价值就在于让这些平时看不见的频谱战争变得一览无余——你在路由器后台看到的是抽象的RSSI数字在频谱仪上看到的是整个频段被占用的真实画面。5.4 看频谱时的几个经验技巧看WiFi信号不能用峰值保持功能因为WiFi是突发性的峰值保持会把突发瞬间的峰值全部保留下屏幕上一片红反而看不清稳态占用。峰值保持适合观察蓝牙跳频和微波炉这类周期性的干扰源。频段扫描间隔设成0.5秒比较合适太快的扫描看起来拖尾严重太慢又看不到跳频的实时变化。如果你主要是看WiFi占用可以把扫描间隔放宽到1秒帧率低省电屏幕显示也更干净。屏幕亮度对电池续航影响很大。满亮度功耗接近180mA调到50%亮度可以控制在100mA左右。我建议在固件里做一个自动亮度调节根据环境光传感器其实用一个光敏电阻就行来动态调整。6. 这个项目踩过的坑与后续扩展方向6.1 三个印象最深的翻车现场第一是SI5351三倍频后的杂散问题。SI5351的输出谐波非常丰富三倍频之后会在本振频率附近产生大量的间谐波如果不加滤波器这些杂散直接混进中频频谱上就会在信号旁边出现一排等间隔的鬼影。我的解决办法是在三倍频器输出端加一级介质滤波器型号是DFC21R45P100BJA专门针对2.4G频段选频。第二是锂电池在低电量时的底噪上升。18650电池降到3.5V以下时稳压器压差不足输出纹波开始变大频谱底噪会整体抬高3~5dB。这个问题最后是用一个高压差的LDO解决加上欠压保护电路电压低于3.3V直接关机。第三是TFT屏幕的数据线干扰射频链路。最初SPI数据线从射频区域穿过结果每次屏幕刷新的时候频谱上就出现对应的干扰毛刺。后来把数据线全部改到板子背面走线并加宽信号线和地之间的距离反面用了完整的接地平面才算把这个问题压下去。6.2 可以继续深挖的方向这台简便型频谱仪做出来之后我陆续收到了不少朋友的反馈有人问能不能加个跟踪信号源有人问能不能把扫描速度做得更快。我的判断是这两个方向各有难度加跟踪信号源需要增加一个VCO模块和功率检测电路相当于把频谱仪升级成标量网络分析仪用来测滤波器频率响应和天线驻波比。这个功能对做天线调试的同学来说非常实用代价是体积和功耗都有明显增加而且PCB面积要重新规划。提扫描速度主要受限于两处本振切换的稳定时间和FFT计算时间。本振稳定时间由SI5351的PLL锁定时间决定很难优化但可以把FFT从CPU计算改为用ESP32的BLE射频硬件加速实际上这是不可能的更好的办法是换用带硬件FFT的芯片比如STM32F4系列它内置的FPU和DSP指令可以让FFT提速数倍。或者干脆改用双通道采集方式同时采I/Q两路信号再合成FFT这样分辨率带宽不变但可以大幅减少扫描时间。我个人更倾向于给设备加一个USB接口把十段扫描的频谱数据直接以CSV格式导出到电脑配合Python的matplotlib库画更细腻的频谱瀑布图。这样等于把它变成了一台便携数据采集前端后端的分析可以交给电脑。这个方案我已经在第二版固件里实现了用ESP32的USB-Serial/JTAG控制器做USB通信实测传输1MB的数据不到两秒。6.3 经验浓缩做射频DIY项目的三个关键词如果只让我用三个词来总结这个项目我会说规划、耐心、反复测量。规划的意思是在画PCB之前就要把整条射频链路的增益预算、噪声预算、频率规划全部算清楚而不是先画板再调。耐心是指第一版板子大概率不会一次成功自激、杂散、镜像干扰这些问题一定会出现需要逐级排查用频谱仪观察每一级输出的信号特征。反复测量则是指不要因为看到屏幕上出现了信号就以为大功告成——要测量底噪是否平坦、动态范围是否够用、频率偏移是否在容忍范围内一个指标地逐项验收。射频DIY和数字电路DIY最大的区别就在这里数字电路是逻辑问题仿真通过基本就过了射频电路是模拟问题仿真只是一个起点真正的挑战在板子回来之后。但也正因为如此每次成功调试一套射频板子的成就感也是数字电路难以比拟的。这台简便型2.4G频谱仪应该是我这些年做过的性价比最高、也最值得反复把玩的一个DIY项目了。本文还有配套的精品资源点击获取