ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AD9268/AD9643高速ADC调试避坑指南:SPI时序、LVDS信号完整性与电源隔离实战

AD9268/AD9643高速ADC调试避坑指南:SPI时序、LVDS信号完整性与电源隔离实战 1. 项目概述这不是一份数据手册复读而是一份用示波器探头和万用表写成的“血泪笔记”AD9268 和 AD9643 这两款高速模数转换器ADC在雷达信号采集、软件无线电SDR、高速数据记录仪这类对采样率、信噪比、通道一致性要求极高的场景里几乎是绕不开的“硬通货”。AD9268 是 16 位、125 MSPS 的双通道 ADCAD9643 则是 14 位、150 MSPS 的单通道 ADC——它们不是那种插上 USB 线就能出波形的消费级芯片而是需要你亲手调电源、掐时序、量差分、抓波形、改寄存器的“硬核器件”。标题里那个“避坑实录”真不是修辞手法。我们团队在一款便携式频谱分析仪的原型机调试中前后花了整整六周才把这两颗芯片从“板子上亮着灯但没数据”调到“稳定输出 12 小时无丢点”。这期间示波器探头换过三副SPI 通信失败的日志文件删了又建LVDS 接收端 FPGA 的 RTL 代码重写了四版。这篇内容就是把那些藏在数据手册第 47 页 footnote 里的隐含条件、那些工程师嘴上说“应该没问题”但实际一上电就翻车的细节、还有那些连 TI/ADI 应用笔记都没明说的“潜规则”一条条摊开来讲。它不教你 SPI 协议怎么定义但会告诉你为什么 STM32F103 的 SPI 在 20MHz 主频下必须关掉 CRC 校验才能和 AD9268 对上它不讲 LVDS 的理论眼图但会手把手教你用万用表测差分线阻抗是否真的落在 100Ω±10% 范围内它不罗列所有寄存器地址但会指出哪三个寄存器一旦配错ADC 就会静默死锁连 RESET 都拉不回来。如果你正拿着一块刚画好的 PCB上面焊着 AD9268 或 AD9643心里还想着“按手册接线应该就能跑”那这篇就是你开机前最该读的“安全须知”。它适合所有角色硬件工程师要确认 layout 是否埋雷FPGA 工程师要核对接收逻辑是否健壮嵌入式工程师要检查驱动是否踩中时序陷阱甚至项目经理也需要知道为什么这个“简单”的 ADC 调试周期比预期多出了整整三周。2. 整体设计思路与方案选型背后的硬逻辑2.1 为什么非得用 SPI 配置JTAG 不香吗看到这里可能有朋友会问ADI 的很多高速 ADC 都支持 JTAG 调试接口为什么还要死磕 SPI答案很现实成本、面积和可靠性。JTAG 需要额外的 TCK/TMS/TDO/TDI 四根信号线还要配套的隔离电路和专用调试器比如 Xilinx 的 Platform Cable USB II。在我们这款便携设备里PCB 板面积被严格限制在 100mm × 80mm 内留给 ADC 周边的布线空间极其紧张。SPI 只需 SCLK、SDIO双向、CS# 三根线且 CS# 可以复用为 GPIO还能通过软件控制多个 ADC 的片选——我们最终的量产版设计里是用一颗 STM32F103C8T6 同时管理两颗 AD9268双通道和一颗 AD9643单通道总共只占用了 5 个 GPIO 引脚。更重要的是JTAG 是一种“在线仿真”协议它依赖于芯片内部的调试逻辑模块而这个模块在某些低功耗模式或异常状态下可能被关闭。SPI 则不同它是 ADC 物理层上最底层的配置总线只要 VDDA/VDDD 供电正常、时钟稳定SPI 就能工作。我们在一次低温测试-20℃中发现JTAG 接口完全失联但 SPI 依然能成功读取芯片 ID 寄存器0x00这成了我们定位低温失效根源的关键突破口。所以选择 SPI 不是妥协而是基于产品形态、成本约束和系统鲁棒性做出的主动决策。2.2 LVDS 输出为何是唯一解CMOS 输出哪里不行AD9268/AD9643 都支持 CMOS 和 LVDS 两种数字输出模式。CMOS 看起来更“友好”单端信号电平是 1.8V 或 3.3VSTM32 直接能接。但问题恰恰出在这里。CMOS 输出是单端的意味着每个数据位都需要一根独立的走线。AD9268 是 16 位并行输出双通道就是 32 根数据线再加上 DCO数据时钟输出、FIFO_READY、OVR溢出标志等控制线整个接口需要超过 40 根信号线。这在高密度 PCB 上几乎无法布线更致命的是这么多单端信号同时翻转会产生巨大的同步开关噪声SSN直接耦合进模拟输入路径让本应干净的 70dB SNR 瞬间跌到 50dB 以下底噪里全是“嗡嗡”的开关毛刺。LVDS 则完全不同。它采用差分对传输每对线上传输的是电流方向相反的信号接收端只关心两根线之间的电压差典型值 ±350mV。这种结构天然具有极强的共模噪声抑制能力。更重要的是LVDS 的功耗与速率几乎无关而 CMOS 的功耗与频率和电容的平方成正比。在 125MSPS 下AD9268 的 LVDS 总功耗约为 450mW而同等条件下 CMOS 模式功耗会飙升到 1.2W 以上这还不算 PCB 上因散热不良导致的温漂问题。我们实测过在 100MHz 采样率下CMOS 输出的频谱底噪比 LVDS 高出整整 12dB这对于一个标称动态范围 90dB 的设备来说是不可接受的降级。因此“必须用 LVDS”不是为了炫技而是为了守住性能底线。2.3 主控平台为何锁定 STM32F103 FPGA纯 MCU 行不行这个问题的答案直接决定了整个系统的架构成败。有人会想既然 SPI 配置都用 STM32F103 了那数据接收也用它不就行了毕竟 F103 有 FSMC灵活静态存储控制器理论上可以接并行总线。但现实是残酷的。AD9268 的 LVDS 数据速率是 125MHz这意味着数据有效窗口data valid window只有 4ns。STM32F103 的 FSMC 最高异步访问时序是 60ns即使强行超频其内部总线仲裁、DMA 请求响应、内存写入延迟等环节加起来根本无法稳定捕获每一个 4ns 宽的数据沿。我们做过极限测试用 FSMC 捕获 AD9268 的 LVDS 数据结果是每 1000 个采样点就丢失 3~5 个且丢失位置完全随机根本无法用于后续的 FFT 分析。FPGA 则是为此类任务而生的。它的 IO 引脚可以精确配置为 LVDS 输入标准内部有专用的 ISERDES串行器/解串器原语能在一个时钟周期内将 7 位或 14 位的串行 LVDS 流解包成并行的宽总线数据。我们选用的 Xilinx Spartan-6 LX9其 LVDS IO 支持高达 1.2Gbps 的速率轻松覆盖 AD9268 的 125MHz × 16bit 2Gbps注意LVDS 是双沿采样实际线速率是 250Mbps/对带宽需求。STM32F103 在这里扮演的是“系统管家”的角色负责上电时序控制、SPI 配置、温度/电压监控、用户交互和数据打包上传FPGA 则是“数据搬运工”专注、高效、零误差地完成高速数据流的接收、缓存和格式转换。这种分工是经过无数次失败后得出的最优解。3. 核心细节解析与实操要点从原理到焊盘的每一处陷阱3.1 SPI 配置别再迷信“标准模式”时序才是生死线ADI 的数据手册里关于 SPI 的描述往往非常简洁“支持标准四线 SPICPOL0, CPHA0”。这句话背后藏着一个巨大的认知陷阱。CPOL0, CPHA0 确实是标准模式但 AD9268/AD9643 对 SCLK 的上升沿和下降沿都有严格的建立setup和保持hold时间要求而这些参数不会出现在主控芯片如 STM32的数据手册里只会藏在 ADC 的“AC Electrical Characteristics”表格中。以 AD9268 为例其关键时序参数如下tDSU(Data Setup Time): 2.5ns SDIO 数据在 SCLK 上升沿前必须稳定tDH(Data Hold Time): 2.0ns SDIO 数据在 SCLK 上升沿后必须保持稳定tCSH(CS# High Time): 10ns 两次 SPI 事务之间CS# 必须至少保持高电平 10ns乍一看这些时间都很短似乎 STM32F103 的 SPI 外设完全能满足。但问题在于STM32F103 的 SPI 在“标准模式”下其内部移位寄存器的更新是在 SCLK 的下降沿进行的而数据采样是在上升沿。这意味着当 STM32 发送一个字节时它会在 SCLK 下降沿把下一个 bit 推到 SDIO 线上然后在下一个 SCLK 上升沿采样这个 bit。这个过程本身就会引入一个“半个时钟周期”的相位偏移。如果 SCLK 频率是 10MHz周期 100ns那么这个偏移就是 50ns远大于 ADC 要求的 2.5ns这就是为什么很多人按手册接线、用 CubeMX 生成默认 SPI 配置却始终读不到正确 ID 的根本原因。我们的实操解法是强制使用“软件片选”“精确延时”。禁用硬件 NSS在 CubeMX 中将 SPI 的 NSS 引脚配置为 GPIO 输出并初始化为高电平。手动控制 CS#在每次 SPI 传输前先用HAL_GPIO_WritePin()将 CS# 拉低传输结束后立即拉高。插入精准延时在 CS# 拉低后、第一个 SCLK 边沿之前插入一个__NOP()循环约 3~5 个 NOP对应 1~2ns确保 SDIO 数据在 SCLK 上升沿到来前已稳定。这个延时不能靠HAL_Delay()必须是 CPU 周期级的精确控制。关闭所有干扰源在 SPI 传输函数内部临时关闭 SysTick、所有中断__disable_irq()防止任何中断打断时序。提示我们曾用 Saleae Logic 8 逻辑分析仪抓取过 SPI 波形。在未做上述处理时SDIO 信号在 SCLK 上升沿附近有明显的“台阶”和振铃这是建立时间不足的典型表现。加入 NOP 延时后波形变得干净利落数据采样点稳稳落在眼图中央。3.2 LVDS 信号链从芯片引脚到 FPGA 引脚阻抗连续性是生命线LVDS 的核心是“恒流源驱动 100Ω 终端匹配”。这个看似简单的公式却是整个硬件调试中最容易被忽视、也最致命的一环。我们遇到的第一个“哑巴”故障就是 LVDS 信号在示波器上能看到清晰的差分波形但 FPGA 就是收不到任何数据。排查了三天最后发现问题出在 PCB 的“过孔”上。AD9268 的 LVDS 输出引脚如 D0P/D0N到 PCB 表层走线再到连接 FPGA 的过孔这一段路径的特性阻抗必须严格控制在 100Ω ± 5%。而一个标准的 0.3mm 过孔其自身阻抗大约是 25Ω。如果一对 LVDS 差分线共用了 4 个过孔D0P 两个D0N 两个那么这 4 个过孔就像 4 个微小的“阻抗断点”在信号路径上形成了强烈的反射。虽然单个过孔的反射很小但 125MHz 的信号波长在 FR4 板材上约为 1.2 米而一个 0.3mm 过孔的物理尺寸远小于波长其影响主要体现在高频分量上。这些高频分量的反射叠加在一起会严重劣化信号的眼图导致 FPGA 的 ISERDES 无法正确采样。我们的实操解法是全链路阻抗控制 “背钻”替代方案。叠层设计先行在 PCB 设计初期就必须与板厂沟通明确要求 LVDS 差分对所在的信号层其参考平面通常是 GND 平面必须完整不能有分割。我们采用 4 层板L1信号-L2GND-L3PWR-L4信号结构LVDS 走线全部放在 L1 层紧贴 L2 的完整 GND 平面。差分线宽/间距计算使用 Polar SI9000 工具根据板材参数FR4, Er4.3, H0.18mm计算出满足 100Ω 差分阻抗的线宽W和线间距S。我们的最终参数是 W0.15mm, S0.20mm。过孔处理绝对禁止LVDS 差分对在中途换层。如果必须换层例如从 L1 到 L4则必须使用“背钻”工艺即在过孔下方钻掉多余的铜柱使其只穿透到目标层。但背钻成本高昂。我们的低成本替代方案是将 LVDS 差分对全程保留在 L1 层通过精心规划的“蛇形走线”绕过障碍哪怕多走 2cm也要保证路径连续。对于必须换层的控制信号如 DCO则单独走线并在换层处添加 100Ω 的表贴电阻进行端接。终端匹配在 FPGA 的 LVDS 输入引脚处必须放置一个 100Ω 的表贴电阻跨接在 D0P 和 D0N 之间。这个电阻不能省略也不能放在 ADC 端那是源端匹配适用于长距离传输不适用于板级短距。我们曾尝试过不放这个电阻结果 FPGA 的 IBIS 仿真显示接收端眼图张开度不足 30%完全无法锁定。3.3 电源与地模拟、数字、LVDS三套系统必须“井水不犯河水”AD9268/AD9643 的数据手册里对电源引脚的划分极其细致AVDD模拟核心、DVDD数字 I/O、DRVDDLVDS 驱动、VREF基准电压…… 这不是厂商在故弄玄虚而是高速 ADC 的物理本质决定的。模拟部分AVDD, VREF对噪声极度敏感任何一点来自数字开关的毛刺都会直接转化为采样误差。而 LVDS 驱动部分DRVDD则需要提供稳定的电流源其噪声会直接影响差分信号的共模电平。我们最初的 PCB 设计采用了“单点接地”的经典理论将所有地平面在 ADC 下方用一个 0Ω 电阻连在一起。结果是灾难性的在 100MHz 采样时频谱上出现了一组间隔为 1MHz 的杂散强度高达 -40dBc。后来用近场探头扫描发现杂散的源头正是 DVDD 电源平面上的 1MHz 开关噪声通过 ADC 封装内部的衬底耦合窜入了 AVDD。我们的实操解法是“分区供电 磁珠隔离 独立地平面”。物理分区在 PCB 上用“挖空”的方式将模拟地AGND、数字地DGND、LVDS 地LGND完全隔离开。三个地平面只在 ADC 的“PGND”引脚Power Ground下方的一个小区域约 2mm × 2mm内通过一个 0Ω 电阻或一小块铜皮相连。这个连接点就是整个系统的“星型接地点”。磁珠隔离DVDD 和 DRVDD 的电源输入必须各自经过一个 600Ω100MHz 的铁氧体磁珠如 Murata BLM18AG601SN1然后再经过一个 10uF 的钽电容和一个 100nF 的陶瓷电容进行滤波。AVDD 则更苛刻我们用了两级磁珠第一级 120Ω100MHz第二级 600Ω100MHz 三级电容22uF 钽 1uF X7R 100nF X7R。去耦电容布局所有去耦电容必须紧贴 ADC 的对应电源引脚走线长度从电容焊盘到芯片引脚必须小于 2mm。我们曾因为一个 100nF 电容离 AVDD 引脚太远走了 5mm 的线导致在 125MHz 采样时VREF 引脚上出现了 20mVpp 的纹波直接让 ENOB有效位数从 14.2bit 降到了 12.8bit。注意VREF 引脚是整个 ADC 的“心脏”。它必须由一个超低噪声的专用基准源如 ADR4540提供且其输出必须经过一个 RC 低通滤波器R10Ω, C10uF后再接入 ADC。任何试图用 LDO 的输出直接作为 VREF 的做法都是在自毁长城。4. 实操过程与核心环节实现一份可直接抄作业的调试清单4.1 第一步上电与基础验证耗时15 分钟这是整个调试流程的“安检门”必须一丝不苟。任何跳过此步的尝试都会让后续工作变成大海捞针。目视检查用放大镜检查 ADC 周围所有焊点特别是 0402 封装的去耦电容确认无虚焊、连锡、漏焊。重点检查 AVDD、DVDD、DRVDD、VREF、GND 引脚。万用表初筛测量 AVDD 引脚对 AGND 的电压应为 1.8V ± 1%。若偏差过大立刻断电检查 LDO 输出和滤波电容。测量 DVDD 引脚对 DGND 的电压应为 1.8V ± 1%。测量 DRVDD 引脚对 LGND 的电压应为 1.8V ± 1%。最关键的一步测量 VREF 引脚对 AGND 的电压。AD9268 的 VREF 典型值是 1.0V但允许范围是 0.95V ~ 1.05V。如果此处电压为 0V 或 1.8V说明基准源未工作或 VREF 引脚被短路。示波器看波形将示波器探头10X的地线夹接到 AGND信号钩钩住 DCO数据时钟输出引脚。给 ADC 上电观察是否有稳定的方波。DCO 的频率应等于采样率如 125MHz。如果没有波形或者波形是乱码说明 ADC 核心未启动问题一定出在电源、地或 RESET 信号上。4.2 第二步SPI 通信握手耗时2 小时这是建立“信任关系”的第一步。目标是能稳定读取芯片 ID 寄存器0x00。编写最小化 SPI 读取函数只包含 CS# 控制、发送 0x00读 ID 命令、接收 2 字节数据。禁用所有中断关闭所有外设时钟确保 CPU 全力服务 SPI。逻辑分析仪抓波形将 LA 的通道 0 接 CS#通道 1 接 SCLK通道 2 接 SDIO。设置触发条件为 CS# 下降沿。观察波形CS# 下降沿后SCLK 是否在 10ns 内开始SDIO 在第一个 SCLK 上升沿前是否已稳定为高电平0x00 的最高位所有 SCLK 周期是否均匀有无抖动逐字节调试如果第一次读取失败不要急着改代码。先尝试只发送 1 个字节0x00看能否收到正确的 IDAD9268 是 0x68。如果能说明时序基本 OK如果不能回到第 2 步用 LA 精确测量 tDSU和 tDH调整 NOP 数量。验证写操作成功读 ID 后尝试写一个非关键寄存器例如 0x01Output Mode Register将其设为 0x00LVDS 模式。然后再次读取 0x01确认写入成功。这一步验证了双向通信的完整性。4.3 第三步LVDS 数据流捕获耗时4 小时这是最激动人心也是最容易崩溃的一步。目标是 FPGA 能稳定捕获到连续、无误码的 LVDS 数据流。FPGA 侧准备在 Vivado 中为 LVDS 输入引脚如 D0P/D0N创建一个IBUFDS原语其输出连接到一个ISERDES模式设为BITSLIPFALSE,DATA_WIDTH8。ISERDES的输出连接到一个 FIFO。在顶层模块中添加一个 LED 指示灯当 FIFO 的FULL信号为高时点亮表示数据正在被成功接收。ADC 侧配置通过 SPI将 AD9268 的寄存器 0x01 设为 0x00LVDS寄存器 0x08Test Mode设为 0x01输出固定码 0xAAAA。这样LVDS 输出的数据就不再是随机噪声而是固定的、易于识别的模式。示波器看眼图将示波器设为差分测量模式使用两个通道数学运算 CH1-CH2探头分别接 D0P 和 D0N。调整时基到 2ns/div观察眼图。理想的眼图应该是一个清晰、张开的“眼睛”高度约 700mV宽度约 3ns。如果眼图闭合、抖动大或有明显畸变立刻停止回到 LVDS 布线检查。FPGA 逻辑分析使用 Vivado 的 ILAIntegrated Logic Analyzer核在ISERDES的输出端口打探针。运行程序捕获一段数据。在 ILA 的波形窗口中查找连续的0xAAAA模式。如果能找到说明物理链路和 FPGA 接收逻辑都 OK。如果找不到检查ISERDES的时钟域是否与 DCO 同步以及BITSLIP是否需要手动调整。4.4 第四步系统联调与性能验证耗时1 天这是验收成果的时刻。目标是 ADC 在真实信号下输出符合规格的数字数据。注入测试信号用一个高质量的信号发生器如 Keysight 33500B向 ADC 的模拟输入端AINP/AINN注入一个 10MHz、1Vpp 的正弦波。数据抓取与分析通过 STM32 将 FPGA 缓存的 8192 点数据通过 USB 打包发送到 PC。使用 Python 的matplotlib和numpy库绘制时域波形和 FFT 频谱。关键指标验证SNR信噪比在 FFT 频谱中找到 10MHz 信号峰计算其功率与整个奈奎斯特带宽0 ~ 62.5MHz内噪声功率的比值。AD9268 在 125MSPS 下的典型 SNR 是 73.5dB。实测值应在 71dB 以上。SFDR无杂散动态范围查看频谱中除了基波和其谐波外是否存在其他显著的杂散峰。最强的杂散应低于基波 90dBc。ENOB有效位数根据 SNR 计算ENOB (SNR - 1.76) / 6.02。实测 ENOB 应 ≥ 11.5bit。压力测试将采样率逐步提高到 125MSPS重复步骤 1-3。观察 SNR 和 SFDR 是否随速率升高而恶化。如果恶化严重3dB问题大概率出在电源噪声或 LVDS 信号完整性上。5. 常见问题与排查技巧实录一份来自战场的速查表问题现象可能原因排查步骤解决方案SPI 读 ID 失败返回全 0 或全 11. CS# 信号未正确拉低2. SCLK 频率过高超出 ADC 时序3. SDIO 线存在严重上拉/下拉1. 用万用表测 CS# 引脚电压2. 用 LA 抓 SCLK确认频率3. 断开 SDIO 与 MCU 的连接单独测 ADC 的 SDIO 引脚对地电阻1. 检查 MCU 的 GPIO 配置和初始化代码2. 将 SCLK 降至 1MHz确认通信成功后再逐步提速3. 移除所有外部上下拉电阻ADC 的 SDIO 是三态由内部控制LVDS 有波形但 FPGA 收不到数据1. FPGA 的 LVDS 输入标准未正确配置2. 100Ω 终端电阻缺失或焊接不良3. DCO 时钟未正确连接到 FPGA 的采样时钟引脚1. 检查 Vivado 中 IO 的IOSTANDARD是否为LVDS_252. 用万用表蜂鸣档测 D0P-D0N 间的电阻3. 用示波器确认 DCO 引脚有稳定时钟1. 在 XDC 文件中为 LVDS 引脚添加set_property IOSTANDARD LVDS_25 [get_ports {d0p}]2. 更换并重新焊接 100Ω 电阻3. 检查 DCO 走线确保无断线、短路频谱上出现固定间隔的杂散如 1MHz, 2MHz1. DVDD 电源噪声耦合到 AVDD2. 数字地DGND与模拟地AGND之间存在共模噪声1. 用近场探头扫描 DVDD 电源平面2. 用示波器差分探头测 AVDD 对 AGND 的纹波1. 在 DVDD 的输入端增加一级 LC 滤波磁珠电容2. 检查“星型接地点”是否只有一个且位置是否在 ADC 的 PGND 引脚正下方ADC 温度升高后数据开始出现随机错误1. AVDD 或 DRVDD 的 LDO 在高温下热保护关断2. 去耦电容在高温下容量衰减1. 用手触摸 LDO 封装感受是否异常烫手2. 查看 LDO 数据手册确认其热关断阈值1. 更换为更高功率、带散热片的 LDO2. 将 10uF 钽电容更换为 22uF 的固态电容如 Panasonic SP-Cap在 CubeMX 中配置 SPI DMA但数据接收错乱1. DMA 的缓冲区大小与 SPI 传输字节数不匹配2. DMA 传输完成中断中未及时清除相关标志位导致重复进入中断1. 检查HAL_SPI_TransmitReceive_DMA()函数的Size参数2. 在中断服务函数中检查__HAL_SPI_GET_FLAG()和__HAL_SPI_CLEAR_FLAG()1. 确保Size等于你要传输的字节数如读 ID 是 2 字节2. 在中断服务函数末尾务必调用HAL_SPI_DMAStop()和HAL_SPI_DeInit()然后重新初始化实操心得我们踩过的最深的一个坑是关于“SPI 的 MSB/LSB 顺序”。ADI 的数据手册里所有寄存器的 bit 位编号都是从 MSBbit 15到 LSBbit 0。但 STM32 的 SPI 外设在 8-bit 模式下默认是先发 MSB。而 AD9268 的 SPI 协议要求命令字节的 bit 7最高位必须是“读/写”标志。我们最初以为发送0x00就是读 ID但实际上0x00的二进制是00000000其 bit 7 是 0代表“写”这会导致 ADC 进入一个等待写数据的状态从而拒绝任何后续的读操作。正确的命令字节应该是0x8010000000其 bit 7 是 1代表“读”。这个细节在数据手册的“SPI Read/Write Timing Diagram”图的注释里用小号字体写着“The MSB of the command byte is the R/W bit.” —— 这就是为什么调试高速 ADC永远要带着放大镜和耐心去读那些被忽略的 footnote。6. 关于“STM32F103 DMA SPI”的特别提醒它不是银弹网络上充斥着大量“STM32F103 SPI DMA 读取 ADC 数据”的教程和代码标题很诱人但内容往往只适用于低速 ADC如 1MSPS 以下。对于 AD9268/AD9643 这种 100M 级别的器件强烈建议放弃在 STM32 上直接用 DMA 接收 LVDS 数据的想法。原因有三带宽瓶颈STM32F103 的 APB2 总线最高频率为 72MHz其 FSMC 或 GPIO 翻转速度根本无法跟上 125MHz 的数据流。试图用 GPIO 模拟 LVDS 接收无异于用自行车去追高铁。时序不确定性DMA 的触发、传输、中断响应都受到 CPU 内部总线仲裁、Cache、中断优先级等多重因素影响其延迟是不可预测的。而 LVDS 数据的有效窗口是 4ns任何微秒级的抖动都会导致采样失败。资源挤占一个 125MSPS 的 16 位数据流其原始带宽是 2Gbps。即使经过 FPGA 的压缩和打包最终通过 USB 2.0480Mbps传给 PCSTM32 也需要承担大量的协议打包、USB 传输调度工作。如果再让它去干高速数据搬运的活整个系统会变得极其脆弱。我们的最终方案是STM32F103 只负责“慢速控制”FPGA 负责“高速搬运”。STM32 通过一个简单的 UART 或 SPI 接口向 FPGA 发送“开始采集”、“停止采集”、“读取缓存”等指令。FPGA 收到指令后自主完成 ADC 配置、数据采集、FIFO 管理、数据打包。当 FIFO 达到预设深度如 4KBFPGA 通过一个 GPIO 信号通知 STM32STM32 再通过 DMA从 FPGA 的共享 SRAM 中以“爆发式”的方式批量读取这 4KB 数据。这种方式将“实时性要求极高”的任务和“实时性要求较低”的任务彻底分离系统稳定性和可维护性得到了质的提升。这个设计哲学比
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进