☰
PLFM_RADAR:FPGA+STM32脉冲线性调频雷达原型全链路设计与实现
2026/11/2 10:37:47 网站建设 项目流程

1. 项目缘起与整体设计思路

PLFM_RADAR 这个名字,第一次看到的人大概率会愣一下。PLFM 是 Pulse Linear Frequency Modulation 的缩写,翻译过来就是脉冲线性调频,说白了就是雷达领域里最经典的一种波形体制——线性调频脉冲压缩。后面跟着的 RADAR 就是雷达本身。所以这个项目从名字上就能拆出三层信息:波形体制是脉冲线性调频,信号处理链路涉及脉冲压缩,最终落地形态是一套雷达系统。

我最早接触这个方向是在做一个低成本相控阵验证平台的时候。当时的需求很明确:要一套能跑通完整信号链的雷达原型,从波形生成、发射、接收、下变频、ADC 采样,到数字下变频、脉冲压缩、动目标检测,最后出距离-多普勒二维图。预算有限,不可能上商用雷达开发套件,所以只能自己搭。核心器件选型上,FPGA 负责高速信号处理,STM32 负责系统控制和人机交互,这个分工几乎是这类项目的标配。

为什么这么分?因为雷达信号处理对实时性要求极高。以常见的 1MHz 带宽、1ms 脉冲重复周期为例,一个 CPI(相干处理间隔)内可能有 128 个脉冲,每个脉冲采样 1000 个点,算下来就是 12.8 万个复数样本。脉冲压缩要做 FFT、复数乘法、IFFT,MTD 还要在慢时间维再做一次 FFT。这些运算如果让 STM32 来扛,就算用 H7 系列带 FPU 和 DSP 指令,也基本跑不动实时。FPGA 的优势就在于并行流水线,做 FFT 和复数乘法可以做到每个时钟周期出一个结果,这是 MCU 架构做不到的。

但 FPGA 也不是万能的。系统控制、参数配置、上位机通信、状态监控这些事,用 FPGA 做反而麻烦。STM32 在这方面生态成熟,USB、UART、以太网都有现成库,开发效率高。所以 PLFM_RADAR 的整体架构就是 FPGA 做信号处理核,STM32 做控制核,两者通过高速接口(通常是 SPI 或 FSMC)交换数据和命令。

这个项目适合谁?如果你正在做雷达相关的毕业设计、嵌入式竞赛,或者想入门相控阵和脉冲压缩算法,PLFM_RADAR 是一个很好的练手平台。它不像商用雷达那么复杂,但完整覆盖了从波形到成像的全链路。对于 FPGA 初学者来说,这也是一个能同时练到高速 ADC 接口、DDR 缓存、FFT IP 核、串口通信的综合性项目。对于 STM32 开发者来说,可以学到如何用 MCU 去协调一个高速信号处理系统,而不是只做点灯和串口打印。

整体设计上,我把它分成四个层次:射频前端、数据采集与缓存、信号处理、控制与显示。射频前端负责发射 LFM 波形和接收回波,数据采集用高速 ADC 把中频信号数字化,缓存用 DDR 做乒乓操作解决跨时钟域和速率匹配问题,信号处理在 FPGA 内完成脉冲压缩和 MTD,控制与显示由 STM32 和上位机配合完成。下面我逐层拆开讲。

2. 核心细节解析与实操要点

2.1 脉冲线性调频波形生成的关键参数

LFM 波形的数学表达式是 s(t) = rect(t/T) * exp(jpiKt^2),其中 T 是脉冲宽度,K 是调频斜率,B = KT 是带宽。这三个参数决定了雷达的距离分辨率和最大探测距离。距离分辨率 delta_R = c/(2B),c 是光速。如果你要 0.15 米的距离分辨率,带宽就得做到 1GHz,这对低成本系统来说不现实。所以实际项目中,我通常把带宽定在 10MHz 到 50MHz 之间,对应距离分辨率 3 米到 15 米,适合做近距离目标检测和算法验证。

