简介:面向通信专业本科、硕士教研学习的一份MATLAB仿真资料包,聚焦多径衰落信道建模与仿真实现,适合需要理解多径传输、多普勒频移等基础概念的入门者。压缩包共16个文件,包含7个.m源码脚本、8张jpg运行结果图和1份doc说明文档,整体仅382KB,轻量紧凑。其中.m脚本为仿真主体,可运行于MATLAB 2019a环境;结果图直观展示不同参数下的信道响应;doc文档则对多径传输与多普勒频移原理进行了梳理。目前已有204人浏览学习。借助这些脚本与说明,读者可以快速搭建多径衰落信道仿真流程,观察多径效应及频率色散对接收信号的影响,并依据运行结果调整参数设置,加深对无线通信信道特性的理解;同时,脚本按功能拆分、参数可调,便于二次开发与学习验证,非常适合作为课程实验、毕业设计以及科研入门的演练素材。
1. 多径衰落信道 MATLAB 仿真:从一根天线看到整条链路的波动
无线通信仿真里,凡是评估性能、测误码率、验证均衡器和 OFDM 参数,几乎都得先过多径衰落信道这一关。信号在建筑物、地面、车辆之间反复反射和散射,到达接收端时已不是单个副本,而是大量幅度、相位和到达时间各不相同的信号叠加的结果,直观表现就是接收波形剧烈起伏、出现码间串扰,星座图被搅成一团。拿到一个多径衰落信道 MATLAB 仿真包,最关键的是看懂三件事:信道冲激响应和抽头延迟线模型怎么建立、Rayleigh 衰落序列在代码里怎么生成、以及 QPSK/OFDM 链路如何正确接上信道。本文就按这三条线把原理、参数和可运行代码一起讲透,让你能改参数、重跑仿真,并判断结果是否合理。
2. 多径衰落信道的数学骨架:冲激响应、Rayleigh 与多普勒谱
2.1 用冲激响应和抽头延迟线描述“多个副本”叠加
多径信道的模型核心是信道冲激响应,工程里写作:
h(τ) = Σ a_i δ(τ - τ_i)其中 a_i 是第 i 条路径的复增益,τ_i 是这条路径的时延。到了 MATLAB 仿真里,这个连续表达式会按接收机的采样周期 Ts 把时延量化成整数个采样点,从而变成一个 FIR 滤波器:
y[n] = Σ h_i[n] · x[n - d_i]这里的 x 是发送的基带复信号,h_i[n] 是第 i 个抽头在时刻 n 的复系数,d_i 是归一化时延。看一段仿真代码时,只要抓住三个参数就能看懂整个信道配置:
- 路径时延向量,决定多径在时间轴上的分布;
- 平均路径功率,决定每条路径的能量占比;
- 最大多普勒频移,决定 h_i[n] 随时间变化的剧烈程度。
3GPP 38.901 里的 TDL(tap delay line)模型就是这样组织的,MATLAB 通信工具箱中的 comm.RayleighChannel 对象也把这三个参数作为核心输入接口。
时延扩展的绝对数值要跟符号速率放在一起比。假如符号周期远大于最大时延扩展,整个信号带宽内信道响应近似平坦,这叫平坦衰落,仿真里通常用一个复系数乘上每个符号就够了;反之则必须用多抽头 TDL 才能体现频率选择性。后面第 4 章会回到这个判断,这里先记住:单径乘性信道是平坦衰落,多径卷积信道是频率选择性衰落。
2.2 Rayleigh 与 Rician:有无视距分量的两种统计场景
衰落幅度的统计特性,由接收端是否存在稳定的视距分量决定。在城区、室内这类散射体密集的环境里没有视距路径,接收信号是大量散射分量的叠加,由中心极限定理可知信道系数是复高斯随机过程,幅度服从瑞利分布。存在视距分量时,幅度服从莱斯分布,两者通过莱斯 K 因子衔接,K 是视距功率与散射功率之比。K=0 退化为瑞利,K 越大信道越接近无衰落高斯信道。
| 统计模型 | 适用物理场景 | 包络 PDF 形式 | 仿真关键参数 |
|---|---|---|---|
| Rayleigh | 密集城区、室内无直射、城市峡谷 | r/σ²·exp(-r²/2σ²) | σ² 为散射分量平均功率 |
| Rician | 无人机空地链路、郊区、室内走廊 | r/σ²·exp[-(r²+A²)/2σ²]·I0(Ar/σ²) | K = A²/2σ²,A 为视距幅度 |
| Nakagami-m | 跨场景通用经验模型 | 2mᵐr²ᵐ⁻¹/(Γ(m)Ωᵐ)·exp(-mr²/Ω) | m 为衰落深度,m=1 即瑞利 |
MATLAB 里 comm.RayleighChannel 和 comm.RicianChannel 都支持直接设置 K 因子或平均路径增益。需要留意的是,同一组路径功率下,K 因子改变会直接影响信道的概率密度分布和误码率曲线形态,仿真时不要只在 SNR 上做文章,K 因子才是多径环境的核心变量。
2.3 Clarke/Jakes 多普勒谱与相干时间
移动终端或散射体运动会让每条路径产生多普勒频移。各方向均匀到达的散射波叠加后,归一化功率谱密度呈经典 Clarke 谱:
S(f) = 1 / (π·fd·sqrt(1 - (f/fd)²)),|f| ≤ fd其中 fd = v·fc/c 是最大多普勒频移。这个谱的形状是两边高、中间低的 U 形,MATLAB 里 sin 波叠加可以生成这种谱型,它的反傅里叶变换正好对应信道包络的自相关函数。
工程上更常用的一个导出量是相干时间 Tc ≈ 0.423/fd,它表示信道冲激响应保持强相关的时间窗。仿真中如果符号间隔大于相干时间,就要每个符号重新采样衰落系数;反过来,fd 很小而仿真时长很短时,信道几乎不变,得到的结果只反映一次“冻结信道”下的性能,没有统计意义。这也是很多人做多径仿真时最容易忽略的边界:fd 设成 10 Hz,符号率 1 MHz,仿真 1 ms,那么整段信号经历的其实是同一个信道状态。
3. MATLAB 中生成多径衰落信道:工具箱对象、Jakes 自实现与 3GPP 参数表
3.1 comm.RayleighChannel 最小可运行代码
通信工具箱提供了现成的信道对象,这是最稳定、最省事的方式。先看一段可以直接复制运行的最小代码:
fs = 1e7; % 系统采样率 10 MHz fd = 100; % 最大多普勒频移 100 Hz delays = [0 0.2e-6 0.5e-6]; % 三条路径的相对时延,单位秒 gains = [0 -3 -8]; % 三条路径的平均功率,单位 dB ray = comm.RayleighChannel( ... 'SampleRate', fs, ... 'MaximumDopplerShift', fd, ... 'PathDelays', delays, ... 'AveragePathGains', gains); x = randn(1e5, 1); % 任意输入信号,这里用 10 万个随机样点 y = ray(x); % 经过多径信道后的输出 figure; plot(real(y(1:2000))); grid on; xlabel('采样点'); ylabel('幅度'); title('多径信道输出的实部波形');这段代码创建了一个三条路径的衰落信道,然后用 10 万个样点的序列过了一趟信道。有几个点要特别说明:
- 输入 x 可以是任意长度的复数基带信号,这里用实数随机序列只是演示波形,后面接 QPSK 时必须换成复数符号。
- 同一个 channel 对象被反复调用时,内部状态会持续推进,也就是说第二次调用不再从第一个时刻开始,这在循环仿真里是正确行为,但容易让人误以为信道变了。
- MaximumDopplerShift 设为 0 意味着静态信道,系数不再随时间变化,多径效应退化为固定 FIR 滤波器。
- 老代码里的 rayleighchan 和 filter 函数写法在新版 MATLAB 中仍然可用,但通信工具箱文档已推荐统一使用 comm 系列对象。
如果只需要单径平坦衰落,把 PathDelays 设成 0、AveragePathGains 设成 0,再给每个符号乘一个按时间生成的复高斯系数即可,完全不需要起一个采样率很高的对象。
3.2 不依赖工具箱的 Jakes 正弦叠加法
有些场景需要完全可控的衰落生成过程,比如验证多普勒谱形状、做教学演示,此时不依赖工具箱的 Jakes 正弦叠加法更合适。其思路是用 N 个不同入射角的多普勒分量叠加,近似各向同性散射环境:
function h = jakesFading(nSamples, fd, fs, N) % JAKESFADING 生成瑞利平坦衰落包络 % 输入: % nSamples : 输出样本点数 % fd : 最大多普勒频移(Hz) % fs : 采样率(Hz) % N : 散射波数量,一般取 16~64 % 输出: % h : 复数衰落系数序列,平均功率约为 1 t = (0:nSamples-1) / fs; alpha = 2*pi*rand(N, 1); % 到达角在 [0, 2π) 均匀分布 phi = 2*pi*rand(N, 1); % 每条路径的随机初始相位 h = zeros(1, nSamples); for n = 1:N % 每一路径贡献一个频率为 fd*cos(alpha) 的复正弦 h = h + exp(1j*phi(n)) .* exp(1j*2*pi*fd*cos(alpha(n)) .* t); end h = h / sqrt(N); % 功率归一化,使 E[|h|^2] = 1 end调用方式为:
h = jakesFading(20000, 100, 1e4, 32);这段代码把 N 个正弦波叠加,入射角按余弦形式影响多普勒频移。fd 越大、时间轴越长,波形变化越剧烈;N 取 32 时统计特性和理想 Rayleigh 已经很接近,N 过小会出现周期性波纹。归一化除以 sqrt(N) 是为了让平均功率为 1,否则后续 SNR 设置会差一个常数倍。
需要注意,Jakes 方法生成的是单个抽头的时变系数,模型中不包含时延扩展,所以只适用于平坦衰落。若仿真 OFDM 或多抽头 TDL 信道,还是要回到第 3.1 节的对象方式,或者自己写一个多条时延路径的 Jakes 生成器。
3.3 3GPP TDL 抽头表:直接把标准参数搬进仿真
5G 和 WiFi 系统仿真里,信道参数通常直接引用 3GPP 38.901 中定义的 TDL 模型。这些模型规定了若干抽头的时延和相对功率,使用时把这些数值替换进 comm.RayleighChannel 即可。下面列出 TDL-E 模型(非视距、强频率选择性)的简化版本:
| 抽头编号 | 时延(ns) | 相对功率(dB) |
|---|---|---|
| 1 | 0 | 0 |
| 2 | 30 | -1.0 |
| 3 | 70 | -2.2 |
| 4 | 90 | -3.2 |
| 5 | 110 | -7.9 |
| 6 | 190 | -7.9 |
| 7 | 410 | -9.8 |
直接配置信道的写法是:
tdlE_delays = [0 30 70 90 110 190 410] * 1e-9; % ns 转秒 tdlE_gains = [0 -1.0 -2.2 -3.2 -7.9 -7.9 -9.8]; ray5g = comm.RayleighChannel( ... 'SampleRate', 100e6, ... 'PathDelays', tdlE_delays, ... 'AveragePathGains', tdlE_gains, ... 'MaximumDopplerShift', 30, ... 'NormalizePathGains', true);这里的 NormalizePathGains 设为 true 时,信道会按抽头总功率自动归一化,避免因路径条数不同导致接收功率变化。三种实现方式各有定位,按场景选择:
| 实现方式 | 工具箱依赖 | 频率选择性 | 统计特性 | 适用场景 |
|---|---|---|---|---|
| comm.RayleighChannel | 需要通信工具箱 | 支持 | 精确 | 端到端链路级仿真 |
| Jakes 正弦叠加 | 无 | 不支持(单抽头) | 近似 | 原理验证、教学 |
| 3GPP TDL 参数表 | 需要通信工具箱 | 支持 | 标准 | 5G/WiFi 系统级仿真 |
4. 端到端链路验证:QPSK 误码率仿真与 OFDM 抗多径效果
4.1 平坦衰落信道下 QPSK 的 BER 曲线
把信道模型接进完整通信链路,最常见的第一件事就是画误码率曲线。下面这段代码对比 QPSK 在 AWGN 和瑞利平坦衰落下的 BER,假设接收端做理想信道估计:
M = 4; % 调制阶数,4 即 QPSK nSym = 2e5; % 单次统计使用的符号数 data = randi([0 M-1], nSym, 1); tx = pskmod(data, M, pi/4); snrDb = 0:2:20; berAwgn = zeros(1, numel(snrDb)); berRay = zeros(1, numel(snrDb)); for k = 1:numel(snrDb) % 基线:纯 AWGN rxAwgn = awgn(tx, snrDb(k), 'measured'); berAwgn(k) = mean(pskdemod(rxAwgn, M, pi/4) ~= data); % 平坦瑞利衰落:每个符号乘一个复高斯系数 h = (randn(nSym,1) + 1j*randn(nSym,1)) / sqrt(2); rxRay = h .* tx; % 过衰落信道 rxRay = rxRay ./ h; % 理想信道均衡 rxRay = awgn(rxRay, snrDb(k), 'measured'); berRay(k) = mean(pskdemod(rxRay, M, pi/4) ~= data); end semilogy(snrDb, berAwgn, '-o', snrDb, berRay, '-s'); legend('AWGN', 'Rayleigh 平坦衰落', 'Location', 'southwest'); xlabel('SNR (dB)'); ylabel('BER'); grid on;代码里的 h 是每符号一个独立复高斯采样,相当于符号周期远大于相干时间的极限情况,真实移动信道中的相邻符号是相关的。均衡用除法实现,对应接收端能无误差估计信道状态。两条曲线的差距非常直观:AWGN 下 10 dB 左右 BER 就降到 1e-4 量级,而平坦瑞利衰落要 SNR 高出大约 20 dB 才能达到同样水平,原因是深度衰落事件会成片打掉符号。
如果去掉 ./h 这行不做均衡,星座图会旋转且无规律扩散,BER 在平坦衰落中始终不会低于某个本底,这在仿真中属于“信道完全未知且无导频”的场景,和带均衡的系统是两个不同问题。
4.2 频率选择性多径的观察:卷积效应与星座图扩散
当符号速率提高、时延扩展超过符号周期后,多径从乘性干扰变成码间串扰。最简单的观察方式是把信道只建模成两个固定抽头,输入一段 QPSK 符号,输出和输入会明显错位:
% 双径固定信道:主径功率 1,第二径时延 1 个符号,幅度 0.7 ch = [1 0.7]; % 卷积核 x = pskmod(randi([0 3], 1000, 1), 4, pi/4); y = conv(x, ch); % 线性卷积,长度为 1001 % 逐符号观察 ISI 对星座图的影响 scatterplot(y(2:end), 1, 0, 'b.'); title('双径信道后的 QPSK 星座图');这个固定信道不会随时间变化,但相邻符号之间发生了叠加,y[n] = x[n] + 0.7·x[n-1]。第二个符号对当前符号形成干扰,星座图上每个原始点周围会散开出四个簇,簇的宽度由抽头功率比 0.7 决定。这个例子虽然没有时变衰落,但它能清晰地把“多径导致 ISI”和“乘性平坦衰落”区分开,是理解频率选择性信道的起点。
4.3 OFDM 加循环前缀:最小化演示多径对抗原理
OFDM 抗多径并不是靠均衡器,而是靠循环前缀把线性卷积改造为循环卷积,从而使每个子载波只经历一个复增益。下面是一个单 OFDM 符号的极简演示,用尾部复制代替真实循环前缀填充以逼近循环卷积:
M = 4; nFft = 64; cpLen = 12; % 子载波数 64,循环前缀 12 x = pskmod(randi([0 M-1], nFft, 1), M, pi/4); s = ifft(x, nFft); % IFFT 后的时域样点 % 构造带循环前缀的发送块:尾部复制 + 原始序列 sCp = [s(end-cpLen+1:end); s]; % 双径信道:主径 + 0.6 倍功率时延 3 个采样点的次径 delayIdx = 3; r = sCp(1:nFft) + 0.6 * sCp(delayIdx+1:delayIdx+nFft); % FFT 恢复频域,乘性系数为 1+0.6*exp(-j*2π*k*3/nFft) rFft = fft(r, nFft); y = pskdemod(rFft, M, pi/4); ber = mean(y ~= x);这里的 r 中,第一项是直射分量,第二项取 sCp 中偏移 3 个采样点的位置,等价于把延迟路径建模为圆周移位。因为 cpLen 取 12,大于时延 3,符号间的干扰被完整约束在循环前缀区间内,去除 CP 后各子载波仍然保持正交。这段代码不包含信道估计和多普勒过程,但足以说明一个结论:OFDM 系统设计循环前缀时,第一原则就是让 CP 长度大于信道最大时延扩展。
5. 仿真结果统计校验与参数调节的实用技巧
5.1 用 CDF 和自相关函数校验衰落序列
每次写完一段信道仿真,第一件事不是看 BER,而是验证产生的衰落序列统计上是否合理。用第 3.2 节的 jakesFading 函数生成一段序列,分别校验包络分布和时域相关性:
h = jakesFading(1e5, 100, 1e4, 32); % 100 Hz 多普勒,10 kHz 采样 r = abs(h); % 包络 CDF 与理论瑞利 CDF 对比 figure; cdfplot(r); hold on; rr = linspace(0, max(r), 200); theoryCdf = 1 - exp(-rr.^2 / mean(r.^2)); plot(rr, theoryCdf, 'r--', 'LineWidth', 1.5); legend('仿真 CDF', '理论 Rayleigh CDF'); xlabel('包络幅度'); ylabel('CDF'); grid on; % 自相关函数与时域变化节奏 [acf, lags] = xcorr(h, 'coeff'); lagsSec = lags / 1e4; figure; plot(lagsSec, abs(acf)); grid on; xline(0.423/100, 'r--', 'Coherence Time'); xlabel('时间差 (s)'); ylabel('|自相关|');理论 CDF 的表达式用 mean(r.^2) 估计平均功率,可以直接检验生成的包络是否偏离瑞利。自相关曲线在相干时间约 4.23 ms 处降到较低值,说明这条衰落序列的变化节奏符合 fd=100 Hz 的设置。如果自相关衰减过快,通常意味着 fd 设置偏大或采样率不足;如果几乎不衰减,则是序列长度不够长,还没有经历足够的深衰落周期。
5.2 三个最容易踩的参数坑
SampleRate 和 PathDelays 的匹配。PathDelays 必须能被采样周期整除或近似整除,否则抽头会落到分数时延上。MATLAB 的 channel 对象允许非整数倍时延,但内部会做插值,输出与预期 PDP 之间会产生偏差。需要整数倍时延时,先算 delaySamples = round(tau × fs) 再回推实际时延。
多普勒频移与仿真步长。fd=1000 Hz 时衰落包络变化周期约 1 ms,如果仿真步长大于 0.1 ms,采样就会丢深衰落谷点,误码率统计偏高。实际经验是至少让 fd×Ts ≤ 0.01,即采样间隔内最多走过多普勒周期的百分之一。
循环复用信道对象时的随机流控制。comm.RayleighChannel 默认使用随机流,每次调用状态推进。需要不同信噪比条件下对照时,先在对象上设置 seed,或者用 reset(ray) 重置,否则多次循环得到的结果不是同一统计条件下的重复实验。
5.3 用有限长序列稳定估计 BER 的最小符号数
仿真中 BER 在 1e-5 以下时,统计波动对符号数极其敏感,正确做法是先按目标误码率设置符号数再跑:若目标 BER 为 1e-4,至少跑 1e6 个符号,并重复 5~10 次取平均。每次重复使用不同随机种子,最后把 BER 逐点取均值并标注置信区间,而不是只看一次结果曲线。按这个原则调节符号数和 fd 后,多径衰落信道的仿真曲线会稳定得多,不同代码包之间的参数对比才有实际意义。
本文还有配套的精品资源,点击获取