☰
FMCW雷达MATLAB实战:从拍频信号到距离-多普勒谱与CFAR检测
2026/10/27 23:45:27 网站建设 项目流程

简介:这份资料面向雷达系统设计、信号处理方向的学习者与工程师,围绕FMCW(调频连续波)雷达的测距、测速与角度估计原理,提供从理论到MATLAB实现的完整参考。内容涵盖线性调频信号生成、回波接收与加噪、混频、FFT频差谱分析以及距离速度估计等关键环节,并配有算法解释与理论背景说明,适合希望深入理解雷达工作机制并动手验证的读者。资源包共16个文件,约7.95MB,以m脚本、wsv波形数据、pdf文档为主,另含mdl仿真模型、pptx演示与zip子包,脚本可直接运行,波形数据便于复现实验场景,文档则补充原理推导与参数说明。目前已有3462人学习下载,可作为课程设计、科研入门或工程原型的实践素材,帮助读者在MATLAB环境中直观验证FMCW雷达信号处理流程,积累调参与排错经验。

1. FMCW 雷达设计代码:从一段拍频信号到能跑的距离-速度谱

很多人第一次拿到 FMCW 雷达的原始数据,看到的就是一坨复数采样点,既没有距离也没有速度,完全不知道从哪下手。这个标题要解决的就是这件事:用 MATLAB 把 FMCW 雷达从波形参数设计、信号生成、混频、采样,一路做到距离维 FFT、速度维 FFT,最后得到一张能读出目标距离和速度的距离-多普勒谱。它适合两类人:一类是刚接触毫米波雷达、想先把信号链跑通的嵌入式或算法新手;另一类是手里已经有 AWR2243 这类雷达板、想把采集到的数据在 MATLAB 里验证一遍的工程师。核心链路其实就四步——发射调频连续波、接收回波、混频得到拍频、对拍频做二维 FFT。把这四步在 MATLAB 里写清楚,后面加 CFAR、加角度维、加稀疏阵列天线都是在这个骨架上长出来的。

2. FMCW 波形参数怎么定:距离分辨率、最大距离与速度模糊

2.1 先搞懂三个公式,参数才不会瞎设

FMCW 雷达的一切参数都围绕三个量转:带宽 B、调频斜率 S、一帧内的 chirp 数。距离分辨率由带宽决定,ΔR = c / (2B),c 是光速。想要 4 cm 的分辨率,带宽就得给到约 3.75 GHz,这就是为什么毫米波雷达带宽都很大。最大不模糊距离由采样率决定,R_max = Fs * c / (2S),采样率越高、斜率越低,能测的距离越远。速度这边,最大不模糊速度由 chirp 周期决定,v_max = λ / (4 * Tc),λ 是波长,Tc 是单个 chirp 的周期。这三个公式决定了你不可能同时要超远距离、超高分辨率和超大速度范围,必须按场景取舍。

我一般会先确定场景:如果是车载前向雷达,关注 100~200 m 和 ±60 m/s;如果是室内手势识别,关注 1~5 m 和 ±2 m/s。场景定了,再反推参数。下面这张表是我常用的两组起点参数,可以直接改。

参数车载前向室内手势
载频 fc77 GHz60 GHz
带宽 B1 GHz4 GHz
调频斜率 S30 MHz/us60 MHz/us
采样率 Fs10 MHz20 MHz
chirp 周期 Tc60 us40 us
每帧 chirp 数12864
距离分辨率15 cm3.75 cm
最大距离50 m25 m
最大速度±19.5 m/s±31 m/s

提示:上表的最大距离是按采样率算的理论值,实际还要看发射功率和天线增益,别拿理论值当探测能力。

2.2 用 MATLAB 生成一帧原始拍频信号

参数定完,先在 MATLAB 里把信号造出来,验证链路对不对。下面这段代码生成两个目标,一个在 10 m 处以 5 m/s 靠近,一个在 25 m 处以 3 m/s 远离,输出一帧的拍频采样矩阵。