调频斜率 K 的选择要结合采样率。根据奈奎斯特采样定理,采样率至少要是带宽的两倍。但实际工程中,我一般会留 2.5 倍以上的余量。比如带宽 20MHz,采样率至少 50MHz,我通常选 80MHz 或 100MHz。这样做的原因是,LFM 信号经过脉冲压缩后,旁瓣电平对采样率敏感,采样率太低会导致旁瓣抬高,影响弱目标检测。

脉冲宽度 T 和脉冲重复周期 PRI 的关系也要注意。T 不能太大,否则占空比过高,发射机散热和电源都是问题。我一般把占空比控制在 10% 到 20% 之间。比如 T = 10us,PRI = 100us,占空比 10%,这个比例比较舒服。PRI 决定了最大不模糊距离 R_max = c*PRI/2。PRI = 100us 对应 15km,对于近距离雷达足够了。

在 FPGA 里生成 LFM 波形,有两种做法。一种是直接用 DDS IP 核,配置频率扫描模式,输出就是 LFM。另一种是自己写相位累加器,用查找表输出正弦和余弦。DDS IP 核的好处是配置简单,Xilinx 和 Intel 都有现成的,但要注意频率扫描的步进精度和扫描时间要匹配。自己写的好处是灵活,可以加窗、可以改调制方式,但需要处理相位截断误差。我实测下来,如果对旁瓣要求不高,DDS IP 核完全够用;如果要做低旁瓣,建议自己写相位累加器,配合 16 位以上的相位位宽。

2.2 高速 ADC 采样与数据对齐

ADC 选型是 PLFM_RADAR 里最容易踩坑的地方。中频信号频率通常在 30MHz 到 200MHz 之间,根据带通采样定理,采样率不需要满足奈奎斯特的低通条件,只要满足带通条件就行。比如中频 70MHz,带宽 20MHz,采样率可以选 80MHz,这样 70MHz 的信号会混叠到 10MHz 的数字中频上。这个技巧在雷达接收机里非常常用,可以大幅降低对 ADC 采样率的要求。

但带通采样有个坑:采样时钟的抖动(jitter)会直接恶化信噪比。ADC 的信噪比公式里有一项是 -20log10(2pif_insigma_t),f_in 是输入信号频率,sigma_t 是时钟抖动。如果 f_in = 70MHz,sigma_t = 1ps,这一项就是 -20log10(2pi70e61e-12) ≈ -67dB。如果时钟抖动做到 10ps,就只剩 -47dB 了。所以 ADC 的采样时钟一定要用低抖动的晶振或时钟芯片,别用 FPGA 内部 PLL 直接分频出来的时钟,那个抖动通常很大。

数据对齐是另一个容易出问题的地方。ADC 输出通常是 LVDS 或 CMOS 电平,FPGA 接收时要做源同步采样。LVDS 的话,要用 IDELAY 和 ISERDES 原语,把数据和时钟对齐。我一般会在 FPGA 里做一个训练模式,让 ADC 输出已知的测试图案(比如递增计数),然后扫描 IDELAY 的抽头值,找到误码率最低的那个点。这个训练过程在系统上电时自动跑一次,把最佳延迟值存到寄存器里。实测下来,不做这个训练,数据错位是家常便饭,而且温度变化后还会漂移。

2.3 DDR 缓存的多端口读写设计

雷达数据流的特点是突发性强、速率高、需要缓存。一个脉冲的采样数据可能只有几微秒,但采样率是 100MHz,位宽 14 位,算下来瞬时数据率是 1.4Gbps。FPGA 内部 BRAM 根本存不下,必须用 DDR。DDR 的读写是分时复用的,不能同时读和写,所以要做乒乓操作。

具体做法是:把 DDR 分成两个 bank,一个 bank 写当前脉冲的数据,另一个 bank 读上一个脉冲的数据给信号处理模块。写完后切换 bank。这个切换逻辑要用状态机控制,注意 DDR 的刷新周期和 bank 切换的时序配合。我试过用 AXI 接口的 DDR 控制器,配置成两个端口,一个写一个读,但 AXI 的仲裁机制在突发长度大的时候会有延迟抖动。后来改成自己写一个简单的乒乓控制器,用原生接口,延迟稳定多了。

