1. 先说清楚:这个项目到底在做什么
如果你在电子这个圈子里混过一阵子,手里没有一台示波器基本是寸步难行的。但正经品牌示波器便宜也要一两千,对学生党或者刚入行的硬件工程师来说,下手确实肉疼。于是“用FPGA自己做一台便携示波器”这个念头,几乎成了不少人入坑FPGA之后的第一个执念。
我最早是冲着AD9288这颗芯片去的。它是一颗双通道、8位、最高100MSPS采样率的ADC,在二手市场或者立创商城上价格都不算贵,而且外围电路非常简单。搭配一块中等规模的低成本FPGA,比如Xilinx Spartan-6、Artix-7或者Intel Cyclone IV,再加一块几寸的TFT屏,就能拼出一台能看波形、能测频率、能触发、能暂停的实用小仪器。
这篇文章就是把我从立项、画板、写逻辑、调波形到最终把这台“口袋示波器”装进3D打印外壳的全过程整理出来。你不是来看PPT的,你是来复现的,所以我会把重点放在“为什么这么设计”和“踩过的坑在哪”,尽量不让废话占篇幅。
适合谁?两类人。第一类是FPGA刚入门、想找个完整项目把时序、跨时钟域、FIFO、状态机、显示驱动全串起来练一遍的人;第二类是手头紧、又想要一台能随身带的基础示波器的人。如果你两个条件都占,那这个项目基本就是为你准备的。
2. 破局点:为什么是AD9288而不是其他ADC方案
2.1 选AD9288的硬逻辑
很多人在ADC选型时第一反应是ADS830、TVL5510或者树莓派上常用的MCP3008、ADS1115。但放在示波器这个场景里,这些芯片都有一个绕不开的短板,要么速度不够,要么接口太占FPGA引脚,要么就是单端输入没法直接做差分信号处理。
AD9288的优势很明确,单芯片集成两个ADC通道,8位垂直分辨率,最高采样率分为40MSPS和100MSPS两个等级,3.3V单电源供电,功耗才几十毫瓦。而且它的输出是8位并行数字信号,对FPGA来说直接给引脚就能采,不像高速ADC动辄上Gbps的LVDS还需要额外做解串逻辑,对新手非常友好。
另外还有一个很实际的原因:AD9288有内置参考电压源,虽然精度不算顶级,但对一台8位示波器来说绰绰有余。你不必专门再搭一个低温漂基准,少一个模块就少一个出问题的点。
2.2 对比方案:为什么不用STM32+ADC或单芯片方案
有人会说,STM32F4内部ADC不是也有几MSPS吗,再加DMA直接打屏,成本更低。这话对了一半。内部ADC的采样率通常只有2~7MSPS,做个音频分析仪勉强够,想看稍微高频一点的信号,比如几兆赫兹的时钟或串行总线波形,直接就糊了。更关键的是内部ADC在时序控制上不够灵活,想要做预触发、多级触发、深存储,逻辑上非常吃力。
还有一类方案是直接用集成模拟前端加ADC和处理器的一体化芯片,比如某些示波器专用的SoC。性能确实强,但这类芯片通常只供给大厂,市面上根本不好买到,价格也不便宜,用起来缺少“自己动手做核心”的感觉。
所以我的结论是:如果目标是低成本、可玩性强、性能靠谱,FPGA+并行ADC就是最合适的组合。FPGA负责采样时钟控制、触发判决、数据缓冲和显示驱动,ADC只负责把模拟信号变成数字,这种分工逻辑清晰,调试起来也容易定位问题。
2.3 指标预设:先定一个小目标
在动手画板之前,我把指标列出来,免得后面越做越跑偏:
- 通道数:2(双通道切换显示)
- 垂直分辨率:8位(256级)
- 最大实时采样率:100MSPS(AD9288-100)
- 模拟带宽:约30MHz(受运放和前端影响)
- 存储深度:FPGA内置BRAM,按4K~16K点做环形缓冲
- 触发方式:上升沿/下降沿触发,支持预触发
- 显示:4.3寸TFT,320×240或800×480均可
这套指标和市面上几百块的玩具示波器基本持平,但因为是DIY,你能完全掌控每一层逻辑,这对学习价值来说是无价的。
3. 模拟前端:信号进来这关最重要
3.1 RF放大器还是高速运放:带宽和驱动能力的权衡
ADC前端只有一句话,让信号在幅值、带宽、阻抗三个方面都满足ADC的输入要求。AD9288的输入是单端或差分信号,满量程通常设为2Vpp左右,但你要测的信号可能是几十毫伏,也可能是十几伏,这个跨度靠ADC自己扛不住,必须加一级或两级模拟处理。
我前期的方案是用一颗低噪声高速运放,典型的比如AD8056、OPA2690或者LMH6629,搭成一个同相放大器电路,增益1倍到10倍可调。这个位置有两个关键点:一是运放的单位增益带宽至少要100MHz以上,否则前面信号一高频就被衰减没了;二是输入阻抗要控制住,探头进来通常是1MΩ并联十几皮法,这个要在输入端处理好。
如果你想让带宽更高,可以换成射频级的方案,比如用BF998双栅MOS管做宽带前端,但调试难度会明显上升,增益稳定性也不好控。对第一版来说,老老实实上宽带运放是性价比最高的选择。
3.2 阻抗匹配和保护电路:别让第一块板就这么没了
输入端一定要加保护。示波器最容易烧的就是前端,静电、过压、反接,任何一个都能让ADC直接报废。我在输入端加了一对背对背的BAT54S二极管,把输入电压钳位在地和VCC之间,同时在信号路径上串了一个100Ω电阻做限流。
电容耦合方面,我留了一个AC/DC耦合切换开关:DC耦合直接全频段通过,AC耦合则串联一个0.1μF电容,把低频直流分量去掉,方便观察有直流偏置的交流小信号。这个功能电路上很简单,但使用频率非常高,建议不要省。
3.3 单端转差分:让ADC进到最佳工作状态
AD9288有两个模拟输入,INA和INB,可以接单端信号,也可以接差分信号。实际测试下来,差分输入对噪声的抑制能力明显更好,尤其是共地带来的地弹干扰,对8位分辨率的影响还是能看到的。所以我给每个通道都加了一级单端转差分电路,用一颗低成本的变压器加运放组合,或者直接用两颗运放搭仪表差分结构。
如果你对模拟电路不够熟,最简单的办法是先直接单端输入,把数字部分跑通了再回头优化前端。毕竟,第一步目标是把波形显示出来,模拟指标的提升可以分步走。
4. FPGA核心逻辑:整套系统的大脑和心脏
4.1 顶层模块怎么切
FPGA内部逻辑按功能拆成五大块:采样时钟管理(MMCM/PLL)、ADC数据采集与通道切换、触发生成与预触发缓冲、FIFO/BRAM波形存储、TFT显示驱动与波形绘制。这五个模块各干各的活,之间用AXI-Stream或者自定义的简单握手协议连接。
顶层连接关系大致是:外部晶振给FPGA一个50MHz或100MHz基准时钟,通过PLL生成100MHz采样时钟;ADC在100MHz时钟驱动下不断输出8位数据;采样数据写入一片环形RAM,同时触发模块持续和预设电平比较,一旦条件满足就停止写入并给出一个“已触发”标志;显示模块从RAM里读出波形数据,绘制到TFT上。
这样设计的好处是每个模块都可以单独仿真、单独测试。我在调试时先把显示模块点亮,让它显示彩条,确认LCD没问题后再把ADC数据灌进去,风险是一步步拆掉的。
4.2 采样时钟与数据同步:最容易翻车的地方
ADC采样时钟是示波器的命根子,它直接决定时基精度。AD9288要求提供采样时钟输入,通常用FPGA的PLL输出。这里有个非常大的坑:ADC输出的数据不是在采样时钟的上升沿都有效,而是在采样时钟上升沿之后的一个固定延迟之后才稳定下来。
所以FPGA采集数据不能直接用采样时钟去打ADC输出,必须做数据和时钟的对齐。我的做法是用PLL产生一个采样时钟,然后通过相移控制,让PLL输出一个延迟后的时钟去采ADC数据总线。具体延迟多少要实测,通过ILA(集成逻辑分析仪)观测高速采样后的数据码型,找到最稳的相位点。
另一个办法是使用DDR模式,即采样时钟上升沿和下降沿都采集数据,这样可以把ADC等效倍频。但AD9288本身是SDR输出,这个方案只适用于后续做插值或者采样率升级时考虑。
4.3 触发逻辑:不是简单比大小那么简单
示波器的触发不只是“电压大于设定值就触发一次”,还涉及触发电平设置、触发边沿选择、触发后再停止采集的时机控制。我用一个可配置阈值的比较器,当输入信号跨过阈值且方向符合设置(上升沿或下降沿)时,产生一个触发脉冲。
触发之后,环形缓冲的写法是关键。我采用的是“连续写、触发后延迟N个时钟再停止”的方式,这样既能抓触发点之后的数据,也能保留触发点之前的数据,这就是预触发功能。预触发深度可以通过一个寄存器控制,比如设置成1K、2K、4K点,这样观察脉冲前沿或者毛刺非常方便。
还有一个不起眼但很重要的小功能,触发释抑(Holdoff)。如果触发信号本身很密集,不设释抑时间会导致波形在屏幕上“乱闪”。我加了一个可编程的计数器,在触发后的一段时钟周期内屏蔽触发信号,这样波形就能稳定显示了。
4.4 波形绘制:从二进制数据到屏幕上的线
显示模块是直接面向用户的部分,它不复杂,但是琐碎。TFT屏上的横坐标对应采样点序号(时间),纵坐标对应ADC数值(电压)。为了让波形看起来很顺滑,我做了两点优化:
第一,数据从8位ADC到屏幕纵向坐标要做一个缩放映射。AD9288的8位数据范围是0~255,屏幕像素行数如果是240,那直接把每个数据右移一位或者查表映射,就能把波形控制在屏幕中间区域。更专业的做法是做电压刻度线和位置平移,让波形可以上下移动。
第二,连线算法。很多人的波形画出来是断断续续的点而不是连续的线,问题就出在没用Bresenham直线算法做点与点之间的插值。这个算法在FPGA里用纯组合逻辑加简单状态机就能实现,成本很低,但效果提升非常明显。画完波形后,再把网格线、触发电平线、测量的电压/频率数值叠加绘上去,一台示波器的基本界面就出来了。
5. 硬件PCB设计:成败藏在细节里
5.1 电源树设计:数字噪声和模拟噪声要分家
这个项目里,FPGA的IO翻转会产生大量的高频噪声,如果这些噪声串到ADC的模拟电源和参考电压上,你会看到波形上出现“莫名其妙”的细刺。解决的办法很简单但也容易被忽略:模拟电源和数字电源要完全分离开。
我用了两级LDO方案,5V输入,第一级输出3.3V给FPGA、TFT等数字电路,第二级单独用一颗低噪声LDO(如LT1963A或TPS7A4700)输出3.3V给AD9288和其他模拟电路。两个3.3V之间的地,用0Ω电阻或者磁珠单点连接。ADC的参考电压引脚,我额外用了一个10μF钽电容加0.1μF陶瓷电容并联去耦,位置尽可能贴近芯片。
FPGA的电源去耦也不能偷懒,每个电源引脚附近都要有一个0.1μF的陶瓷电容。这看似是基本功,但很多时候波形噪底压不下去,检查出来的原因就是几个BGA封装的电容离引脚太远。
5.2 布局布线:ADC周边一寸都不能乱
AD9288周边的布线规则是:模拟输入走线尽量短而宽,采样时钟线尽量远离模拟输入线;数据总线走线长度尽量等长,避免高速数字信号在FPGA采样的建立/保持窗口内跳动。
如果条件允许,给ADC做一片独立的小板,再用排针和FPGA主板连接,这样调试时如果前端坏了,直接换小板就行,不用拆整个系统。我现在这台样机就是主板和采集板分离的,后续升级前端也方便。
还有一个细节:TFT屏的排线或者连接器,一定要加一些上拉电阻或者串阻,避免在屏线比较长的时候产生振铃,否则屏幕显示会出现“雪花点”那样的问题,排查起来很浪费时间。
5.3 便携性的实现结构
“便携”两个字落实到机械结构上,就是要小巧、低功耗、好供电。整机我做了四层板的方案,电源层和底层完整铺地,顶层走模拟信号,中间层走数字信号。四层板的成本比两层板贵不少,但对高速ADC数据总线和LCD排线来说,完整的地平面真的能省掉很多麻烦。
电池供电方面,我直接用一块3.7V锂聚合物电池,加一颗升压到5V的DC-DC,然后再进两级LDO。这里注意DC-DC的开关频率噪声比较高,布局时一定要把DC-DC部分和其他模拟部分拉开距离,甚至在电源板和中控板之间用屏蔽罩隔一下,效果更好。
外壳我用3D打印做了一个带支架的盒子,侧面开口正好露出USB供电口和BNC探头接口。整机厚度大概不到3厘米,重量300克左右,随身塞进工具包里没有任何压力。
6. 调试实录:那些让我差点砸板子的问题
6.1 波形乱跳?先查时钟和数据对齐
我第一次上电时,屏幕上显示的是一堆雪花一样的乱码点,完全没有波形形状。这个现象几乎可以断定是ADC数据和采样时钟没有对齐,FPGA在ADC输出还没稳定的时候就去采了,采到的是一堆无效数据。
我用ILA抓了ADC数据总线,看到总线上的值确实在乱跳。然后我把PLL的时钟相移一步步调,每调一个档位就抓一次数据,最后找到那个所有位都稳定的相位区间。整个过程不到半小时,但如果你不知道“并行ADC需要时钟对齐”这个坑,可能得折腾好几天。
给后来者一个建议:画板子时最好在ADC数据总线上多引出几个测试点,或者直接用FPGA的内部逻辑分析仪,不要等焊好了再到处飞线测试。
6.2 波形幅值不对?不一定是你逻辑错了
后来波形显示出来了,但幅值比预想的偏小很多,正弦波2Vpp输入,显示出来只有1Vpp。我先怀疑是模拟前端增益不够,用万用表量运放输出,发现运放输出是对的,问题出在ADC的参考电压上。
查了一遍发现,AD9288内部参考电压输出引脚的滤波电容我焊反了极性,钽电容正负接反直接导致参考电压被拉低,ADC量程变小,波形自然就压缩了。换掉电容后,波形幅值马上恢复正常。这类问题最折磨人,因为逻辑和固件都没问题,纯粹是硬件上的一个低级失误。
6.3 屏幕闪烁和触发抖动
触发抖动多半是触发电平和迟滞不够。如果比较器没有加入回差(迟滞),信号电平在阈值附近微小的噪声就会反复触发。我在比较器后面加了一个可编程的迟滞窗口,比如设定阈值上下各留10mV的区间,低于下沿不触发,高于上沿才触发,这样波形就稳定多了。
屏幕闪烁还有一个常见原因是TFT刷新的帧率和波形采集率不匹配。我做了双缓冲,先把波形画到一块SRAM里,画完一整帧再一次性拷贝到LCD上,彻底解决了撕裂和闪烁的问题。这个优化很值得做,代码量增加不到100行,体验提升非常明显。
6.4 常见问题速查表
| 问题现象 | 根本原因 | 解决办法 |
|---|---|---|
| 波形全是乱码点 | ADC数据与采样时钟未对齐 | 调整PLL相位,用ILA找稳定采样点 |
| 波形幅值整体偏小/偏大 | ADC参考电压异常或前端增益不对 | 用万用表/示波器测参考电压、运放输出 |
| 屏幕上波形断层不连续 | 采样数据写入和读取存在冲突 | 检查FIFO读写使能时序,确认不丢数据 |
| 波形抖动无法稳定显示 | 触发无迟滞或释抑时间不够 | 增加比较器迟滞窗口,设置触发释抑计数器 |
| TFT闪烁或撕裂 | 直接写屏与采集并发 | 改为双缓冲,整帧拷贝后再刷新TFT |
| 直流偏置挡位不准 | AC/DC耦合电容漏流不一致 | 选用高质量薄膜电容,校准软件增益系数 |
7. 写在后面:这个项目的价值飞跃点
费了这么大劲做一台指标不算顶级的示波器,很多人可能会问:直接买一台不香吗?我的回答是,整个项目里你学到的东西,远不止一台示波器本身。
你在画模拟前端时,理解了阻抗匹配、带宽和噪声的纠缠关系;你在调采样时钟对准时,真正吃透了并行ADC的时序约束;你在写触发状态机时,体会了什么叫“时序控制是示波器灵魂”;你在调试TFT刷新时,学会了怎么用双缓冲解决性能和观感的平衡。这些东西,不是你看几篇技术文章或者跑几个LED流水灯例程就能掌握的。
如果你做完第一版觉得不够过瘾,后续的扩展方向也已经明确,比如把ADC换成ADS4226或者EV10AQ190实现500MSPS以上的采样率,增加以太网或者USB接口把波形数据上传到PC,甚至加上FFT频谱分析功能。硬件上模块化设计的底子已经打好,软件上FPGA的逻辑也可以复用,升级都只是时间问题。
最后再分享一个我自己的小习惯:给整台设备加一个自检模式,开机时把ADC输入端接到内部一个已知电平,通过屏幕显示校准电压值来判断模拟链路是否正常。这个功能用到的资源极少,但它让你在现场排查问题时心里有底,个人认为非常值得加。
现在你可以去画第一版原理图了。别怕参数调不好,别怕板子焊坏了,所有示波器的精妙,都是从一个“能开机”的裸板开始的。