% FMCW 一帧拍频信号生成 c = 3e8; fc = 77e9; % 载频 B = 1e9; % 带宽 S = 30e6/1e-6; % 调频斜率 30 MHz/us Fs = 10e6; % 采样率 Tc = 60e-6; % 单 chirp 周期 Nc = 128; % 每帧 chirp 数 Ns = round(Tc * Fs); % 每 chirp 采样点数 lambda = c / fc; t = (0:Ns-1) / Fs; % 单 chirp 内采样时间轴 % 目标:[距离(m), 径向速度(m/s)],正速度表示远离 targets = [10, -5; 25, 3]; beat = zeros(Ns, Nc); for k = 1:Nc for i = 1:size(targets,1) R = targets(i,1); v = targets(i,2); tau = 2 * R / c; % 往返时延 fb = S * tau; % 拍频 fd = 2 * v / lambda; % 多普勒频率 beat(:,k) = beat(:,k) + ... exp(1j*2*pi*(fb*t + fd*(k-1)*Tc)); end end beat = beat + 0.01*(randn(size(beat)) + 1j*randn(size(beat))); % 加噪

逻辑说明:外层循环遍历 chirp,内层循环叠加每个目标的回波。拍频fb = S * tau是距离信息的载体,多普勒项fd * (k-1) * Tc是慢时间维的相位变化,两者叠加后就是完整的拍频信号。最后加 1% 的复高斯噪声,模拟真实接收机底噪。

参数说明:Ns由Tc * Fs决定,必须保证采样窗口覆盖整个 chirp 周期,否则会截断。targets里速度的正负号要和后面 FFT 的符号约定一致,我习惯正速度表示远离,这样距离-多普勒谱里正速度在上半平面,读图不容易搞反。

3. 距离维与速度维 FFT:把拍频矩阵变成距离-多普勒谱

3.1 距离维 FFT 的加窗与补零

拿到beat矩阵后,第一件事是沿快时间维(每列)做 FFT,得到距离谱。直接 FFT 会有频谱泄漏,因为目标拍频不一定落在整数 bin 上。我一般加汉明窗压制旁瓣,再补零到 2 的幂次,让峰值位置更细。

Nfft_r = 2^nextpow2(Ns * 4); % 距离维补零到 4 倍 win_r = hamming(Ns); range_fft = fft(beat .* win_r, Nfft_r, 1); % 距离轴 f_beat = (0:Nfft_r-1) * Fs / Nfft_r; range_axis = f_beat * c / (2 * S);

逻辑说明:beat .* win_r是逐列加窗,MATLAB 会自动广播。fft(..., 1)指定沿第 1 维做 FFT,也就是快时间维。补零到 4 倍采样点数,等效于在频域插值,峰值定位更准,但不会提高真实分辨率——分辨率还是由带宽 B 决定,补零只是让谱看起来更细。

参数说明:Nfft_r取 2 的幂次是为了 FFT 效率。range_axis的换算用f_beat * c / (2S),注意这里f_beat是拍频,不是射频。如果发现距离轴最大值超过R_max,说明补零补多了,把无意义的区域也画进来了,截到R_max以内即可。

3.2 速度维 FFT 与多普勒轴对齐

距离维做完,沿慢时间维(每行)再做一次 FFT,就得到速度。这里有个坑:速度维 FFT 之前要做 fftshift,否则零速度不在中心,读图很别扭。

Nfft_d = 2^nextpow2(Nc * 4); win_d = hamming(Nc).'; rd_map = fft(range_fft .* win_d, Nfft_d, 2); rd_map = fftshift(rd_map, 2); % 多普勒轴 f_d = (-Nfft_d/2 : Nfft_d/2-1) * (1 / (Nc * Tc)) / Nfft_d; vel_axis = f_d * lambda / 2;

逻辑说明:range_fft .* win_d是逐行加窗,fft(..., 2)沿第 2 维做 FFT。fftshift(..., 2)把零频搬到中心。多普勒频率f_d的间隔是1 / (Nc * Tc),也就是一帧总时长的倒数,这是慢时间维的采样率。

参数说明:vel_axis用f_d * lambda / 2换算成速度。注意符号:如果前面生成信号时正速度表示远离,这里正速度应该出现在vel_axis的正半轴。如果发现反了,检查fftshift的方向或者生成信号时的符号约定,两者必须一致。

3.3 把距离-多普勒谱画出来并验证峰值

figure; imagesc(vel_axis, range_axis(1:Nfft_r/2), ... 20*log10(abs(rd_map(1:Nfft_r/2, :)))); xlabel('速度 (m/s)'); ylabel('距离 (m)'); title('距离-多普勒谱'); colorbar; axis xy;

逻辑说明:只画前半段距离轴,因为实信号 FFT 后另一半是镜像。20*log10(abs(...))转 dB,动态范围看得更清楚。axis xy让距离轴从下往上增,符合直觉。