DDR 的地址映射也要注意。雷达数据是二维的:快时间维(一个脉冲内的采样点)和慢时间维(脉冲序号)。在 DDR 里存储时,我一般把快时间维放在低位地址,慢时间维放在高位地址。这样读一个脉冲的数据是连续地址,突发传输效率高。如果反过来,读一个脉冲要跨很多行,DDR 的行激活开销会吃掉大量带宽。

2.4 STM32 与 FPGA 的接口协议设计

STM32 和 FPGA 之间的通信,我选的是 SPI 加 FSMC 的组合。SPI 用来传命令和状态,速率不用太高,10MHz 足够。FSMC 用来传数据,比如把 FPGA 处理完的距离-多普勒图传给 STM32 做显示。FSMC 配置成 16 位数据宽度,地址线和片选接 FPGA 的 IO,FPGA 内部做一个双口 RAM 映射到 FSMC 地址空间。STM32 读的时候就像读外部 SRAM 一样,很方便。

这里有个细节:FSMC 的时序参数要跟 FPGA 的 RAM 读延迟匹配。STM32 的 FSMC 可以配置地址建立时间、数据保持时间等参数。如果 FPGA 那边是同步 RAM,读延迟是 1 个时钟周期,那 FSMC 的等待周期要设够。我一般先用保守参数(比如等待周期设 5 个),跑通后再逐步压缩,用示波器看 FSMC 的读写波形,确保没有建立/保持时间违例。

SPI 协议的设计上,我定义了一个简单的帧格式:帧头(2 字节)+ 命令码(1 字节)+ 数据长度(2 字节)+ 数据(N 字节)+ 校验(1 字节)。命令码包括配置波形参数、启动采集、读取状态、读取处理结果等。FPGA 那边用一个状态机解析 SPI 帧,收到完整帧后执行对应操作。这个协议简单可靠,调试的时候用逻辑分析仪抓 SPI 波形,一眼就能看出问题。

3. 实操过程与核心环节实现

3.1 系统上电与初始化流程

整个系统的上电顺序有讲究。我踩过的坑是:如果 FPGA 先配置完,STM32 还没启动,FPGA 可能会因为收不到命令而进入不确定状态。所以我的做法是让 STM32 先启动,初始化完外设后,通过一个 GPIO 给 FPGA 一个复位信号,FPGA 收到复位后才开始配置逻辑。这样时序是确定的。

STM32 的初始化包括:时钟树配置(HSE 到 PLL,系统时钟跑到 400MHz 以上)、GPIO 初始化(SPI、FSMC、复位控制引脚)、SPI 初始化(主机模式,CPOL=0,CPHA=0,速率 10MHz)、FSMC 初始化(NOR/SRAM 模式,16 位数据宽度)、USB 初始化(如果要用 USB 传数据给上位机)。USB 这块,STM32 的 USB OTG 库用起来还算顺手,配置成 CDC 设备,上位机识别成虚拟串口,传输速率比 UART 快得多。

FPGA 的初始化包括:DDR 控制器校准、ADC 接口训练、DDS 配置、FFT IP 核配置、中断使能。DDR 校准是必须的,Xilinx 的 MIG 和 Intel 的 UniPHY 都有自动校准流程,但校准结果要检查,如果校准失败,后面读写全是错的。ADC 训练就是我前面说的 IDELAY 扫描,找到最佳采样点。

3.2 波形发射与接收链路调试

发射链路的调试,我一般分三步走。第一步,用示波器看 DDS 输出的数字波形(如果 DAC 有模拟输出)或者用逻辑分析仪抓 DAC 的输入数据,确认 LFM 的频率在扫描。第二步,用频谱仪看发射中频信号的频谱,确认带宽和中心频率对。第三步,用喇叭天线发射,用一个简单的二极管检波器加示波器接收,看包络是不是脉冲形状。这三步走完,发射链路基本就没问题了。

