
简介这份资源面向无线通信方向的学生与研究人员提供一套用MATLAB仿真MIMO信道容量的实例帮助理解多天线系统在空间复用下的性能表现。压缩包共2个文件含1个m脚本与1个docx文档整体约12KB脚本用于生成随机信道矩阵并计算不同信噪比下的容量文档则梳理了瑞利衰落等情形下信道容量的计算思路。读者可借助代码复现信道容量随信噪比、发射与接收天线数目变化的曲线直观观察天线数量增加对容量的提升作用以及高信噪比下增益逐渐放缓的规律。已有265人学习下载适合作为MIMO入门仿真与课程实验的参考素材。1. 从一份 MIMO MATLAB 压缩包说起信道容量到底在算什么很多人第一次接触 MIMO是从下载到一个叫MIMO MATLAB.rar的压缩包开始的。解压之后通常是一堆.m文件跑一下能出几条曲线横轴信噪比纵轴 bps/Hz看着挺唬人但真被问一句「这条曲线为什么在这个点拐弯」「天线数从 2 加到 4 容量为什么不是翻倍」多数人就卡住了。MIMO 信道容量这件事本质是在回答一个工程问题在给定发射功率、带宽和信道条件下多根天线到底能换来多少速率以及这份速率是靠空间复用换来的还是靠分集换来的。它适合已经会用 MATLAB 画图、但想把「MIMO 天线」和「MIMO 容量」之间的因果链彻底搞清楚的通信方向从业者也适合做天线硬件、想理解自己设计的天线阵列在系统层面值多少钱的人。这一篇不讲空泛的公式推导而是把一份典型的 MIMO 容量 MATLAB 方案拆开从信道矩阵怎么生成到容量公式怎么落地再到参数怎么调、哪里最容易翻车一步步走完。2. MIMO 信道容量 MATLAB 方案的骨架信道矩阵、容量公式与仿真流程2.1 为什么 MIMO 容量必须先有一个信道矩阵 H单天线系统的容量只跟标量信噪比有关而 MIMO 的一切复杂度都来自那个Nr × Nt的复信道矩阵 H。这个矩阵的每一个元素h_ij表示第 j 根发射天线到第 i 根接收天线的复增益它同时携带幅度和相位。MIMO 容量之所以能随天线数增长核心在于 H 的秩如果 H 满秩就存在多个并行的空间子信道容量近似按min(Nt, Nr)线性增长如果 H 严重相关、秩亏那多出来的天线基本是摆设。所以任何一份靠谱的 MIMO 容量 MATLAB 代码第一步都不是写容量公式而是把 H 生成对。常见做法是假设独立同分布瑞利衰落即 H 的每个元素服从零均值单位方差的复高斯分布这样得到的是理想独立信道下的容量上界用来做理论参照。真实系统里还要考虑空间相关、视距分量、天线间距这些后面章节会展开。2.2 容量公式在 MATLAB 里怎么落地MIMO 容量最常被引用的形式是发射端未知信道状态信息CSI时的等功率分配容量C log2(det(I (SNR/Nt) * H * H))其中H是 H 的共轭转置I是单位阵SNR是总发射信噪比除以Nt是因为总功率平均分到每根发射天线上。这个公式的物理含义是对H*H做特征值分解每个非零特征值对应一个空间子信道容量就是所有子信道log2(1 (SNR/Nt)*λ_i)之和。MATLAB 里实现非常短但坑都在细节里。下面是一段可以直接跑的最小实现% MIMO 容量最小实现i.i.d. 瑞利信道等功率分配 clear; clc; Nt 4; % 发射天线数 Nr 4; % 接收天线数 SNR_dB 0:2:20; % 信噪比扫描范围单位 dB MC 2000; % 每个 SNR 点的蒙特卡洛次数越大曲线越平滑 C zeros(1, length(SNR_dB)); for k 1:length(SNR_dB) snr 10^(SNR_dB(k)/10); % dB 转线性 tmp 0; for m 1:MC H (randn(Nr,Nt) 1j*randn(Nr,Nt))/sqrt(2); % 复高斯功率归一化 tmp tmp log2(real(det(eye(Nr) (snr/Nt)*(H*H)))); end C(k) tmp/MC; % 蒙特卡洛平均 end plot(SNR_dB, C, -o); grid on; xlabel(SNR (dB)); ylabel(Capacity (bps/Hz)); title(sprintf(MIMO Capacity %dx%d, Nt, Nr));逻辑说明外层循环扫信噪比内层做蒙特卡洛因为 H 是随机的单次容量波动很大必须对大量信道实现取平均才能得到有意义的遍历容量。参数说明Nt、Nr决定空间维度MC决定曲线平滑度一般 1000 到 10000 之间randn/sqrt(2)这一步是功率归一化漏掉它会让容量整体偏高约 3 dB这是新手最常见的翻车点之一。real(det(...))取实部是为了防止浮点误差导致 det 出现极小虚部虽然理论上应该是实数但数值计算里不取实部偶尔会报复数警告。2.3 遍历容量和中断容量不是一回事跑完上面代码得到的是遍历容量也就是对所有信道实现取平均。但工程上更关心中断容量比如「95% 的概率容量不低于多少」。这两条曲线在同一个 SNR 下能差出一大截尤其在天线数少、信道波动大的时候。做法是把每个 SNR 点下的 MC 次容量存下来排序取第 5 百分位C_all zeros(MC,1); for m 1:MC H (randn(Nr,Nt) 1j*randn(Nr,Nt))/sqrt(2); C_all(m) log2(real(det(eye(Nr) (snr/Nt)*(H*H)))); end C_outage prctile(C_all, 5); % 5% 中断容量选型理由如果你做的是链路预算和覆盖规划中断容量比遍历容量更有参考价值因为它对应最差情况。很多网上流传的 MIMO 容量脚本只画遍历容量拿去汇报容易被问住。参数上prctile的第二个参数按你的可靠性目标定URLLC 场景可能要看 1% 甚至 0.1%。3. 天线数与相关性怎么影响容量把参数调出物理意义3.1 天线数增加时容量为什么不线性增长理论上min(Nt,Nr)越大容量越高但实际曲线会告诉你增长在放缓。原因有两个一是等功率分配下弱特征值对应的子信道贡献很小天线越多新增的那根天线带来的边际容量越低二是当Nt Nr时容量受限于接收端自由度多出来的发射天线只能用于分集或波束赋形不能继续开空间流。验证方法很简单固定Nr4把Nt从 2 扫到 8看高 SNR 段的斜率变化。我一般会写一个循环把不同配置画在一张图上对比这样汇报时一眼能看出「加天线值不值」。configs [2 2; 4 4; 8 8; 4 2; 8 4]; % 每行一个 [Nt Nr] 配置 SNR_dB 0:2:20; figure; hold on; for c 1:size(configs,1) Nt configs(c,1); Nr configs(c,2); C zeros(1,length(SNR_dB)); for k 1:length(SNR_dB) snr 10^(SNR_dB(k)/10); tmp 0; for m 1:1000 H (randn(Nr,Nt)1j*randn(Nr,Nt))/sqrt(2); tmp tmp log2(real(det(eye(Nr)(snr/Nt)*(H*H)))); end C(k) tmp/1000; end plot(SNR_dB, C, -o, DisplayName, sprintf(%dx%d,Nt,Nr)); end legend(show); grid on; xlabel(SNR (dB)); ylabel(Capacity (bps/Hz));参数说明configs里4x2和8x4是发射多于接收的情况你会看到它们的容量在高 SNR 段明显低于同量级的对称配置这就是接收端自由度受限的直接体现。注意SNR/Nt里的Nt必须跟着配置变否则总功率不守恒对比就不公平。3.2 空间相关性让理想曲线现原形的关键参数i.i.d. 信道是理想假设真实天线阵列里天线间距不够、角度扩展小都会让 H 的元素相关秩下降容量缩水。常见做法是引入 Kronecker 相关模型H Rr^(1/2) * Hiid * Rt^(1/2)其中Rt、Rr是发射和接收相关矩阵。指数相关模型最常用相关系数rho控制相邻天线的相关程度rho 0.5; % 相邻天线相关系数0 为独立1 为完全相关 Rt toeplitz(rho.^(0:Nt-1)); % 发射相关矩阵 Rr toeplitz(rho.^(0:Nr-1)); % 接收相关矩阵 H Rr^0.5 * ((randn(Nr,Nt)1j*randn(Nr,Nt))/sqrt(2)) * Rt^0.5;逻辑说明toeplitz生成对称的指数衰减相关矩阵rho越大矩阵越接近全 1秩越低。参数说明rho取 0.3 到 0.7 是比较贴近实测的范围具体取决于天线间距和散射环境rho0退化成独立信道可以用来验证代码正确性。把rho从 0 扫到 0.9你会看到高 SNR 段容量掉得最狠因为相关性强的时候弱特征值趋近于零等功率分配还在往这些子信道上灌功率纯属浪费。这也是为什么实际系统里要做预编码和注水功率分配。3.3 注水功率分配能挽回多少容量当发射端知道 CSI 时最优策略是注水给强特征值对应的子信道多分功率弱的少分甚至不分。容量变成对特征值λ_i做注水后的求和。实现上先对H*H做特征分解再按水位求解[~, D] eig(H*H); lambda real(diag(D)); % 特征值 lambda sort(lambda, descend); % 注水找水位 mu使 sum(max(mu - Nt/(snr*lambda), 0)) 1 mu_lo 0; mu_hi 1e3; for it 1:60 mu (mu_lomu_hi)/2; p max(mu - Nt./(snr*lambda), 0); if sum(p) 1, mu_hi mu; else, mu_lo mu; end end C_wf sum(log2(1 (snr/Nt)*lambda.*p));参数说明二分法找水位mu60 次迭代足够收敛p是各子信道功率分配比例和必须为 1。对比等功率和注水两条曲线低 SNR 段差距不大高 SNR 段注水能拉开 1 到 3 bps/Hz具体取决于特征值扩散程度。如果特征值很集中注水退化成等功率别指望有惊喜。4. 避坑与排查MIMO 容量仿真里最容易翻车的五件事4.1 容量曲线整体偏高 3 dB现象跑出来的容量比文献里的参考曲线高出一截形状对但数值偏大。原因生成复高斯信道时忘了功率归一化randn默认方差是 1实部虚部各 1合起来每个元素功率是 2相当于信噪比凭空多了 3 dB。解决统一写成(randn1j*randn)/sqrt(2)养成习惯别在不同脚本里用不同写法。4.2 det 报出复数或者容量出现 NaN现象log2(det(...))偶尔返回复数或者对负数取 log 得到 NaN。原因浮点误差让本应为实数的 det 带上极小虚部或者矩阵接近奇异时 det 出现极小负值。解决外面套real()并对 det 结果做max(det, eps)保护避免 log 负数。更稳妥的做法是用特征值求和代替 det数值上更稳定。4.3 蒙特卡洛次数太少导致曲线毛刺现象曲线锯齿明显换个随机种子形状就变。原因MC太小遍历容量的估计方差大。解决MC至少 1000做论文级曲线建议 10000 以上如果嫌慢可以用parfor并行但要注意随机数流的独立性别让各 worker 用同一个种子。4.4 天线数配置和 SNR 定义不匹配现象对比不同天线数配置时曲线交叉关系不符合预期。原因SNR/Nt里的Nt没跟着配置更新或者把总功率 SNR 和每天线 SNR 搞混了。解决明确约定 SNR 是总发射 SNR容量公式里永远除以当前的Nt如果要用每天线 SNR公式里就不除但全文必须统一不能一半一半。4.5 相关矩阵开方用错现象引入相关性后容量不降反升或者出现异常。原因Rr^0.5在 MATLAB 里是矩阵幂对非对角矩阵不一定等于 Cholesky 分解得到的平方根且相关矩阵理论上半正定数值误差可能让它出现负特征值。解决用chol做 Cholesky 分解H Lr * Hiid * Lt其中Lrchol(Rr,lower)这样既快又稳还能保证结果物理可解释。5. 把 MIMO 容量仿真做成可复用的验证工具真正让这套东西有价值的不是跑出一条漂亮曲线而是把它变成一个能反复回答问题的工具。我自己的习惯是写一个函数mimo_capacity(Nt, Nr, snr_dB, rho, mode)mode控制等功率还是注水、遍历还是中断所有参数从外部传主脚本只负责调参和画图。这样下次有人问「天线间距从半波长加到两个波长容量能涨多少」你只需要改rho重跑而不是重写代码。验证方法上除了对比文献还可以做两个自检rho0且NtNr1时容量必须退化成log2(1snr)这是香农公式对不上说明公式或归一化有问题NtNr且高 SNR 时容量斜率应该接近min(Nt,Nr)倍每 3 dB斜率不对说明空间自由度没算对。进阶一点可以把信道从 i.i.d. 换成 3GPP 的 CDL 模型或者把天线方向图从全向换成微带贴片天线的实测方向图这时候容量仿真才真正和你的天线设计挂上钩。我踩过最深的坑是早期只顾着把曲线画好看忽略了rho的物理来源结果汇报时被问「你这个相关系数对应多大的天线间距」答不上来。后来我强制自己在每个相关矩阵旁边标注对应的天线间距和角度扩展假设曲线才站得住。做 MIMO 容量仿真公式是死的参数背后的物理场景才是活的把这一层想清楚那份MIMO MATLAB.rar才算真正被你用起来。希望帮到你。本文还有配套的精品资源点击获取