FPGA+STM32相控阵雷达原型:PLFM_RADAR系统架构与脉冲压缩实现
1. 从“PLFM_RADAR”这个名字说起:它到底想做什么
第一次看到“PLFM_RADAR”这个项目名,很多人会愣一下:PLFM 是什么?是某个芯片型号,还是某种调制方式的缩写?结合关键词里的 phased array(相控阵)、RADAR、FPGA、STM32,基本可以判断这是一个以 FPGA 做实时信号处理、STM32 做系统控制与上位机交互的相控阵雷达原型系统。PLFM 大概率是 Pulse Linear Frequency Modulation 的缩写,也就是脉冲线性调频——雷达领域最经典、最基础的一种波形体制。
为什么这个判断比较靠谱?因为相控阵雷达的核心链路就是“波形产生 → 发射 → 接收 → 下变频 → ADC 采样 → 数字下变频/脉冲压缩 → 目标检测 → 显控”。其中脉冲压缩这一步计算量极大,必须靠 FPGA 并行流水线来做;而波束调度、时序控制、参数配置、串口/USB 上报这些“慢逻辑”,交给 STM32 反而更省事、更灵活。所以“FPGA + STM32”这个组合在雷达原型里几乎是标配,不是随便凑的。
这篇文章适合谁看?如果你正在做雷达相关的毕业设计、嵌入式竞赛、实验室预研项目,或者你手上有 FPGA 和 STM32 两块板子但不知道怎么把它们串成一个完整系统,那这篇内容会对你有直接帮助。我会把 PLFM_RADAR 这类项目的整体架构、关键模块、参数计算、调试踩坑都拆开讲清楚,尽量让你看完就能动手复现。
需要先说明一点:项目正文和关键词都是空的,所以下面的内容是基于标题、热搜词以及这类系统的通用工程实践做的合理补全。凡是补全的部分,我都会明确标注“这是常见做法”,你可以根据自己的硬件条件调整。
2. 系统架构怎么切:FPGA 和 STM32 的职责边界
2.1 为什么不让一颗芯片全包
新手最容易犯的错,是想用 STM32 一颗芯片把雷达信号处理全干了。理论上不是不行,但实际会撞墙。脉冲压缩本质是卷积运算,假设一个脉冲周期采样 1024 点,匹配滤波器长度 256 点,那一次脉冲压缩就是 1024×256 ≈ 26 万次乘加。雷达每秒要发几百到几千个脉冲,算下来每秒几亿次乘加,STM32 的 Cortex-M 内核根本扛不住,就算用 DSP 指令也够呛。
FPGA 的优势在于并行。它可以把 256 个乘法器同时铺开,一个时钟周期算 256 次乘加,200MHz 时钟下就是每秒 512 亿次乘加,轻松覆盖需求。而且 FPGA 的流水线延迟是确定的,这对雷达这种强实时系统非常关键——你不能这一帧数据算了 10ms、下一帧算了 15ms,那样时序全乱。
那 STM32 干什么?它负责“人机接口”和“系统调度”:接收上位机指令、配置 FPGA 的寄存器(比如脉冲宽度、PRF、波束指向)、管理 T/R 组件的开关时序、采集温度/电压等慢变量、通过 USB 或串口把目标信息上报。这些任务对算力要求不高,但对灵活性和开发效率要求高,用 C 语言写 STM32 比写 Verilog 快得多。
2.2 两块芯片之间怎么通信
FPGA 和 STM32 之间的接口,常见有三种选择,我列个表对比一下:
| 接口方式 | 速率 | 引脚数 | 适用场景 | 坑点 |
|---|---|---|---|---|
| SPI | 10~50 Mbps | 4 | 寄存器配置、低速数据 | 全双工但带宽有限,长距离易受干扰 |
| FSMC/并口 | 50~200 Mbps | 20+ | 大批量数据搬运 | 引脚多,PCB 布线麻烦 |
| 双口 RAM | 取决于时钟 | 30+ | 高速共享缓存 | 成本高,一般原型用不上 |
对于 PLFM_RADAR 这种原型,我建议配置通道走 SPI,数据通道走 FSMC 或自定义并口。配置通道数据量小但要求可靠,SPI 足够;数据通道要传目标点迹或原始采样,带宽需求大,并口更合适。如果只是验证算法,甚至可以让 FPGA 先把结果存进片内 BRAM,STM32 通过 SPI 慢慢读,速度慢但能跑通。
提示:SPI 做跨芯片通信时,一定要确认两边的时钟极性(CPOL)和相位(CPHA)一致,我见过太多人卡在这里,波形看着对但数据就是错位。
2.3 一个容易被忽略的细节:复位和时钟同步
FPGA 和 STM32 各自有复位电路,但系统上电时两者的启动时间不一样。STM32 从复位到跑 main 函数大概几十毫秒,FPGA 从配置完成到进入工作状态可能要几百毫秒甚至更久。如果 STM32 一上电就急着给 FPGA 发配置,很可能 FPGA 还没准备好,配置全丢了。
常见做法是:STM32 先拉高一个 GPIO 作为“FPGA 就绪”检测线,FPGA 配置完成后把这个脚拉低(或拉高,看约定),STM32 检测到之后再开始初始化。这个握手机制看起来简单,但能省掉大量“为什么上电后系统不工作”的调试时间。
3. 波形产生与发射链路:PLFM 信号是怎么造出来的
3.1 线性调频信号的数学本质
脉冲线性调频信号,说白了就是频率随时间线性变化的信号。它的表达式是:
s(t) = exp(j·2π·(f0·t + 0.5·K·t²)), 0 ≤ t ≤ T其中 f0 是起始频率,K = B/T 是调频斜率,B 是带宽,T 是脉冲宽度。带宽决定了距离分辨率(ΔR = c/2B),脉冲宽度决定了能量。这两个参数是雷达设计的核心,直接决定你能看多远、看多清。
举个例子:如果 B = 10MHz,那距离分辨率 ΔR = 3e8/(2×10e6) = 15 米。想要 1 米分辨率,带宽得做到 150MHz。这就是为什么雷达都拼命往大带宽走。
3.2 FPGA 里怎么生成 LFM 波形
生成方式主要有两种:DDS 直接合成和查表法。
DDS 的做法是用一个相位累加器,每个时钟周期累加一个频率控制字,累加器的输出作为相位去查正弦表。要生成 LFM,只需要让频率控制字随时间线性增加即可。这种方式的优点是频率切换快、相位连续,缺点是控制逻辑稍复杂。
查表法是提前把整个 LFM 波形算好存进 ROM,发射时按顺序读出。优点是简单,缺点是波形固定,改参数要重新生成 ROM。
对于 PLFM_RADAR 原型,我推荐DDS 方式,因为雷达经常需要改波形参数做对比实验,DDS 改起来只是改几个寄存器值,查表法就得重新综合,太慢。
具体实现时,相位累加器位宽一般取 32 位,取高 12~14 位去查正弦表。正弦表用 Block RAM 实现,深度 4096 或 8192 就够。频率控制字 Δφ 的计算公式是:
Δφ = f_out × 2^N / f_clk其中 N 是累加器位宽,f_clk 是系统时钟。比如要输出 10MHz 信号,系统时钟 200MHz,N=32,那 Δφ = 10e6 × 2^32 / 200e6 ≈ 214748364,约等于 2^31/10。
3.3 DAC 选型和输出调理
FPGA 输出的是数字信号,要变成射频还得经过 DAC 和上变频。原型阶段常用的是高速 DAC + 直接上变频,或者DAC 输出中频 + 混频器。
DAC 选型看两个指标:更新率和位数。LFM 带宽 10MHz,按奈奎斯特至少要 20MSPS,实际工程上取 4~5 倍余量,所以 100MSPS 以上的 DAC 比较稳妥。位数方面,12 位是底线,14~16 位更好,因为位数直接决定信号的杂散水平。
输出调理电路要注意抗混叠滤波。DAC 输出会有镜像频率,如果不在 DAC 后面加低通滤波器,镜像会混进发射信号,污染频谱。滤波器截止频率设在 DAC 更新率的一半略低的位置。
注意:DAC 的输出幅度通常不够驱动后级混频器,中间要加一级放大器。选放大器时注意它的 1dB 压缩点和三阶交调点,别让放大器本身产生非线性失真,那样再好的 DAC 也白搭。
4. 接收链路与 ADC 采样:把微弱回波捞出来
4.1 接收前端的基本组成
接收链路从天线开始,依次是:限幅器 → 低噪放(LNA)→ 混频器 → 中频滤波 → 中频放大 → ADC。限幅器是为了保护 LNA 不被强信号烧掉,LNA 决定了整个接收机的噪声系数,混频器把射频搬到中频,中频滤波和放大把信号调理到 ADC 合适的输入范围。
噪声系数是接收机的核心指标。整个链路的噪声系数主要由第一级 LNA 决定,所以 LNA 要选噪声系数尽量低的,同时增益要够,把后级的噪声贡献压下去。级联噪声系数的公式是 Friis 公式:
F_total = F1 + (F2-1)/G1 + (F3-1)/(G1·G2) + ...从公式能看出来,第一级的噪声系数 F1 直接加到总和上,而第二级的贡献被 G1 除掉了。所以 LNA 的增益 G1 越大,后级影响越小。但增益也不能无限大,否则会压缩后级动态范围。
4.2 ADC 采样率与位数的权衡
ADC 选型是接收链路的关键决策。采样率决定了能处理的最大带宽,位数决定了动态范围。
对于 PLFM_RADAR,如果中频是 30MHz,带宽 10MHz,那采样率至少要 80MSPS(带通采样可以更低,但原型阶段建议用奈奎斯特采样,简单可靠)。位数方面,12 位能提供约 72dB 的动态范围,14 位约 84dB,16 位约 96dB。雷达回波动态范围很大,近处强目标可能比远处弱目标强 60dB 以上,所以 14 位是比较合理的选择。
采样时钟的抖动是个隐形杀手。时钟抖动会直接恶化 ADC 的信噪比,公式是:
SNR_jitter = -20·log10(2π·f_in·t_jitter)假设输入信号 30MHz,时钟抖动 1ps,那 SNR 约 74dB。如果抖动涨到 10ps,SNR 掉到 54dB,直接损失 20dB。所以 ADC 的采样时钟一定要用低抖动的晶振或时钟芯片,别随便拿 FPGA 的普通 IO 分频凑合。
4.3 FPGA 侧的数据接收
ADC 输出通常是 LVDS 或 CMOS 电平。高速 ADC 基本都用 LVDS,因为抗干扰能力强、速率高。FPGA 接收 LVDS 要用专门的差分输入引脚,并且要做源同步时序约束。
这里有个大坑:LVDS 数据的建立保持时间。ADC 输出的数据和随路时钟之间有固定的相位关系,FPGA 内部要用 IDELAY 或 IDELAYCTRL 调整延迟,让采样点落在数据眼图中央。Xilinx 的 FPGA 有 IDELAYE2 原语,Altera 的对应是 LVDS 接收器里的相位调整。不做这一步,数据误码率会很高,而且温度一变就出错。
接收到的数据要先做数字下变频(DDC),把中频信号搬到基带。DDC 的核心是数字混频器加低通滤波,混频用 NCO 产生正交本振,和输入信号相乘得到 I/Q 两路。低通滤波用 CIC 滤波器加补偿 FIR 实现,CIC 负责大比例抽取,FIR 负责补偿 CIC 的幅频响应下垂。
5. 脉冲压缩:雷达信号处理的心脏
5.1 匹配滤波器的原理
脉冲压缩的本质是匹配滤波。发射的是宽脉冲 LFM,回波也是宽脉冲,直接检测的话距离分辨率很差。匹配滤波器的作用是把宽脉冲压缩成窄脉冲,压缩后的脉冲宽度约等于 1/B,这样既保留了宽脉冲的能量,又获得了窄脉冲的分辨率。
匹配滤波器的冲激响应是发射信号的共轭翻转。对于 LFM 信号,匹配滤波在频域上等价于乘以一个共轭的频域参考函数。所以工程上通常用频域脉冲压缩:把回波做 FFT,乘以参考信号的共轭 FFT,再做 IFFT。
5.2 FPGA 实现脉冲压缩的几种方案
方案一:时域卷积。直接用 FIR 滤波器结构,把匹配滤波器的系数作为 FIR 系数。优点是结构简单,缺点是系数太长时资源消耗大。256 阶的复数 FIR 需要 256 个复数乘法器,资源紧张。
方案二:频域处理。用 FFT IP 核做正变换和逆变换,中间做复数乘法。优点是计算量小(N log N 对比 N²),缺点是 FFT IP 核有延迟,且需要额外的缓存。对于 1024 点 FFT,资源消耗比 256 阶时域卷积小得多。
方案三:分段卷积。把长序列拆成短段,用重叠保留法或重叠相加法处理。适合系数特别长的情况。
对于 PLFM_RADAR 原型,我推荐频域方案。Xilinx 和 Altera 都有现成的 FFT IP 核,配置好点数、数据位宽、流水线模式就能用。注意 FFT 的定点位宽要算清楚,中间级容易溢出,一般每级加 1~2 位保护位。
5.3 定点位宽的计算
定点位宽是 FPGA 信号处理最容易翻车的地方。位宽给少了溢出,给多了浪费资源。以 1024 点 FFT 为例,输入 12 位,第一级蝶形运算后幅度可能翻倍,所以要加 1 位。1024 点需要 10 级,理论上要加 10 位,但实际信号不会每级都满幅,通常加 5~6 位保护位就够。
具体做法是:先用 MATLAB 或 Python 做定点仿真,把整个处理链路的位宽和截位方式确定下来,再写 Verilog。直接上手写 RTL 然后发现溢出,回头改起来非常痛苦。
提示:FFT 输出后的复数乘法,参考信号的共轭也要做定点化。参考信号的动态范围可能很大,建议先归一化再定点,否则乘法结果位宽爆炸。
6. 波束控制与相控阵时序:让天线“指哪打哪”
6.1 相控阵的基本原理
相控阵天线由多个阵元组成,每个阵元的发射/接收相位可以独立控制。通过调整相邻阵元的相位差,可以让波束在空间扫描。相位差 Δφ 和波束指向角 θ 的关系是:
Δφ = 2π·d·sin(θ)/λ其中 d 是阵元间距,λ 是波长。通常 d 取 λ/2,这样可以避免栅瓣。
6.2 波束控制的实现方式
原型阶段,波束控制通常用移相器实现。每个阵元后面接一个数字移相器,FPGA 通过 SPI 或并口给移相器写相位值。移相器的位数决定了相位量化精度,6 位移相器有 64 个相位状态,量化误差约 2.8°,对原型够用。
如果要做的更灵活,可以用数字波束形成(DBF),每个阵元单独接收、单独 ADC、在数字域加权求和。这种方式灵活性最高,但硬件成本也最高,N 个阵元就要 N 路接收链路。原型阶段一般先用移相器方案验证算法,再考虑 DBF。
6.3 发射/接收时序的精确控制
雷达时序是强实时的,发射脉冲、切换收发开关、启动 ADC 采样、触发信号处理,这些动作之间的时间关系必须精确到纳秒级。FPGA 在这方面有天然优势,用一个高精度计数器就能产生所有时序信号。
典型时序是:PRF 周期开始 → 发射脉冲(宽度 T)→ 等待保护时间 → 打开接收开关 → ADC 采样(采样窗长度对应最大作用距离)→ 关闭接收 → 启动信号处理 → 等待下一个 PRF。
保护时间是为了让收发开关完成切换,避免发射信号泄漏进接收机。这个时间通常几百纳秒到几微秒,取决于开关速度。
注意:收发开关的切换时间要留足余量。我见过一个项目,保护时间设得太短,发射脉冲尾部漏进接收机,把 LNA 给饱和了,整个接收窗的数据全废。
7. STM32 侧的系统控制与上位机交互
7.1 STM32 要管哪些事
STM32 在 PLFM_RADAR 里的角色是“大管家”,具体包括:
- 接收上位机指令,解析后配置 FPGA 寄存器
- 管理 T/R 组件的电源和开关时序
- 采集系统温度、电压、电流等状态量
- 把 FPGA 处理后的目标点迹打包上报
- 处理异常情况,比如过温、过流保护
这些任务的特点是实时性要求不高,但逻辑复杂,正好适合 STM32。
7.2 USB 设备开发的关键点
热搜词里有“stm32 如何做 usb 设备”,这确实是很多人的痛点。STM32 的 USB 外设分 Full Speed(12Mbps)和 High Speed(480Mbps),原型阶段用 Full Speed 的 CDC 类做虚拟串口最方便,免驱,上位机直接当串口用。
配置 USB CDC 的步骤:
- 用 CubeMX 使能 USB Device,选择 CDC 类
- 配置时钟,USB 需要 48MHz 时钟,注意时钟树别配错
- 生成代码后,在
CDC_Receive_FS回调里处理接收数据 - 发送数据用
CDC_Transmit_FS,注意这个函数是非阻塞的,要检查返回值
常见的坑是USB 时钟配置错误。STM32 的 USB 外设要求 48MHz ±0.25% 的时钟精度,如果用的是内部 RC 振荡器,精度不够,USB 枚举会失败。必须用外部晶振,并且通过 PLL 倍频到 48MHz。
7.3 上位机通信协议设计
FPGA 处理完一帧数据后,STM32 要把结果上报。协议设计要考虑帧同步、数据校验、流量控制。
一个简单的协议格式:
帧头(2字节) + 长度(2字节) + 命令字(1字节) + 数据(N字节) + CRC16(2字节)帧头用固定的 0xAA55 或类似值,接收方靠帧头做同步。长度字段告诉接收方这帧有多少数据。CRC16 做校验,防止传输错误。流量控制可以用简单的应答机制,STM32 发一帧等上位机回 ACK 再发下一帧。
如果数据量大,比如要传原始 ADC 采样,那 USB CDC 的带宽可能不够。这时候可以考虑USB 自定义类 + 批量传输,或者用以太网。STM32F4/F7/H7 系列有以太网 MAC,跑 UDP 能到几十 Mbps,比 USB CDC 快得多。
8. 调试与联调:那些文档里不会写的坑
8.1 FPGA 和 STM32 联调的顺序
联调最忌讳一上来就全系统跑。正确的顺序是:
- 单独验证 FPGA:用 SignalTap 或 ILA 抓内部信号,确认波形产生、ADC 接收、脉冲压缩各模块单独工作正常
- 单独验证 STM32:用串口打印调试信息,确认 USB 通信、寄存器配置正常
- 验证通信接口:STM32 发固定数据,FPGA 回环,确认 SPI/并口通信无误
- 小环路联调:FPGA 产生简单信号,STM32 读取并上报,确认数据通路
- 全系统联调:接入射频前端,实际发射接收
每一步都要有明确的验证标准,别跳步。
8.2 常见问题排查表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| FPGA 配置失败 | 配置时钟不稳、配置文件损坏 | 检查配置时钟频率,重新生成比特流 |
| ADC 数据全零 | 采样时钟没接、LVDS 相位不对 | 用示波器看时钟,调整 IDELAY |
| 脉冲压缩结果异常 | 定点溢出、参考信号不匹配 | 用 MATLAB 对比定点仿真和 RTL 结果 |
| USB 枚举失败 | 时钟精度不够、描述符错误 | 换外部晶振,用 USB 分析仪抓包 |
| 通信误码率高 | 时序不满足、干扰 | 加时序约束,检查 PCB 布线 |
| 波束指向偏差大 | 相位计算错误、移相器校准 | 重新推导相位公式,校准移相器 |
8.3 我踩过的几个坑
坑一:FPGA 的复位信号。热搜词里有“fpga有固定的复位脚吗”,答案是没有。FPGA 的复位是设计出来的,不是芯片自带的。我一开始以为某个引脚是复位脚,结果发现它只是普通 IO。正确的做法是用一个全局复位信号,通过时钟同步后分发到各个模块。
坑二:STM32 的延时函数卡死。热搜词里有“stm32延时函数delay卡死”,这通常是因为中断优先级配置不当,或者延时函数里关了中断但没恢复。用 SysTick 做延时时,注意不要在中断里调用长延时。
坑三:Testbench 写得太简单。热搜词里有“fpga如何正确写testbench”,我的经验是:Testbench 要模拟真实时序,包括时钟抖动、复位释放、数据延迟。只给理想激励的 Testbench 测不出时序问题。
坑四:跨时钟域没做同步。FPGA 里多个时钟域是常态,ADC 采样时钟、系统时钟、通信时钟往往不同。跨时钟域的信号必须做同步处理,单比特用两级触发器,多比特用异步 FIFO 或握手协议。不做同步,亚稳态会让你怀疑人生。
9. 从原型到可用系统:还需要补哪些课
原型跑通只是第一步,要变成真正可用的系统,还有几件事要做。
第一是校准。相控阵的每个通道幅度相位都有差异,不校准的话波束会畸变。校准方法有内校准和外校准,内校准用耦合器把发射信号耦合回接收通道,外校准用远场标准源。校准数据存进 Flash,上电时加载。
第二是散热。FPGA 和 ADC 都是发热大户,相控阵的 T/R 组件更是发热集中。原型阶段可以用散热片加风扇,产品化要考虑导热结构。
第三是电磁兼容。雷达系统自己发射强信号,又接收微弱信号,EMC 问题很突出。PCB 要做分区布局,数字地和模拟地分开,射频走线要阻抗匹配和屏蔽。
第四是软件框架。原型阶段的代码往往是“能跑就行”,产品化要重构。FPGA 侧要模块化、参数化,STM32 侧要用 RTOS 管理任务,上位机要有完整的日志和异常处理。
这些内容每一项都能单独写一篇文章,这里只是点一下方向。如果你正在做 PLFM_RADAR 这类项目,建议先把核心链路跑通,再逐步补这些工程化的内容。毕竟雷达系统太复杂,想一口吃成胖子不现实。
我个人在实际操作中的体会是:雷达项目的难点不在单个模块,而在系统联调。每个模块单独测都正常,连起来就是不出结果,这时候要有耐心,一个环节一个环节地隔离排查。用示波器、逻辑分析仪、SignalTap 这些工具把信号抓出来看,比盯着代码空想有效得多。