接收链路的调试更麻烦一些。我通常先注入一个已知信号(用信号发生器产生一个单频连续波),看 ADC 采样后的数字频谱。在 FPGA 里加一个简单的 FFT 核,把 ADC 数据做 1024 点 FFT,通过 SPI 把幅度谱传给 STM32,再通过 USB 传到上位机显示。如果能看到一个干净的峰值,说明 ADC 采样和 FFT 链路都正常。然后换成 LFM 信号输入,看脉冲压缩后的峰值。如果峰值位置和理论值对得上,旁瓣电平也合理,接收链路就通了。

这里有个经验:调试的时候一定要把中间数据引出来看。FPGA 内部信号用 ILA(集成逻辑分析仪)抓,STM32 这边用串口打印或者 USB 传数据。别想着一次跑通,雷达信号链环节多,任何一个环节的参数不对,最后结果都是错的。分段调试,每段确认无误后再连起来,效率最高。

3.3 脉冲压缩的 FPGA 实现细节

脉冲压缩的本质是匹配滤波,在频域就是乘以参考信号的共轭频谱。FPGA 实现时,流程是:ADC 数据做 FFT,然后与预存的参考频谱做复数乘法,再做 IFFT,输出就是压缩后的脉冲。参考频谱是提前算好的,存在 ROM 里。复数乘法用 DSP48 或 DSP 块实现,注意位宽管理,避免溢出。

FFT 的长度选择要匹配脉冲采样点数。比如脉冲宽度 10us,采样率 100MHz,一个脉冲有 1000 个点。FFT 长度要选 1024 或 2048,把 1000 个点补零到 1024。补零会带来一点信噪比损失,但影响不大。如果 FFT 长度选 512,那就得截断,会损失脉冲能量,旁瓣也会抬高。所以 FFT 长度宁大勿小。

复数乘法的位宽管理是个细活。FFT 输出通常是 16 位或 18 位复数,参考频谱也是 16 位。乘出来是 32 位或 36 位,需要截位或舍入回 16 位给 IFFT。截位会引入量化噪声,舍入会好一些但资源消耗大。我一般用四舍五入加饱和处理,实测下来旁瓣能控制在 -35dB 以下。如果对旁瓣要求更高,可以加窗,比如汉明窗或泰勒窗,但主瓣会展宽,距离分辨率会下降。这是一个权衡,看你的应用场景。

3.4 MTD 与距离-多普勒二维图生成

MTD(动目标检测)是在慢时间维做 FFT。假设一个 CPI 有 128 个脉冲,每个脉冲经过脉冲压缩后得到一个距离维的复数序列。把这 128 个脉冲的同一个距离单元的数据取出来,做 128 点 FFT,就得到这个距离单元的多普勒谱。对所有距离单元都做一遍,就得到距离-多普勒二维图。

FPGA 实现 MTD 的难点在于数据转置。脉冲压缩输出是按脉冲顺序来的,先出脉冲 1 的所有距离单元,再出脉冲 2 的。但 MTD 需要按距离单元取数据,同一个距离单元的不同脉冲数据要放在一起做 FFT。所以需要一个转置缓存。我一般用 DDR 做这个转置:脉冲压缩结果按脉冲顺序写入 DDR,MTD 读取时按距离单元顺序读出。DDR 的地址计算要仔细,写地址是 pulse_idx * num_range_bins + range_idx,读地址是 range_idx * num_pulses + pulse_idx。这个转置操作对 DDR 带宽压力很大,要算好带宽够不够。

MTD 做完后,二维图的数据量是 128 距离单元 x 128 多普勒单元 = 16384 个复数。每个复数用 16 位表示,就是 64KB。这个数据量通过 FSMC 传给 STM32 没问题,STM32 再通过 USB 传给上位机显示。上位机用 Python 的 matplotlib 画二维图,横轴是距离,纵轴是多普勒,颜色表示幅度。如果看到目标是一个亮点,背景是噪声,那就对了。

4. 常见问题与排查技巧实录

4.1 雷达信号链典型故障速查表

