基于 MATLAB 的 2×2 MIMO-OFDM ISAC 收发机设计与实现(含雷达距离-多普勒处理)
一个自包含的仿真工程:同一套 OFDM numerology 下同时实现 2×2 空分复用通信链路与 2×2 时分 MIMO 单基地雷达探测,输出 BER / EVM 与距离-多普勒图。全部使用 base MATLAB,无需任何工具箱。
〇、运行环境
软件 : MATLAB R2020b 或更高(base MATLAB,无需 Communications/Phased Array 等工具箱)
脚本文件 : isac_mimo_ofdm_transceiver.m(单文件,约 200 行)
输出 : isac_mimo_ofdm_results.png(四子图结果)
随机种子 : rng(17, 'twister')(可复现)
脚本结构:
① 系统配置
② 通信帧与 QPSK 发射流
③ 频选 MIMO 通信信道
④ 通信接收:CP 去除 → FFT → 导频 LS 估计 → MMSE 均衡
⑤ ISAC 感知突发:TDM-MIMO OFDM 雷达波形
⑥ 雷达接收:信道除法 → 距离 IFFT → 多普勒 FFT → 通道合并
⑦ 结果绘图与导出
⑧ 局部函数(调制/解调/OFDM/信道/回波)
一、系统配置
matlab
clear; clc; close all;
rng(17, 'twister'); % 固定随机种子,保证结果可复现
c = 299792458;
fc = 5.9e9; % 载频 [Hz],λ ≈ 5.08 cm
lambda = c/fc;
Nt = 2; Nr = 2; % 2 发 2 收
Nfft = 64;
subcarrierSpacing = 15e3; % 子载波间隔 [Hz]
Fs = Nfft*subcarrierSpacing; % 采样率 = 960 kHz
Ncp = 16; % 循环前缀(采样点数)
Tsym = (Nfft + Ncp)/Fs; % OFDM 符号长度 ≈ 83.33 μs
snrDb = 22;
由配置直接得到的雷达性能指标:
| 指标 | 公式 | 数值 |
|---|---|---|
| 总带宽 | N f f t Δ f N_{fft}\Delta f NfftΔf | 960 kHz |
| 距离采样间隔 | c / ( 2 F s ) c/(2F_s) c/(2Fs) | 156.1 m |
| 最大无模糊距离 | c / ( 2 Δ f ) c/(2\Delta f) c/(2Δf) | 10 km |
| PRI(TDM-MIMO 后) | N t T s y m N_t T_{sym} NtTsym | 166.67 μs |
| 最大无模糊速度 | λ / ( 4 ⋅ P R I ) \lambda/(4\cdot PRI) λ/(4⋅PRI) | ±76.2 m/s |
| 速度分辨率 | λ / ( 2 N p u l s e s P R I ) \lambda/(2N_{pulses}PRI) λ/(2NpulsesPRI) | 9.53 m/s |
二、通信发射端
2.1 QPSK 调制