跑完这段,你应该在 10 m、-5 m/s 和 25 m、+3 m/s 附近看到两个亮斑。如果只有一个斑,检查两个目标的拍频是否落在同一个距离 bin 里;如果斑的位置偏了,回头核对S和Fs的单位,这是最常见的翻车点。

4. 避坑与排查:FMCW 信号处理里最容易翻车的 5 个地方

4.1 距离轴整体偏移一个固定值

现象:所有目标的距离读数都比真实值大或小一个固定量。原因:拍频公式里漏掉了收发切换时延或者天线馈线时延,也可能是S的实际值和设定值有偏差。解决:用一个已知距离的角反射器做单点校准,把偏移量减掉;同时核对雷达手册里S的实际精度,很多芯片的斜率有 ±1% 的误差。

4.2 速度符号反了

现象:靠近的目标显示成正速度,远离的显示成负速度。原因:生成信号时多普勒项写成exp(-1j*2*pi*fd*...),而 FFT 后又没做共轭或者 fftshift 方向不对。解决:统一约定——正速度表示远离,多普勒频率fd = 2v/lambda,慢时间维相位随 chirp 递增。改完生成端和解析端要同时改,只改一头会更乱。

4.3 距离-多普勒谱里出现对称的假目标

现象:真实目标旁边出现一个镜像,速度符号相反。原因:拍频信号是实数采样后转复数,或者 I/Q 不平衡导致负频抑制不够。解决:检查接收链路是不是真的复采样;如果是实采样,做希尔伯特变换后再进 FFT。I/Q 不平衡的话,在 MATLAB 里做一次简单的相位和幅度校正。

4.4 补零后分辨率没变但峰值分裂

现象:补零到很高倍数后,一个目标变成两个相邻的峰。原因:补零只是插值,如果窗函数主瓣很宽,插值后会把主瓣的起伏显示出来。解决:换旁瓣更低的窗,比如凯泽窗,或者降低补零倍数。补零不是越多越好,4 倍足够。

4.5 多目标情况下弱目标被强目标旁瓣淹没

现象:近处强目标的旁瓣盖住了远处弱目标。原因:没加窗或者窗的旁瓣抑制不够。解决:距离维和速度维都加汉明窗或布莱克曼窗,代价是主瓣变宽、分辨率略降。如果动态范围要求很高,用切比雪夫窗,旁瓣可以压到 -60 dB 以下,但主瓣会明显变宽。

5. 进阶技巧:用 CFAR 做自适应检测并验证检测门限

谱画出来只是第一步,真正要自动读出目标,得加 CFAR。我一般用单元平均 CFAR(CA-CFAR),在距离-多普勒谱上滑窗,用参考单元估计噪声功率,再乘一个门限因子。下面这段代码在距离维做一维 CA-CFAR,速度维可以照搬。

function det = ca_cfar_1d(power_spectrum, guard, ref, pfa) N = length(power_spectrum); det = zeros(size(power_spectrum)); alpha = ref * (pfa^(-1/ref) - 1); % 门限因子 for i = (guard+ref+1) : (N-guard-ref) lead = power_spectrum(i-guard-ref : i-guard-1); lag = power_spectrum(i+guard+1 : i+guard+ref); noise = mean([lead; lag]); if power_spectrum(i) > alpha * noise det(i) = 1; end end end

逻辑说明:guard是保护单元,防止目标能量泄漏到参考单元里抬高噪声估计;ref是参考单元数,一般取 16~32;pfa是虚警概率,常用 1e-4 到 1e-6。门限因子alpha由pfa和ref共同决定,参考单元越多,同样虚警概率下门限越低。

参数说明:guard取 2~4 就够,太大反而会让密集目标互相遮挡。ref取 16 是折中,想要更稳的噪声估计可以取 32,但计算量翻倍。pfa设 1e-4 时,一帧 128×256 的谱大概会有几个虚警点,实际用的时候再配合速度维 CFAR 做与运算,把虚警压下去。

验证方法:拿一帧只有噪声的数据跑一遍 CFAR,统计检测点数,应该接近pfa * 总单元数。如果远大于这个值,说明门限因子算错了,检查alpha公式里的ref是不是和实际参考单元数一致。这个自检习惯帮我省过很多次调试时间——先拿纯噪声验证检测器,再上真实目标。

我自己的习惯是每换一组波形参数,都先用纯噪声跑一遍 CFAR 自检,再拿一个已知距离的角反射器验证距离轴,最后才上多目标场景。这套流程看起来笨,但比在复杂场景里瞎调参数快得多。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询