现象可能原因排查方法解决方案
脉冲压缩后无峰值参考频谱不匹配检查参考频谱的共轭是否正确,FFT长度是否一致重新生成参考频谱,确保与发射波形参数一致
峰值位置偏移采样延迟未校准用已知延迟的电缆做参考,测量实际峰值位置调整 IDELAY 抽头值或数字延迟补偿
旁瓣电平过高截位方式不当或未加窗检查复数乘法后的截位逻辑,尝试加窗改用舍入加饱和,或加汉明窗
距离-多普勒图模糊MTD 转置地址错误用已知单频信号输入,检查多普勒维 FFT 结果修正 DDR 地址计算,确保转置正确
ADC 数据错位源同步采样未对齐运行 IDELAY 训练,扫描最佳采样点上电自动训练,存储最佳延迟值
DDR 读写失败校准未通过或时序违例检查 MIG/UniPHY 校准状态寄存器重新校准,降低 DDR 频率或调整时序参数
STM32 读 FSMC 数据错误等待周期不足用示波器看 FSMC 读写波形增加等待周期,或改用同步模式
SPI 通信无响应片选或时钟极性错误逻辑分析仪抓 SPI 波形检查 CPOL/CPHA 配置,确认片选有效

4.2 几个让我印象深刻的踩坑经历

第一个坑是 DDR 带宽不够。当时 MTD 转置和脉冲压缩同时访问 DDR,两个模块的突发长度都很大,结果 DDR 控制器频繁插入等待周期,实时性直接崩了。后来我把脉冲压缩的中间结果先存到 BRAM,等一个 CPI 的数据都收完了再统一写 DDR,MTD 读的时候也是整块读,这样 DDR 的访问模式变成了大块连续读写,带宽利用率上去了,实时性也恢复了。这个经验告诉我,DDR 不怕数据量大,就怕访问模式碎。

第二个坑是 ADC 时钟抖动。一开始我用 FPGA 的 PLL 分频出 100MHz 给 ADC 做采样时钟,结果脉冲压缩后的信噪比只有 40dB 左右,比理论值差了 20dB。查了很久才发现是 PLL 的抖动太大。换成专用的时钟芯片后,信噪比直接到了 60dB 以上。所以雷达系统里,时钟质量比什么都重要,别在这上面省钱。

第三个坑是 STM32 的 USB 传输丢包。STM32 的 USB OTG 在高速模式下,如果中断优先级配置不当,或者 DMA 缓冲区太小,很容易丢包。我的做法是把 USB 中断优先级设到最高,DMA 缓冲区开到 4KB 以上,上位机那边用大缓冲区接收,并且加一个简单的重传机制。实测下来,连续传 10MB 数据不丢包。

4.3 调试工具与技巧

逻辑分析仪是必备的,抓 SPI、FSMC、ADC 接口的波形全靠它。我用的是一款 16 通道、100MHz 采样率的便携逻辑分析仪,够用了。ILA 是 FPGA 调试的神器,Vivado 和 Quartus 都自带,可以把内部信号引出来看,不用改代码重新综合。示波器用来看模拟信号和时钟质量,带宽至少 200MHz,不然看不了中频信号。

还有一个技巧:在 FPGA 里加一个伪随机序列发生器,把已知的伪随机序列注入信号链,然后在输出端做相关,看相关峰值。这个方法可以快速判断信号链是否通畅,而且对信号链的线性度不敏感。我每次改完信号处理逻辑,都会先跑一遍伪随机序列测试,确认链路通了再做实际雷达实验。

4.4 参数配置的经验值

根据我多次项目的经验,下面这组参数在低成本雷达原型上比较稳妥:带宽 20MHz,脉冲宽度 10us,脉冲重复周期 100us,采样率 80MHz,FFT 长度 1024,CPI 脉冲数 128,DDR 时钟 400MHz(DDR3-800),STM32 系统时钟 400MHz,SPI 时钟 10MHz,FSMC 等待周期 3 个。这组参数下,距离分辨率约 7.5 米,最大不模糊距离 15km,速度分辨率约 0.12m/s(假设载频 2.4GHz),数据率约 1.4Gbps。对于毕业设计和算法验证来说,这个性能足够了。

