多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

FPGA+STM32相控阵雷达信号处理系统架构与工程实践

FPGA+STM32相控阵雷达信号处理系统架构与工程实践 1. 从“PLFM_RADAR”这个名字说起它到底想做什么第一次看到“PLFM_RADAR”这个项目名很多人会愣一下PLFM 是什么是某个芯片型号还是某种调制方式的缩写结合关键词里的 phased array、RADAR、FPGA、STM32基本可以判断这是一个相控阵雷达信号处理平台的项目代号。PLFM 大概率是 Pulse Linear Frequency Modulation 的缩写也就是脉冲线性调频——雷达领域最经典、最常用的一种波形体制。为什么这个项目值得单独拿出来讲因为相控阵雷达听起来高大上但真正落到工程实现上它其实是一套非常具体的分工FPGA 负责高速数据采集、数字下变频、脉冲压缩、波束形成这些“重活”STM32 负责系统控制、时序管理、人机交互、上位机通信这些“细活”。两者各司其职中间通过高速接口交换数据。这套架构在工业雷达、气象雷达、无人机避障雷达、车载毫米波雷达里反复出现是雷达工程师绕不开的基本功。这篇文章适合谁看如果你正在做基于 FPGA 的雷达信号处理项目或者手头有一个相控阵相关的课题、毕设、竞赛选题又或者你只是好奇“雷达信号处理到底是怎么从天线走到屏幕上的”那这篇内容应该能给你一条比较清晰的路径。我不会只讲概念而是把架构设计、芯片选型、接口协议、时序对齐、调试踩坑这些实际会遇到的问题都摊开来说。需要提前说明的是PLFM_RADAR 这个项目本身没有公开的完整源码和文档下面的内容是基于相控阵雷达信号处理系统的通用工程实践结合 FPGA STM32 这套经典组合的常见做法进行的合理还原和补充。如果你手上的项目细节和这里描述的不完全一致那很正常重点是理解背后的设计逻辑。2. 相控阵雷达的信号链到底长什么样2.1 从天线到 ADC模拟前端决定了系统上限相控阵雷达和传统机械扫描雷达最大的区别在于它没有转动的天线而是通过控制每个阵元发射/接收信号的相位差让波束在空间上“电子扫描”。一个典型的 N 元线阵或面阵每个阵元后面都跟着一套收发组件T/R 组件包括功率放大器、低噪声放大器、移相器、衰减器。接收链路里每个阵元的信号经过低噪放和移相器之后会在模拟域或者数字域进行合成。模拟合成速度快、资源省但灵活性差数字合成需要在每个通道后面都放 ADC数据量大得惊人但可以做自适应波束形成、超分辨测角这些高级操作。PLFM_RADAR 这个级别的项目通常会选择子阵级数字化的折中方案比如 16 个阵元先分成 4 个子阵每个子阵内部模拟合成4 个子阵输出再分别数字化。这样既保留了部分数字灵活性又不至于让 FPGA 的 IO 和逻辑资源爆炸。ADC 的选型是第一个关键决策点。PLFM 波形的带宽通常在几 MHz 到几十 MHz 之间根据奈奎斯特采样定理采样率至少要覆盖 2 倍带宽。但实际工程里我们往往会过采样到 2.5 到 4 倍目的是降低对抗混叠滤波器的阶数要求同时给数字下变频留出足够的过渡带。比如一个 10 MHz 带宽的 LFM 信号采样率选 40 MSPS 是比较舒服的。分辨率方面12 到 14 bit 是主流再高的话 FPGA 的 LVDS 接口压力和后续处理量都会明显上升。注意ADC 的采样时钟质量直接决定整个系统的相位噪声底。相控阵雷达对通道间相位一致性极其敏感时钟抖动如果太大波束指向精度和旁瓣电平都会恶化。建议用低抖动的时钟分配芯片并且做好时钟走线的等长和屏蔽。2.2 FPGA 在信号链里的真实角色很多人以为 FPGA 在雷达系统里就是“做做滤波”这个理解太窄了。在 PLFM_RADAR 这类系统里FPGA 承担的是从 ADC 原始数据到目标点迹之间的全部实时处理。具体来说至少包括以下几件事第一是数字下变频DDC。ADC 采回来的中频信号需要乘以一个本地振荡器的正弦/余弦序列搬移到基带然后通过抽取滤波器降低采样率。这一步在 FPGA 里通常用乘法器加 CIC 滤波器加半带滤波器级联实现。CIC 负责大比例抽取半带负责精细滤波两者配合可以在资源消耗和阻带衰减之间取得平衡。第二是脉冲压缩。LFM 信号的优势在于发射一个宽脉冲可以获得高能量接收时通过匹配滤波本质上是和发射波形做卷积把它压缩成一个窄脉冲从而同时获得高能量和高距离分辨率。FPGA 里实现脉冲压缩常见做法是把匹配滤波器的系数存在 ROM 里用 FIR 滤波器结构做卷积。如果点数很多可以考虑用 FFT 做频域卷积但 FFT 的资源和延迟需要仔细评估。第三是波束形成。对于数字波束形成系统每个通道的下变频输出需要乘以对应的相位权值再累加。这个权值可以预先算好存在查找表里也可以根据波束指向实时计算。FPGA 的并行结构非常适合这种“多通道乘加”的操作一个时钟周期就能完成几十个通道的复数乘累加。第四是目标检测和参数估计。经过脉冲压缩和波束形成之后信号会做 CFAR恒虚警率检测找出超过门限的点然后估计距离、速度、角度。这部分算法在 FPGA 里实现起来比较有挑战因为 CFAR 需要滑动窗口统计资源消耗不小。很多项目会选择在 FPGA 里做初步的 CFAR把候选点传给 STM32 或者上位机做进一步处理。2.3 STM32 不是“打杂的”它是系统调度中枢STM32 在这套架构里的角色经常被低估。有人觉得 FPGA 都把事情干完了STM32 就是个串口转发器。实际上一个设计良好的系统里STM32 负责的是时间敏感但计算不密集的任务雷达工作时序控制什么时候发射、什么时候接收、PRF脉冲重复频率怎么切换、波束驻留时间多长与上位机的通信协议把 FPGA 处理后的目标点迹打包通过以太网或 USB 上传系统状态监控温度、电压、电流的采集和告警人机交互按键、显示屏、蜂鸣器这些参数配置把上位机下发的波形参数、波束指向、检测门限写入 FPGA 的寄存器STM32 的强项是实时性和低功耗中断响应确定性好外设丰富。用 STM32F4 或者 STM32H7 系列主频足够跑这些控制逻辑而且 H7 带以太网 MAC 和 USB HS跟 FPGA 和上位机的通信都很方便。3. FPGA 与 STM32 的分工边界怎么划3.1 数据流和控制流的分离原则在 PLFM_RADAR 这类系统里FPGA 和 STM32 之间的分工本质上遵循的是数据流归 FPGA控制流归 STM32这个原则。但实际项目中这条线并不是那么清晰经常会出现“这个功能到底放哪边”的纠结。我的经验是判断标准可以归结为三个问题第一这个任务是不是每个采样周期都要做如果是放 FPGA。第二这个任务的计算量是不是跟采样率成正比如果是放 FPGA。第三这个任务是不是需要频繁跟外部设备交互、但实时性要求没那么极端如果是放 STM32。举个例子脉冲压缩是每个脉冲都要做的计算量跟采样点数和滤波器阶数成正比毫无疑问放 FPGA。而“根据上位机指令切换波形参数”这件事可能几秒钟才发生一次但涉及协议解析、参数校验、寄存器写入放 STM32 更合适。3.2 接口选型FSMC、SPI、UART 还是以太网FPGA 和 STM32 之间的通信接口常见的有几种选择各有各的适用场景接口类型典型速率适用场景注意事项FSMC/FMC几十 MB/sSTM32 读写 FPGA 内部寄存器或 RAM时序需要仔细约束地址线多SPI几 MHz 到几十 MHz低速配置和状态读取简单可靠但速率有限UART几百 kbps 到几 Mbps调试信息、低速控制最简单但只适合小数据量以太网10/100 Mbps大量目标点迹上传需要协议栈STM32 H7 自带 MACUSB几十到几百 Mbps高速数据上传STM32 做 USB 设备有坑后面细说在 PLFM_RADAR 这个场景里我倾向于双通道设计用 FSMC 或者 SPI 做控制通道STM32 通过它配置 FPGA 的寄存器、读取状态用 UART 或者以太网做数据通道把 FPGA 处理完的目标点迹传给上位机。如果目标点迹数据量不大比如每个 CPI 只有几十个点UART 波特率拉到 921600 甚至 2 Mbps 也够用。如果要传原始 ADC 数据做调试那就必须上以太网或者 USB 了。3.3 时钟和同步最容易被忽视的坑FPGA 和 STM32 各自有各自的时钟域两者通信的时候跨时钟域同步是必须处理的问题。我见过不少项目功能逻辑都对但数据偶尔出错查来查去就是跨时钟域没处理好。如果用的是 FSMC 或者 SPI 这种带握手信号的接口问题相对小一些因为读写操作本身有明确的时序关系。但如果是 FPGA 主动往 STM32 推数据或者 STM32 主动读 FPGA 的异步 FIFO那就必须做同步处理。常见做法是数据信号用双触发器同步控制信号用握手协议或者异步 FIFO。还有一个容易被忽视的点是系统上电顺序。FPGA 的配置时间通常比 STM32 启动时间长如果 STM32 在 FPGA 还没配置完成的时候就试图访问它读回来的全是无效数据。稳妥的做法是FPGA 配置完成后拉一个“INIT_DONE”信号给 STM32STM32 检测到这个信号之后再开始初始化通信接口。4. 基于 FPGA 的多端口 DDR 读写雷达数据缓存的命脉4.1 为什么雷达系统离不开 DDRPLFM_RADAR 这类系统里DDR 内存扮演的是“数据中转站”的角色。ADC 采回来的原始数据、下变频后的基带数据、脉冲压缩的中间结果、多个 CPI 的积累数据都需要地方暂存。FPGA 内部的 Block RAM 容量有限通常只有几 MB 到几十 MB存不下多个脉冲的完整数据。这时候就需要外挂 DDR3 或者 DDR4。但 DDR 的读写控制不是一件简单的事。雷达系统的数据流有几个特点第一写入是连续的、高速的ADC 每个时钟周期都在产生新数据第二读取可能是突发的、非连续的比如脉冲压缩的时候需要按帧读取第三可能有多个通道同时访问 DDR比如波束形成需要同时读取多个通道的数据。4.2 多端口 DDR 控制器的设计思路“多端口”这个词在这里的意思是DDR 控制器需要同时服务多个读写请求源。比如通道 A 在写 ADC 数据通道 B 在读脉冲压缩的系数通道 C 在读上一个 CPI 的积累结果。这些请求的优先级、数据宽度、突发长度都不一样。常见的实现方案有两种。一种是时分复用DDR 控制器在一个调度周期内轮流响应各个端口的请求。这种方案逻辑简单但需要仔细设计仲裁策略否则高优先级的数据流可能被低优先级请求阻塞。另一种是多 Bank 并行利用 DDR 的多个 Bank把不同端口的数据映射到不同的 Bank 上减少冲突。这种方案效率高但对地址映射和 Bank 管理的要求更高。在实际项目中我通常会用 Xilinx 的 MIGMemory Interface Generator或者 Intel 的 EMIF IP 核来生成 DDR 控制器然后在上面套一层自定义的仲裁逻辑。仲裁策略一般采用“优先级 轮询”的混合方式ADC 写入通道给最高优先级保证不丢数其他读取通道按轮询方式分配带宽。提示DDR 的读写切换有额外的时序开销tWTR、tRTW 等参数频繁的读写切换会明显降低有效带宽。设计时尽量把同类型的操作批量处理比如积累一批写请求再统一写入积累一批读请求再统一读出。4.3 实测中遇到的带宽瓶颈和解决办法我曾经在一个类似项目里遇到过 DDR 带宽不够的问题。理论上 DDR3-1600 的带宽有 12.8 GB/s但实际测下来有效带宽只有 3 GB/s 左右。排查后发现几个原因第一突发长度太短。DDR 的高效率依赖于长突发传输如果每次只读写几个数据就切换命令开销和切换开销会吃掉大部分带宽。解决办法是把多个小请求合并成大突发。第二Bank 冲突。多个端口同时访问同一个 Bank 的不同行会导致频繁的预充电和激活操作。解决办法是重新设计地址映射让不同端口尽量落在不同 Bank。第三刷新操作的影响。DDR 需要定期刷新刷新期间无法响应读写请求。如果刷新太频繁有效带宽会下降。这个只能通过选择合适刷新间隔和调度策略来缓解。5. STM32 做 USB 设备雷达数据上传的实战细节5.1 为什么选 USB 而不是串口雷达系统调试的时候经常需要把原始数据或者中间结果传到电脑上分析。串口最简单但速率是硬伤。115200 波特率下每秒只能传 11 KB 左右一个脉冲的 ADC 数据可能就有几十 KB传起来慢得让人抓狂。USB FS全速理论速率 12 Mbps实际能跑到 1 MB/s 左右USB HS高速理论速率 480 Mbps实际能跑到 30-40 MB/s。对于雷达数据上传来说USB HS 是比较理想的选择。STM32 的 USB 外设F4 系列只有 USB FSH7 系列有 USB HS。如果数据量不大FS 也够用如果要传原始 ADC 数据建议上 H7。5.2 STM32 USB 设备开发的几个坑STM32 做 USB 设备最容易踩的坑有这几个第一个坑是时钟配置。USB FS 需要 48 MHz 时钟这个时钟通常由 PLL 提供。如果主频配置和 USB 时钟冲突USB 就枚举不了。比如 STM32F407 要跑 168 MHz 主频PLL 配置需要仔细算确保能分出 48 MHz 给 USB。我见过有人主频跑 168 MHzUSB 死活不识别最后发现是 PLL 分频系数设错了。第二个坑是端点缓冲区分配。STM32 的 USB 外设有一块专用的 PMAPacket Memory Area不同型号大小不一样F4 通常是 320 字节。如果端点配置太多或者缓冲区设太大PMA 不够用USB 就会工作异常。建议在 CubeMX 里配置的时候仔细检查每个端点的缓冲区大小不要浪费。第三个坑是描述符。USB 描述符是主机识别设备的关键设备描述符、配置描述符、接口描述符、端点描述符任何一个字段错了都可能导致枚举失败。特别是 VID/PID如果用了默认值可能和系统里其他设备冲突。建议用自己申请的 VID/PID或者用 ST 的测试 VID/PID 但注意不要用于量产。第四个坑是数据传输的同步。USB 是主机轮询的设备不能主动发数据。如果 FPGA 那边有数据要传STM32 需要先缓存起来等主机来读的时候再发。如果缓存不够大数据就会丢。解决办法是设计一个环形缓冲区FPGA 往里面写USB 中断从里面读读写指针分开管理。5.3 用 USB 做雷达数据上传的完整流程假设我们要把 FPGA 处理后的目标点迹通过 USB 传给上位机流程大概是这样的STM32 初始化 USB 外设配置为 CDC虚拟串口或者自定义设备类FPGA 检测到新的目标点迹通过 FSMC 或者 SPI 写入 STM32 的缓冲区STM32 收到数据后触发 USB 发送上位机通过 USB 读取数据解析显示如果数据量比较大建议用 USB 的批量传输端点而不是中断端点。批量传输不保证带宽但保证数据完整性适合大数据量传输。中断传输适合小数据量、低延迟的场景。6. 调试雷达系统时那些让人抓狂的问题6.1 串口能发不能收一个经典排查案例雷达调试的时候串口通信是最基本的调试手段。但串口问题也是最多的。我遇到过一个很典型的情况STM32 通过串口给 FPGA 发配置命令FPGA 能收到但 FPGA 回传的状态数据STM32 死活收不到。排查过程是这样的先用示波器看 FPGA 的 TX 引脚有波形说明 FPGA 确实在发。再看 STM32 的 RX 引脚也有波形说明信号到了。那问题就在 STM32 的串口配置上。检查后发现STM32 的串口 RX 引脚配置成了推挽输出模式而不是复用输入模式。CubeMX 里如果手动改过引脚配置很容易出这个问题。这个坑的教训是串口通信出问题先确认硬件链路再确认引脚配置最后查软件逻辑。不要一上来就怀疑代码。6.2 CAN 通信突然连不上终端电阻和波特率如果雷达系统里用了 CAN 总线做设备间通信可能会遇到“昨天还好好的今天突然连不上”的情况。CAN 通信对物理层的要求比较高常见问题有终端电阻没接或者接错。CAN 总线两端各需要一个 120 欧姆的终端电阻如果只接了一端或者电阻值不对通信距离短的时候可能勉强能通距离一长就出问题。波特率不匹配。CAN 的波特率和时钟配置有关如果两个节点的时钟源精度不够或者分频系数算错波特率就会有偏差导致通信失败。总线电容太大。如果挂的设备太多或者线太长总线电容会累积导致信号边沿变缓通信出错。排查 CAN 问题最好用 CAN 分析仪抓一下总线波形看看差分信号的质量和波特率是否准确。6.3 STM32 延时函数卡死中断优先级惹的祸STM32 的HAL_Delay()函数依赖 SysTick 中断来计数。如果在一个高优先级中断里调用HAL_Delay()而 SysTick 中断的优先级比它低那 SysTick 中断就进不来HAL_Delay()就会一直卡住。这个问题在雷达系统里特别容易遇到因为雷达的时序控制经常在中断里做而中断优先级配置又比较复杂。解决办法是要么在中断里不要用HAL_Delay()改用硬件定时器做精确延时要么把 SysTick 的优先级设到最高。7. 从原型到可用系统几个关键的设计取舍7.1 资源估算FPGA 选型不能只看逻辑单元选 FPGA 的时候很多人只看逻辑单元数量这是不够的。雷达信号处理系统里以下几个资源同样关键DSP Slice 数量脉冲压缩、波束形成、DDC 都要用乘法器DSP 不够就得用逻辑搭乘法器资源和功耗都会上去。Block RAM 容量匹配滤波器系数、波束权值、中间数据缓存都要用 BRAM容量不够就得外挂 SRAM 或者 DDR。高速收发器如果 ADC 用 JESD204B 接口需要 FPGA 有对应的 SerDes 资源。IO 数量和电平标准ADC 的 LVDS 接口、DDR 的接口、STM32 的 FSMC 接口都需要足够的 IO 和正确的电平标准支持。以 Xilinx 的 Artix-7 或者 Kintex-7 为例做一个小规模相控阵雷达信号处理XC7A200T 或者 XC7K325T 是比较常见的选择。如果通道数更多、算法更复杂可能要考虑 Zynq 或者 Kintex UltraScale。7.2 功耗和散热别让雷达变成烤箱FPGA 和 DDR 的功耗都不小尤其是高速收发器和 DDR 控制器全速运行的时候。一个中等规模的雷达信号处理板FPGA 加 DDR 加 ADC 的功耗可能到 10-20 W。如果散热没做好芯片温度上去之后时序会变差甚至出现功能错误。散热设计要考虑几点第一FPGA 下面要铺足够的散热过孔把热量导到背面第二如果功耗大要加散热片甚至风扇第三DDR 的布局要远离热源因为 DDR 对温度比较敏感温度高了刷新率要提高否则会丢数据。7.3 电磁兼容雷达系统的隐形战场雷达系统本身就是一个电磁发射源同时又要接收微弱的回波信号电磁兼容EMC问题非常突出。常见的措施包括电源做好滤波数字电源和模拟电源分开用磁珠或者电感隔离高速信号走线做好阻抗匹配和屏蔽尤其是 ADC 的模拟输入和时钟收发隔离要做好发射的时候接收通道要能承受泄漏过来的大信号接地要合理数字地、模拟地、射频地分开单点连接这些问题在原型阶段可能不明显但到了外场测试或者量产阶段就会集中爆发。建议在 PCB 设计阶段就找有射频经验的工程师评审。8. 写在最后一些个人体会做 PLFM_RADAR 这类项目最大的感受是雷达系统是一个系统工程任何一个环节出问题整个系统都跑不起来。FPGA 逻辑写得再好如果 ADC 时钟质量不行信噪比就上不去STM32 控制逻辑再完善如果 DDR 带宽不够数据就会丢算法再先进如果电源噪声太大检测性能就会下降。另一个体会是调试手段比代码本身更重要。雷达系统的调试不能只靠打印和断点必须要有示波器、频谱仪、逻辑分析仪这些工具。FPGA 内部要预留足够的调试资源比如 ILA集成逻辑分析仪核可以在线抓取内部信号。STM32 这边SWO 或者串口打印要设计好关键路径上要有日志。最后文档和版本管理不能省。雷达系统的参数太多了波形参数、波束权值、滤波器系数、接口协议任何一个改了都要记录。我见过因为版本混乱导致外场测试失败的案例查了两天才发现是 FPGA 配置文件用错了版本。用 Git 管理代码和配置文件每次修改都写清楚改了什么、为什么改这个习惯能省下大量时间。
返回列表