matlab
function symbols = qpskMod(bits)
bits = bits(:);
assert(mod(numel(bits),2) == 0, 'QPSK requires an even number of bits.');
% 每 2 bit 映射为一个符号,实部/虚部取 ±1/sqrt(2),保证平均功率为 1
symbols = ((1 - 2*bits(1:2:end)) + 1j*(1 - 2*bits(2:2:end))) / sqrt(2);
end
注意:此映射不是格雷编码。对 BER 曲线的影响:高 SNR 下符号错误可能带来 2 个比特错误,而非格雷映射下通常为 1 个。与标准曲线对比时需说明。
2.2 帧结构与正交导频
matlab
NcommSym = 20;
pilotSym = 1:Nt; % 每个 Tx 占一个整带导频符号(时域正交)
dataSym = (Nt+1):NcommSym;
NdataBits = 2*Nfft*numel(dataSym)*Nt;
txBits = randi([0 1], NdataBits, 1);
txData = qpskMod(txBits);
Xcomm = zeros(Nfft, NcommSym, Nt);
for tx = 1:Nt
% 整带、恒模导频:exp(j2πk·m/Nfft),类似 DFT/Zadoff-Chu 序列
Xcomm(:, pilotSym(tx), tx) = exp(1j*2*pi*(0:Nfft-1)'*(tx+1)/Nfft);
end
Xcomm(:, dataSym, :) = reshape(txData, Nfft, numel(dataSym), Nt);
txCommWave = ofdmModulate(Xcomm, Nfft, Ncp);
设计要点:
| 设计 | 目的 |
|---|---|
| 每个 Tx 独占一个导频符号 | 时域正交,使 LS 估计解耦为逐元素除法 |
| 导频序列恒模 | 频域全子载波激励(无需插值)+ 低峰均比 |
| 导频开销 2/20 = 10% | 通信吞吐的固定代价,换取雷达相干处理能力 |
![]() |
2.3 OFDM 调制与解调
matlab
function wave = ofdmModulate(grid, Nfft, Ncp)
[~, Nsym, Nant] = size(grid);
timeNoCp = ifft(grid, Nfft, 1) * sqrt(Nfft); % 酉变换约定
timeWithCp = [timeNoCp(end-Ncp+1:end,:,:); timeNoCp]; % 加 CP
wave = reshape(timeWithCp, (Nfft+Ncp)*Nsym, Nant);
end
function grid = ofdmDemodulate(wave, Nfft, Ncp, Nsym)
Nant = size(wave,2);
assert(size(wave,1) == (Nfft+Ncp)*Nsym, 'Unexpected received frame length.');
blocks = reshape(wave, Nfft+Ncp, Nsym, Nant);
grid = fft(blocks(Ncp+1:end,:,:), Nfft, 1) / sqrt(Nfft); % 必须配对
end
关键 :ifft(...)*sqrt(Nfft) 与 fft(...)/sqrt(Nfft) 构成酉变换对,保证时/频域功率一致。两处缩放系数必须严格配对,否则 EVM 会被系统性缩放、BER 曲线整体平移。
三、通信信道与接收端
3.1 三径频选 MIMO 信道
matlab
function h = makeMimoChannel(Nr, Nt, delays, powerDb)
L = max(delays) + 1;
h = zeros(Nr, Nt, L);
for p = 1:numel(delays)
spatialTap = (randn(Nr,Nt) + 1j*randn(Nr,Nt)) / sqrt(2); % 复高斯
h(:,:,delays(p)+1) = sqrt(10^(powerDb(p)/10)) * spatialTap;
end
end
function y = applyMimoChannel(x, h)
[Nr, Nt, ~] = size(h);
Ns = size(x,1);
y = zeros(Ns, Nr);
for rx = 1:Nr
for tx = 1:Nt
response = squeeze(h(rx,tx,:));
filtered = conv(x(:,tx), response); % 线性卷积
y(:,rx) = y(:,rx) + filtered(1:Ns); % 截取前 Ns 个样本(无拖尾)
end
end
end
tapDelays = [0 3 7];
tapPowerDb = [0 -5 -10];
hComm = makeMimoChannel(Nr, Nt, tapDelays, tapPowerDb);
建模约定:
- 最大时延 7 < Ncp = 16,全部多径落在 CP 内,无 ISI/ICI;
- 第一径时延为 0,FFT 窗口定时精确,频域信道不含额外线性相位;
- 各抽头空间矩阵独立同分布复高斯,抽头间不相关(简化模型)。
conv 的长度为 Ns + L - 1,截取前 Ns 个样本等价于"只保留在 CP 保护范围内的部分",这是时域等效信道建模的标准做法。
3.2 加噪
matlab
rxCommWaveClean = applyMimoChannel(txCommWave, hComm);
signalPower = mean(abs(rxCommWaveClean(:)).^2);
noiseVariance = signalPower / 10^(snrDb/10);
% 复高斯噪声:实虚部各承担一半方差,因此乘 sqrt(noiseVariance/2)
rxCommWave = rxCommWaveClean + sqrt(noiseVariance/2) * ...
(randn(size(rxCommWaveClean)) + 1j*randn(size(rxCommWaveClean)));
这是最易出错的一行 :漏掉 1/2 会让实际 SNR 比标称高 3 dB,BER 曲线整体乐观,且从图上基本看不出来。
3.3 LS 信道估计
matlab
Ycomm = ofdmDemodulate(rxCommWave, Nfft, Ncp, NcommSym);
Hest = zeros(Nfft, Nr, Nt);
for tx = 1:Nt
for rx = 1:Nr
% 导频时域正交 → 每个导频符号只含一路 Tx 信号 → 逐元素除法即 LS 解
Hest(:, rx, tx) = Ycomm(:, pilotSym(tx), rx) ./ Xcomm(:, pilotSym(tx), tx);
end
end
3.4 逐子载波 MMSE 均衡
W M M S E = ( H H H + σ 2 I N t ) − 1 H H \mathbf{W}{MMSE} = \left(\mathbf{H}^H\mathbf{H} + \sigma^2\mathbf{I}{N_t}\right)^{-1}\mathbf{H}^H WMMSE=(HHH+σ2INt)−1HH
matlab
rxData = zeros(Nfft, numel(dataSym), Nt);
for m = 1:numel(dataSym)
symbolIndex = dataSym(m);
for k = 1:Nfft
Hk = squeeze(Hest(k, :, :)); % Nr × Nt
yk = squeeze(Ycomm(k, symbolIndex, :)); % Nr × 1
Wmmse = (Hk' * Hk + noiseVariance*eye(Nt)) \ Hk';
rxData(k, m, :) = Wmmse * yk;
end
end
工程要点:
noiseVariance必须与实际加噪方差一致。若用1/SNR硬编码,MMSE 会退化成"带错误正则项的 ZF";- 逐子载波求逆利用了 OFDM 的频率对角化特性,复杂度随 N f f t N_{fft} Nfft 线性增长;
- 当 N t > N r N_t > N_r Nt>Nr 时矩阵可能病态,建议改用
pinv或用\(MATLAB 会给出最小二乘解)。
3.5 解调与评估
matlab
function bits = qpskDemod(symbols)
symbols = symbols(:);
bits = zeros(2*numel(symbols), 1);
bits(1:2:end) = real(symbols) < 0; % 符号判决,等价于最小距离判决(QPSK)
bits(2:2:end) = imag(symbols) < 0;
end
rxBits = qpskDemod(rxData(:));
ber = mean(rxBits ~= txBits);
evmRms = sqrt(mean(abs(rxData(:) - txData).^2) / mean(abs(txData).^2));
fprintf('Communication BER = %.4g, RMS EVM = %.2f %% at %.1f dB SNR\n', ...
ber, 100*evmRms, snrDb);
EVM 定义:
E V M R M S = E ∣ s r x − s t x ∣ 2 E ∣ s t x ∣ 2 \mathrm{EVM}_{RMS} = \sqrt{\frac{\mathbb{E}\left\\left\|s_{rx}-s_{tx}\\right\|\^2\\right}{\mathbb{E}\left\\left\|s_{tx}\\right\|\^2\\right}} EVMRMS=E∣stx∣2E∣srx−stx∣2
在 22 dB 条件下的合理预期值 :BER 约 10 − 4 10^{-4} 10−4 量级、EVM 约 10%。若 BER 为 0,检查噪声是否加对(很可能噪声方差算错,或均衡器用了真实信道 hComm 而非 Hest);若 BER > 0.1,检查 QPSK 的 ± 1 / 2 \pm1/\sqrt{2} ±1/2 归一化与判决逻辑。

四、ISAC 感知突发:TDM-MIMO
matlab
NpulsesPerTx = 16;
NradSym = Nt*NpulsesPerTx; % 32 个雷达符号
Xrad = zeros(Nfft, NradSym, Nt);
for m = 1:NradSym
activeTx = mod(m-1, Nt) + 1; % 轮转激活:1,2,1,2,...
Xrad(:, m, activeTx) = qpskMod(randi([0 1], 2*Nfft, 1));
end
txRadarWave = ofdmModulate(Xrad, Nfft, Ncp);
TDM-MIMO 的两大收益与一大代价:
| 收益 | 说明 |
|---|---|
| 波形正交 | 每个符号只含一路 Tx 信号,Y/X 可直接解 |
| 虚拟阵列 | N t N r = 4 N_t N_r = 4 NtNr=4 个收发通道,等效孔径翻倍 |
| 代价 | 量化 |
|---|---|
| PRI 拉长为 N t T s y m N_t T_{sym} NtTsym = 166.67 μs | 无模糊速度 ±152 → ±76.2 m/s |
| 速度分辨率变粗 | Δ v = 9.53 \Delta v = 9.53 Δv=9.53 m/s( N p u l s e s = 16 N_{pulses}=16 Npulses=16 时) |
目标回波模型
matlab
function y = targetEcho(x, delays, dopplers, azimuthDeg, amplitudes, fc, Fs, Nt, Nr)
c = 299792458;
lambda = c/fc;
elementSpacing = lambda/2; % 半波长线阵
Ns = size(x,1);
n = (0:Ns-1)';
y = zeros(Ns, Nr);
for q = 1:numel(delays)
theta = deg2rad(azimuthDeg(q));
aTx = exp(1j*2*pi*elementSpacing/lambda*(0:Nt-1)'*sin(theta));
aRx = exp(1j*2*pi*elementSpacing/lambda*(0:Nr-1)'*sin(theta));
delayed = zeros(size(x));
delayed(delays(q)+1:end,:) = x(1:end-delays(q),:); % 整数采样时延
transmittedAtTarget = delayed * aTx; % 发射阵列响应
dopplerPhase = exp(1j*2*pi*dopplers(q)*n/Fs); % 慢时间多普勒
for rx = 1:Nr
y(:,rx) = y(:,rx) + amplitudes(q)*aRx(rx) * ...
dopplerPhase .* transmittedAtTarget;
end
end
end
虚拟阵列的数学本质 :发射侧乘 a T x a_{Tx} aTx,接收侧乘 a R x a_{Rx} aRx,级联后相位相加 ,即方向图正比于 a T x ⊗ a R x a_{Tx}\otimes a_{Rx} aTx⊗aRx 的 Kronecker 结构。
目标参数注入:
matlab
targetDelaySamples = [4 10]; % 量化到采样点,便于校验
targetRange = targetDelaySamples*c/(2*Fs); % [624.6, 1561.4] m
targetVelocity = [10 -6]; % 径向速度 [m/s]
targetDoppler = 2*targetVelocity*fc/c; % [393.3, -236.0] Hz
targetAzimuthDeg = [18 -25];
targetAmplitude = [0.85 0.45] .* exp(1j*[0.4 -1.1]);
五、雷达接收链
matlab
Yrad = ofdmDemodulate(rxRadarWave, Nfft, Ncp, NradSym);
%% ① 信道除法 + ② 距离维 IFFT
rangeCube = zeros(Nfft, NpulsesPerTx, Nr, Nt);
for tx = 1:Nt
symbolsForTx = tx:Nt:NradSym; % 关键:步长 = Nt,按激活 Tx 抽取
for rx = 1:Nr
targetResponse = Yrad(:, symbolsForTx, rx) ./ Xrad(:, symbolsForTx, tx);
rangeCube(:, :, rx, tx) = ifft(targetResponse, Nfft, 1);
end
end
%% ③ 多普勒维 FFT
rdCube = fftshift(fft(rangeCube, NpulsesPerTx, 2), 2);
%% ④ 非相干合并(跨 4 个虚拟阵元)
rdPower = squeeze(sum(sum(abs(rdCube).^2, 4), 3));
rdPowerDb = 10*log10(rdPower/max(rdPower(:)) + eps);
| 步骤 | 操作 | 物理含义 |
|---|---|---|
| ① | Y k / X k Yk/Xk Yk/Xk | 剥离已知调制符号,得到含时延/多普勒的信道 |
| ② | ifft(..., 1) |
频域 → 时延域, τ ↔ R = c τ / 2 \tau \leftrightarrow R = c\tau/2 τ↔R=cτ/2 |
| ③ | fft(..., 2) |
慢时间 → 多普勒域, f D ↔ v = f D c / ( 2 f c ) f_D \leftrightarrow v = f_D c/(2f_c) fD↔v=fDc/(2fc) |
| ④ | ∑ r x , t x ∣ ⋅ ∣ 2 \sum_{rx,tx}\vert\cdot\vert^2 ∑rx,tx∣⋅∣2 | 4 通道非相干累积,提升检测 SNR |
为什么第 ④ 步用非相干合并 :不需要已知目标角度,对相位误差鲁棒。若改用相干合并(先按阵列相位加权),理论增益为 10 log 10 ( N v a ) ≈ 6 10\log_{10}(N_{va})\approx 6 10log10(Nva)≈6 dB,但前提是先完成 DOA 估计------本文 4 元阵列的角分辨率约 30°,不足以支撑相干加权。

坐标轴与峰值检测
matlab
rangeAxis = (0:Nfft-1)' * c/(2*Fs);
PRI = Nt*Tsym; % 单个 Tx 的脉冲重复间隔
dopplerAxis = ((-NpulsesPerTx/2):(NpulsesPerTx/2-1)) / (NpulsesPerTx*PRI);
velocityAxis = dopplerAxis * c/(2*fc);
[~, peakIndex] = max(rdPower(:));
[rangeBin, velocityBin] = ind2sub(size(rdPower), peakIndex);
fprintf('Strongest sensing peak: range %.1f m, velocity %.2f m/s\n', ...
rangeAxis(rangeBin), velocityAxis(velocityBin));
三个必须记住的公式:
Δ R = c 2 F s = 156.1 m , Δ f D = 1 N p u l s e s P R I = 375 H z , Δ v = λ 2 N p u l s e s P R I = 9.53 m / s \Delta R = \frac{c}{2F_s}=156.1\,\mathrm{m},\quad \Delta f_D = \frac{1}{N_{pulses}PRI}=375\,\mathrm{Hz},\quad \Delta v = \frac{\lambda}{2N_{pulses}PRI}=9.53\,\mathrm{m/s} ΔR=2Fsc=156.1m,ΔfD=NpulsesPRI1=375Hz,Δv=2NpulsesPRIλ=9.53m/s
量化误差说明 :目标 2 的速度为 −6 m/s,落在 0 与 −9.53 之间,最近 bin 是 −9.53 m/s,因此峰值搜索会报告 −9.53 m/s,误差 3.5 m/s。这是速度分辨率的物理下限,不是代码 bug。要提升速度分辨率,唯一办法是增大 N p u l s e s N_{pulses} Npulses 或缩小 PRI(后者与 TDM-MIMO 冲突)。
六、结果绘图
matlab
figure('Color','w', 'Position',[100 100 1150 720]);
% 子图 1:发射 QPSK 星座
subplot(2,2,1);
plot(real(txData(1:500)), imag(txData(1:500)), 'o', 'MarkerSize', 4);
grid on; axis square; title('Transmit QPSK constellation');
% 子图 2:均衡后数据星座(含 BER/EVM 标注)
subplot(2,2,2);
plot(real(rxData(:)), imag(rxData(:)), '.', 'MarkerSize', 7);
grid on; axis square;
title(sprintf('Equalized data: BER %.3g, EVM %.2f%%', ber, 100*evmRms));
% 子图 3:距离-多普勒图
subplot(2,2,3);
imagesc(velocityAxis, rangeAxis, rdPowerDb); axis xy; colorbar; caxis([-35 0]);
xlabel('Radial velocity (m/s)'); ylabel('Range (m)');
title('Combined MIMO range-Doppler map (dB)');
hold on; plot(targetVelocity, targetRange, 'wo', 'LineWidth', 1.5, 'MarkerSize', 8); hold off;
% 子图 4:距离像(沿多普勒取最大)
subplot(2,2,4);
plot(rangeAxis, max(rdPowerDb, [], 2), 'LineWidth', 1.2); grid on; hold on;
xline(targetRange(1), '--'); xline(targetRange(2), '--'); hold off;
title('Range profile'); ylim([-45 2]);
exportgraphics(gcf, 'isac_mimo_ofdm_results.png', 'Resolution', 160);
七、常见问题排查表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 图里没有距离峰 | 按 Tx 抽取索引错误(步长写成 1 而非 Nt) | 打印 Xrad(:,symbolsForTx,tx) 确认非零比例 |
| 距离峰位置整体偏移 | 坐标轴换算漏了 2(用了 c / F s c/F_s c/Fs 而非 c / 2 F s c/2F_s c/2Fs) | 核对 rangeAxis 表达式 |
出现 Inf/NaN |
除法分母为 0(索引错位) | 检查分子分母是否同一三元组 |
| 底噪整体抬高 | 时延超过 CP → ISI/ICI | 比较最大时延与 Ncp |
| BER 远低于理论值 | 噪声方差漏乘 1/2,或帧长/信号功率估计不准 | 打印 10*log10(signalPower/noiseVariance) 校验 SNR |
| EVM 异常大/小 | ifft*sqrt(Nfft) 与 fft/sqrt(Nfft) 未配对 |
做一次无噪回环测试(信道设为单位) |
| 速度估计偏差 3~5 m/s | 速度分辨率不足( Δ v = 9.53 \Delta v = 9.53 Δv=9.53 m/s) | 增大 NpulsesPerTx 重跑 |
八、可扩展方向
- 角度维 :把 N t N_t Nt 或 N r N_r Nr 扩到 8 以上,在
rdCube后加第三维 FFT(虚拟阵列方向),或引入 MUSIC / 2D-OMP; - 分数时延 :把整数采样时延改成连续时延,用相位斜坡
exp(-j2πk·τ_frac/Nfft)在频域实现,验证插值精度; - 感知辅助通信闭环 :用
rdPower中的分布(如雷达距离像的信道状态)反推通信侧最优的 MCS / 波束 / 功率分配------这才是 ISAC 的核心价值; - 杂波抑制:在多普勒维加 MTI(动目标显示)滤波器,剔除零多普勒静态杂波;
- 波形复用替代方案 :把 TDM-MIMO 换成 DDMA(多普勒分集)或 CDM(码分),可避免 PRI 被 N t N_t Nt 拉长,代价是旁瓣和波形设计复杂度上升;
- 与 OFDM 标准对齐:把子载波间隔与 CP 换成 5G NR 的 numerology(15/30/60 kHz,normal/extended CP),评估对雷达性能的影响。
九、参考文献
- K. M. Braun, "OFDM Radar Algorithms in Mobile Communication Networks," Ph.D. dissertation, Karlsruhe Institute of Technology, 2014.
- C. Sturm, W. Wiesbeck, "Waveform Design and Signal Processing Aspects for Fusion of Wireless Communications and Radar Sensing," Proceedings of the IEEE, vol. 99, no. 7, pp. 1236--1259, 2011.
- 3GPP TR 22.837, Feasibility Study on Integrated Sensing and Communication (Release 19).
- 3GPP TS 38.211, NR: Physical channels and modulation(OFDM numerology 与 CP 定义)。
- IEEE 802.11bf Task Group, WLAN Sensing.
十、小结
本工程的实现要点可归纳为三句话:
- 通信侧:时域正交导频把 MIMO 信道估计简化成逐元素除法,逐子载波 MMSE 均衡把频选信道对角化处理,导频开销 10%;
- 感知侧 :TDM-MIMO 保证波形正交并形成 4 元虚拟阵列,
Y/X → IFFT → FFT → 非相干合并四步完成距离-多普勒成像; - 必须警惕的三个数值陷阱 :CP 长度约束、复噪声方差的 1/2 因子、
ifft/fft的sqrt(Nfft)配对。
代码可直接运行并复现出 624.6 m / 1561.4 m 两个目标的距离像,以及 22 dB 条件下的 BER / EVM 结果。