如果要做更远距离或更高分辨率,带宽和采样率都要往上走,DDR 带宽和 FPGA 资源也要相应增加。我建议先用低参数跑通全链路,再逐步提高参数,这样调试起来心里有底。一上来就堆高参数,出了问题很难定位是哪个环节的瓶颈。

5. 系统联调与性能优化

5.1 全链路联调的顺序

全链路联调最忌讳的就是一把梭。我的做法是分四步走。第一步,只跑发射链路,用频谱仪确认 LFM 波形正确。第二步,把发射信号通过电缆直接接到接收端(不加天线),跑通接收和脉冲压缩,确认峰值位置和旁瓣电平。第三步,加上天线,在暗室或空旷场地做近距离目标检测,比如放一个角反射器在 5 米外,看能不能检测到。第四步,加 MTD,看运动目标的多普勒谱。每一步都确认无误后再进下一步,这样出问题的时候,排查范围就小很多。

联调的时候,我习惯在 STM32 里加一个调试模式,可以通过串口命令单独控制每个模块的开关。比如只开 ADC 采样,只开脉冲压缩,只开 MTD。这样定位问题的时候,可以快速缩小范围。这个调试模式在最终版本里可以保留,不影响正常运行,但调试的时候能省很多时间。

5.2 资源优化与时序收敛

FPGA 资源优化是个永恒的话题。PLFM_RADAR 里最耗资源的是 FFT IP 核和 DDR 控制器。FFT 核可以用流水线模式(Streaming)或突发模式(Burst)。流水线模式吞吐率高,但资源消耗大;突发模式资源省,但需要额外的缓存。我一般用突发模式,因为雷达数据是突发的,不是连续的,突发模式够用了。

时序收敛方面,高速接口(ADC、DDR)的时序约束要仔细写。ADC 的源同步接口要用 set_input_delay 约束,DDR 要用 set_output_delay 和 set_input_delay,还要加 false path 或 multicycle path。我一般先用保守约束跑通,再逐步收紧,看时序报告里的 slack。如果 slack 是负的,先看是不是约束写错了,再考虑优化逻辑或降频。

STM32 这边的优化主要是中断响应和 DMA 配置。雷达数据流是高速的,中断太频繁会拖垮 CPU。我一般用 DMA 搬运数据,中断只在 DMA 传输完成时触发一次。USB 传输也用 DMA,减少 CPU 干预。这样 STM32 的 CPU 占用率能控制在 30% 以下,留出余量做其他事。

5.3 实测性能与改进方向

实测下来,这套系统在 10 米距离上能检测到角反射器,信噪比约 25dB,距离分辨率约 7.5 米,速度分辨率约 0.12m/s。脉冲压缩旁瓣约 -32dB,MTD 后的多普勒谱能清楚看到目标峰值。这个性能对于低成本原型来说,我觉得可以接受。

改进方向有几个。一是提高带宽到 50MHz,距离分辨率能到 3 米,但 ADC 和 DDR 都要升级。二是加通道,做真正的相控阵,这需要多路 ADC 和多路发射,FPGA 资源要翻倍。三是把信号处理算法从 FPGA 搬到 SoC(比如 Zynq 或 Cyclone V SoC),用 ARM 做控制,FPGA 做加速,集成度更高。四是加跟踪算法,在检测到目标后,用卡尔曼滤波做轨迹跟踪,这需要在 STM32 或上位机里实现。

我个人觉得,PLFM_RADAR 这个项目的价值不在于性能多高,而在于它把雷达信号链的每个环节都跑通了。你在这个项目里踩过的坑、调过的参数、写过的接口,在更复杂的雷达系统里都会用到。我后来做相控阵项目的时候,很多调试方法和代码模块都是直接从 PLFM_RADAR 里搬过来的,省了很多事。

最后分享一个小技巧:雷达实验一定要在合规的场地做,注意发射功率和频率要符合当地规定。调试的时候先用电缆连接,确认信号链无误后再接天线。接天线的时候,人不要站在天线正前方,微波辐射虽然功率不大,但长时间近距离照射还是不好的。这些细节看起来不起眼,但养成习惯后,做项目会顺利很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询