ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Matlab实现2×2 Alamouti双发双收MIMO仿真与误码率分析

Matlab实现2×2 Alamouti双发双收MIMO仿真与误码率分析 简介一套基于Alamouti原始论文的2×2双发双收空间分集编码MATLAB仿真实现面向无线通信与MIMO系统学习、科研的工程师、研究生及高年级本科生用于直观理解Alamouti方案的工作原理、解码流程与性能表现。方案在两根发射天线、两根接收天线下可实现全速率传输并能通过简单线性操作恢复原始符号非常适合作为MIMO课程算法验证与链路仿真的入门参考。压缩包共11个文件均为.m脚本整体仅9KB涵盖BPSK、QPSK、16QAM的调制解调、噪声方差计算、最大似然判决、星图映射、仿真主程序等完整模块各脚本职责清晰便于二次开发。已有670人学习下载常用于课程设计、毕业设计或科研预研中的链路级仿真。通过运行主脚本可即时获得不同调制方式与信道条件下的误码率曲线对比空间分集增益代码结构清晰、模块化程度高适合在此基础上修改参数、更换调制方式或扩展为其他天线配置也可用于复现Alamouti原始论文中的经典仿真结果。1. 双发双收 Alamouti 方案这份资源能干什么、适合谁如果你在找“2×2 Alamouti方案实现”多半是这三类情况课程设计要交一个能跑的MIMO仿真毕业论文需要一张理论加仿真的误码率对比图或者想照着Alamouti原始论文复现一遍却被代码细节卡住。这份资源正好落在这件事上用Matlab把Alamouti双发双收、BPSK调制、Rayleigh信道、接收端MRC合并和误码率统计完整串起来跑完能直接得到一条与理论曲线对照的BER曲线。它最适合通信方向的研究生、本科生以及想快速验证“分集增益”为什么有效的工程师。2. 原始论文里的 Alamouti 编码从2×1到2×2是怎么推过来的网上讲Alamouti的资料不少但大多数只贴矩阵不推信号导致代码里每个变量对应什么物理含义都不清楚。这一章把原始论文的编码矩阵、2×2接收模型和BPSK的选取理由拆开后面写代码时才不会出现“矩阵转置对不上”的翻车。2.1 编码矩阵两个符号、两个时隙、两根天线Alamouti 1998年发表那篇经典论文时核心结论是一个2×1配置两根发射天线、一根接收天线就能在不增加带宽、不需要发射端知道信道状态信息的前提下获得二阶分集。做法是把两个符号s1、s2按下面的矩阵从两根天线发出去时隙天线1天线2t1s1s2t2-s2*s1*注意t2时刻天线1发的是-s2*天线2发的是s1*符号上加*表示共轭。这个矩阵形式很聪明它的行是时间、列是空间并且任意两行之间满足正交关系。所谓“正交”指矩阵与自己共轭转置相乘后只剩对角项没有符号间的相互干扰。我一般会让初学者先敲下面这段Matlab确认正交性再往下写系统代码syms s1 s2 real; % 两个复符号先按实符号验证 G [s1 -conj(s2); ... s2 conj(s1)]; % 列对应天线行对应时隙 disp(G * G); % 结果应为对角阵这段代码用符号计算验证G*G等于(|s1|^2|s2|^2)乘以单位阵对角项之外的元素全是0。G*G这个结果就是Alamouti方案能够简单线性解码的根基接收端只需要做线性合并不需要像V-BLAST那样做逐符号干扰消除复杂度低很多。这里把G写成列对应天线、行对应时隙与后面系统模型保持一致。有了这个正交编码2×1系统的解码很简单但双发双收的2×2配置需要把两根接收天线也考虑进来。很多人以为双发双收就是把2×1的代码复制粘贴两份再拼起来实际上接收端要额外处理两根接收天线各自收到的两时隙信号再合并成两个判决统计量。接下来把系统模型写清楚。2.2 2×2接收信号模型双收天线的合并逻辑设h_ij表示第j根发射天线到第i根接收天线的信道系数1≤i≤21≤j≤2均服从复高斯分布。以接收天线1为例它在时隙t1收到的是s1经过h11、s2经过h12后的叠加再加噪声。时隙t2收到的是-s2*与s1*分别经过h11、h12后的叠加。写成向量形式y1_t1 h11s1 h12s2 n1y1_t2 -h11s2* h12s1* n2接收天线2同理只是信道系数换成h21、h22。这个结构的关键是每个接收天线都能独立分离出s1和s2分离方法就是把两个时隙的接收信号与共轭信道相乘后合并s1_hat_1 h11* * y1_t1 h12 * y1_t2*s2_hat_1 h12* * y1_t1 - h11 * y1_t2*其中h11*表示h11的共轭y1_t2*表示第二时隙接收信号的共轭。这套合并本质上就是最大比合并因为它把不同路径上的信号按信道系数共轭加权使SNR最大化。对两根接收天线分别做上述合并再把两个s1_hat相加、两个s2_hat相加就得到最终的判决统计量。我常在草稿纸上推导这一步确认符号方向和加减号否则写代码时会差一个共轭结果误码率曲线像噪声。从分集角度看2×1配置每个符号的等效分集阶数是22×2配置等效分集阶数是4。也就是说双发双收的BER曲线斜率更陡在10^{-2}往下的区域每条曲线的下降速度大约按10^{-L}变化L就是分集阶数。这个结论在后面第4章会和理论曲线对照验证。2.3 BPSK 为什么适合做验证调制调制方式选BPSK不是随便定的理由有三个。第一BPSK每个符号只承载1比特数学表达式s ±1判决时只需要看实部符号把干扰因素降到最低第二BPSK的复共轭和原符号相同因此上面矩阵里的conj操作不会改变符号值但代码里仍然保留conj的写法为的是以后换QPSK、16QAM时不改接收逻辑第三BPSK的理论误码率在Rayleigh分集信道下有闭式解方便仿真结果对照。我拿到别人的Alamouti代码时会先看它有没有保留conj和s1_hat实部判决。如果全部用实数运算跳过共轭通常说明作者只写了BPSK专用版本扩展性差。后面第6章会讲怎么从BPSK改到QPSK到时候你就明白保留共轭能省多少事。3. Matlab 复现路径BPSK 发射、Rayleigh 信道与 MRC 检测这一章给出能直接跑的仿真骨架。完整流程分三段发射端生成比特并做Alamouti编码中间生成Rayleigh块衰落信道和AWGN噪声接收端做MRC合并和判决。下面按这三个步骤贴代码每一段都带参数说明。3.1 初始化与发射端符号能量归一化的第一个关键点不管以后怎么扩展发射端第一件事是把符号能量归一化。Alamouti是两根天线同时发信号与单天线系统比较时如果不把每根天线的发射功率各分一半总发射功率就成了原来的两倍仿真SNR会比设定值高3dB整条BER曲线偏移。常见做法是让每个符号能量等于0.5这样两根天线每个时隙的总发射能量恰好为1和SISO公平对照。% 仿真参数 EbN0_dB 0:2:20; % 横轴比特信噪比BPSK下 EsEb numBits 1e6; % 每个SNR点要统计的比特数偶数 ber zeros(size(EbN0_dB)); for snrIdx 1:length(EbN0_dB) EbN0 10^(EbN0_dB(snrIdx)/10); N0 1 / EbN0; % 单边噪声谱密度 noiseSigma sqrt(N0/2); % 复噪声实部/虚部标准差 % 发射端BPSK映射 能量归一化 bits randi([0 1], numBits, 1); s (1 - 2*bits) / sqrt(2); % 0-1/sqrt(2), 1--1/sqrt(2) s1 s(1:2:end); % 每个Alamouti块的第一个符号 s2 s(2:2:end); % 每个Alamouti块的第二个符号代码里s1和s2的长度是numBits/2每个s1对应一个编码块两个天线在两个时隙内发送s1/s2组合。注意s的生成用了“1-2*bits”这比直接判断0/1再乘正负更快。能量归一化的除法放在映射之后不要写反否则后面s1和s2的统计功率就不是0.5。numBits必须保证是偶数否则最后一块凑不齐两个符号实际使用中还要处理尾块这个细节在第5章避坑会提到。3.2 信道生成与接收信号建模块衰落不能随便抽Alamouti方案里最关键的信道假设是一个编码块的两个时隙内信道系数保持不变。仿真中对应“块衰落”模型即每两行数据共享一组h11/h12/h21/h22。如果每个符号都独立抽信道接收端合并时会破坏正交性分集阶数直接打折。下面这段在每个SNR循环里重新生成信道但只在整个编码块内保持不变。% 信道每2个符号抽一次块衰落 numBlocks length(s1); h11 (randn(numBlocks,1) 1j*randn(numBlocks,1)) / sqrt(2); h12 (randn(numBlocks,1) 1j*randn(numBlocks,1)) / sqrt(2); h21 (randn(numBlocks,1) 1j*randn(numBlocks,1)) / sqrt(2); h22 (randn(numBlocks,1) 1j*randn(numBlocks,1)) / sqrt(2); % 接收信号两根接收天线各两个时隙 n1 noiseSigma * (randn(numBlocks,1) 1j*randn(numBlocks,1)); n2 noiseSigma * (randn(numBlocks,1) 1j*randn(numBlocks,1)); n3 noiseSigma * (randn(numBlocks,1) 1j*randn(numBlocks,1)); n4 noiseSigma * (randn(numBlocks,1) 1j*randn(numBlocks,1)); % 接收天线1 r1_1 h11 .* s1 h12 .* s2 n1; % 时隙1 r2_1 -h11 .* conj(s2) h12 .* conj(s1) n2; % 时隙2 % 接收天线2 r1_2 h21 .* s1 h22 .* s2 n3; r2_2 -h21 .* conj(s2) h22 .* conj(s1) n4;信道系数用randn除以sqrt(2)保证每径平均功率为1。除以sqrt(2)的意思是把实部、虚部各自归一化使|h|^2的均值等于1。很多新手直接用randn(1)1j*randn(1)得到的信道功率均值是2这会让衰落方差偏大曲线整体右移约1点多dB别看不大论文对比图上一眼就能看出不对。噪声方面n1到n4分别对应两根接收天线的两个时隙。噪声方差由noiseSigma控制实部、虚部独立同分布。注意这里噪声只加在接收端不加在信道上。有些网上代码把噪声乘到信道系数上导致高SNR时BER不再下降这是低频错误但也说明“噪声只能加在接收信号上”这个常识需要反复跟学生强调。3.3 MRC合并、判决与误码统计三段拼接就是完整仿真接收端合并直接套第2章的数学式。对每个接收天线分别做最大比合并然后把两个天线的结果相加得到每个符号的判决统计量。判决时BPSK只需要看实部符号统计量大于0判为0小于0判为1。% MRC合并两根接收天线各自的估计相加 s1_hat conj(h11).*r1_1 h12.*conj(r2_1) ... conj(h21).*r1_2 h22.*conj(r2_2); s2_hat conj(h12).*r1_1 - h11.*conj(r2_1) ... conj(h22).*r1_2 - h21.*conj(r2_2); % BPSK判决实部小于0判为1 bitsHat zeros(numBits, 1); bitsHat(1:2:end) real(s1_hat) 0; bitsHat(2:2:end) real(s2_hat) 0; % 统计误码 nErr sum(bitsHat ~ bits); ber(snrIdx) nErr / numBits; end figure; semilogy(EbN0_dB, ber, b-o); grid on; hold on; xlabel(Eb/N0 (dB)); ylabel(BER);s1_hat和s2_hat的表达式里第一行来自接收天线1第二行来自接收天线2。加号和减号的位置要和发射端一致合并s1时用共轭h11乘第一时隙、h12乘第二时隙的共轭合并s2时用共轭h12乘第一时隙、减h11乘第二时隙的共轭。这是整段代码最容易写错的地方错一个符号误码率曲线会直接变成0.5左右的平线。蒙特卡洛统计时ber等于错误比特数除以总比特数。这里每个SNR点用1e6比特大约能把BER有效统计到10^{-4}量级如果想看更低的误码率比如10^{-5}建议把numBits提高到5e6以上否则那一点曲线会抖得像信道是随机生成的没法跟理论曲线比。完整脚本其实到这里只有几十行但跑出来的结果和书上理论曲线基本重合。4. 仿真参数与误码率验证怎么把曲线调到和理论4阶分集重合代码能跑只是第一步能不能和Alamouti原始论文的结论对上才是判断这个资源值不值得用的标准。这一章给参数表、理论公式和排查方向。4.1 仿真参数表每个数值都对应一个坑下面这张表是我复现时固定下来的配置照着填基本不会跑偏。参数取值说明调制方式BPSK每符号1比特误码率理论闭式解简单天线配置2×2双发双收等效4分支MRC发射符号能量0.5两发分摊功率总功率与SISO一致信道模型Rayleigh块衰落每2个时隙重新生成信道系数功率1randn/sqrt(2)生成EbN0范围0~20 dB步进2dB共11个点每SNR点数1e6比特BER统计下限约1e-4把发射符号能量写成0.5是很多人不愿意做的事总觉得“我明明按BPSK±1映射的能量就是1啊”。但Alamouti两根天线同时发信号如果要和单天线系统横着比就必须把总功率降下来。这一段是整张表里最值得解释完再填的。信道系数功率设为1也是关键信道功率不对理论曲线永远对不上仿真。4.2 理论误码率4分支MRC公式与Matlab计算2×2 Alamouti方案中每根接收天线收到的是两径叠加等价于4条独立衰落路径上的最大比合并。BPSK在L分支MRC下的误码率有闭式解P_b ((1-μ)/2)^L * Σ_{k0}^{L-1} C(L-1k, k) * ((1μ)/2)^k其中μ sqrt(γ/(1γ))公式里γ是单分支的平均信噪比等于10^(EbN0/10)。在代码中计算时注意组合数用了nchoosekL4。下面是可直接复制的理论曲线片段% 理论4分支MRCBPSKRayleigh L 4; theorBer zeros(size(EbN0_dB)); for snrIdx 1:length(EbN0_dB) gammaBar 10^(EbN0_dB(snrIdx)/10); mu sqrt(gammaBar / (1 gammaBar)); tmp 0; for k 0:L-1 tmp tmp nchoosek(L-1k, k) * ((1mu)/2)^k; end theorBer(snrIdx) ((1-mu)/2)^L * tmp; end semilogy(EbN0_dB, theorBer, r-, LineWidth, 1.5); legend(仿真2x2, 理论4阶分集);运行后仿真曲线应该贴着理论曲线走。如果两条曲线在低SNR区域重叠、在高SNR区域分开优先怀疑随机数统计量不足。值得说明的是这个理论公式针对的是i.i.d. Rayleigh信道如果信道的两根发射天线间距太近导致相关性高或者接收天线间相关实际BER会恶化这一点在Alamouti论文里也有相似结论。做课程设计时通常不管相关性问题但要心里有数。4.3 曲线对不齐时的三个排查方向第一个方向是功率归一化。先算每个接收天线的平均接收功率如果不等于1说明符号能量或信道能量设置偏了。第二个方向是信道更新频率。检查h11等在多少个符号后变化一次如果每个符号都变重新看3.2节。第三个方向是噪声方差。打印EbN010dB时的noiseSigma按噪声Sigma sqrt(1/10^{EbN0/10}/2)核对这一步能排除80%以上的低级错误。我一般把这套排查做成一个check函数每跑完一段数据都自动检查避免到交报告时才后悔没有早验证。5. 避坑与常见问题双发双收仿真里最容易翻车的四个点以下几条是我在给学生审代码、给自己调参时反复遇到的坑。每条都按现象、原因、解决三步写可以直接对应到代码行号排查。5.1 噪声方差算错整条曲线偏移3dB现象仿真BER曲线看起来跟理论一致但整体向右偏移了约3dB或向左偏移导致性能优于理论。原因发射端没有做功率分摊两根天线的总发射功率是SISO的两倍或者噪声方差用了N0而不是N0/2导致实部和虚部叠加后的总噪声功率不是N0在实数判决里被误解。解决把符号能量强制改成0.5并确认复噪声实部、虚部方差各为N0/2。代码里打印一次noiseSigma和mean(abs(s).^2)前者等于sqrt(1/(2*EbN0_linear))后者等于0.5。两个数对了曲线基本就能对齐。5.2 信道没按块衰落生成高信噪比出现误码地板现象仿真BER在EbN0超过14dB后下降变慢看起来像理论曲线不再有斜率。原因每符号独立抽信道导致Alamouti矩阵正交性被破坏合并输出仍残留符号间干扰。用户看到的“地板”不是硬件地板而是干扰受限。解决信道抽样的粒度改成编码块级别即每2个时隙只生成一次信道系数。可以检查h11(1:5)输出看连续两块之间是否变化。仿真中每块独立是允许的只要块内不变即可。5.3 符号能量没分摊2×2曲线和1×2对比失真现象把2×2仿真曲线和1×2曲线放在同一张图2×2好像比理论更好增益超过3dB或者反之。原因对比时2×2发射总功率和1×2不一致。Alamouti方案本身不带来功率增益只有分集增益。如果2×2总功率大一倍曲线自然压低。解决所有天线配置下每个符号的总发射能量都设为1。2×1时每根天线发0.52×2时每根天线仍发0.5。对比前先打印每个配置的平均发射能量确保都是1。5.4 误码率统计样本不足曲线尾部抖动像噪声现象BER曲线在10^{-3}以下呈锯齿状与理论曲线偏差大数值不稳定。原因每个SNR点只发了几万比特统计到的错误比特数太少相对误差大。解决按目标误码率估算采样量。如果想看到10^{-4}的误码率至少需要10^6比特数量级。更实用的习惯是固定总比特数只把每条对比曲线在相同随机种子下的信道序列共用减少曲线之间的差异。6. 扩展玩法从BPSK换到QPSK以及一条验证分集阶数的捷径6.1 QPSK改造映射和判决怎么改把发射端s直接换成QPSK符号代码改动点只有两个映射函数和判决逻辑。QPSK符号可以用(1j)/sqrt(2)之类表示每两个比特构成一个符号发射端需要先把比特流两两分组。接收端s1_hat、s2_hat依然是复数但不能再只看实部。常见做法是依据s1_hat落在哪个象限判决并与发送星座点一一比对误码率统计的是比特错误。如果沿用BPSK的实部判决误码率会卡在25%左右这个现象很典型一眼就能看出来是判决没换。6.2 验证分集阶数看BER曲线斜率拿到新代码时我最常用的验证手段不是盯着绝对数值而是看两条不同配置曲线的斜率差。2×2 Alamouti曲线在高SNR区斜率大约是-41×2大约是-2SISO大约是-1。只要把三种配置的曲线画在一张log坐标图里用最小二乘法在10^{-2}以下的区间拟合斜率就能快速判断实现是否正确。这个方法对BPSK、QPSK都成立比逐点对比理论公式更直观。回到我自己复现这份资源的经历最初拿到脚本时第一版跑出来2×2曲线比理论好3dB我当时以为是代码有“玄学加成”后来打印发射能量才发现是两根天线总功率翻了一倍。从那以后我每次拿到别人的MIMO仿真代码都会强制自己先做两件事打印平均发射能量对比理论曲线的斜率再往下改参数。这个习惯帮我省下了不少和论文对线的时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表