Matlab實(shí)現(xiàn):STBC編碼與誤碼率曲線仿真)
簡(jiǎn)介MIMO通信系統(tǒng)Matlab仿真包面向無(wú)線通信方向的在校學(xué)生、科研人員與工程開(kāi)發(fā)者提供了一套完整的多天線系統(tǒng)仿真實(shí)現(xiàn)用于理解空間復(fù)用、分集及波束賦形等關(guān)鍵概念。壓縮包內(nèi)共3個(gè)文件包括兩個(gè).m源程序主程序與訓(xùn)練符號(hào)生成腳本和一份說(shuō)明文檔整體大小僅14KB輕量便于部署。目前已有2135人學(xué)習(xí)。工程基于STBC與OFDM技術(shù)覆蓋信道模型建立、Alamouti空時(shí)分組碼、預(yù)編碼/后編碼、最大似然與MMSE接收解碼、信道估計(jì)等關(guān)鍵模塊并可繪制誤碼率-信噪比曲線。借助該仿真包學(xué)習(xí)者可自由調(diào)整天線數(shù)量、調(diào)制方式和多徑參數(shù)直觀觀察不同配置對(duì)系統(tǒng)容量、頻譜效率及誤碼性能的影響同時(shí)可對(duì)比多種解碼算法的復(fù)雜度與效果適合作為課程實(shí)驗(yàn)、畢業(yè)設(shè)計(jì)或科研論文中的算法驗(yàn)證平臺(tái)。1. MIMO通信系統(tǒng)matlab實(shí)現(xiàn)一套能直接出誤碼率曲線的入門(mén)工程很多人第一次在Matlab里寫(xiě)MIMO仿真都會(huì)卡在同一個(gè)地方算法看得懂但代碼到手總是跑不通要么誤碼率曲線橫著走要么換個(gè)信噪比就報(bào)矩陣奇異。這套MIMO通信系統(tǒng)matlab實(shí)現(xiàn)工程解決的正是這個(gè)問(wèn)題它把發(fā)射端調(diào)制、STBC空時(shí)編碼、瑞利衰落信道、接收端檢測(cè)和信道估計(jì)串成一條完整的仿真鏈跑完直接能畫(huà)出BER曲線還能和前一天的AWGN理論曲線放在一起做對(duì)比。適合通信方向做畢設(shè)的學(xué)生也適合剛接觸無(wú)線物理層、想快速建立鏈路感的工程師拿到手改參數(shù)就能用。2. 整體架構(gòu)從發(fā)射端到接收端的鏈路是怎么拼起來(lái)的2.1 目錄組織一份工程就該有的文件劃分拿到這套工程先別急著點(diǎn)run我把目錄結(jié)構(gòu)翻了一遍它沒(méi)有把所有代碼堆在一個(gè)script里而是按仿真鏈路拆成了配置、主循環(huán)、功能函數(shù)、繪圖四塊。這種組織方式對(duì)二次開(kāi)發(fā)非常友好因?yàn)槟阋奶炀€數(shù)時(shí)不需要去函數(shù)體里大海撈針只需要在配置腳本里動(dòng)兩個(gè)變量。常見(jiàn)布局是這樣的config_params.m全局參數(shù)腳本天線數(shù)、調(diào)制階數(shù)、信噪比范圍、蒙特卡洛次數(shù)全都集中在這里。main_ber_simulation.m主程序負(fù)責(zé)把發(fā)射、信道、接收、檢測(cè)串起來(lái)。function/功能函數(shù)目錄里面放STBC編碼器、信道生成器、檢測(cè)器、信道估計(jì)函數(shù)。plot_results.m繪圖腳本畫(huà)誤碼率曲線時(shí)對(duì)比不同檢測(cè)算法。我一般拿到這種工程會(huì)先做一件事在配置腳本里把Nt 2; Nr 2;改成Nt 4; Nr 4;然后直接跑一次如果主程序不需要任何改動(dòng)就能跑通說(shuō)明模塊間的接口設(shè)計(jì)是合格的。這套工程的設(shè)計(jì)思路就是這樣函數(shù)與函數(shù)之間只傳矩陣和參數(shù)不依賴(lài)全局變量滿天飛信號(hào)流方向從發(fā)射端一路到接收端非常清晰。2.2 發(fā)射端調(diào)制、STBC編碼與功率歸一化發(fā)射端第一步是把比特流映射成符號(hào)。這套工程用的是QPSK調(diào)制映射方式選的是Gray編碼即相鄰星座點(diǎn)之間只差一個(gè)比特這樣在高信噪比下少數(shù)一次判決錯(cuò)誤只帶來(lái)一個(gè)bit翻轉(zhuǎn)誤碼率會(huì)比自然映射好看一些。% config_params.m 關(guān)鍵參數(shù) Nt 2; % 發(fā)射天線數(shù) Nr 2; % 接收天線數(shù) modOrder 4; % QPSK Es 1; % 符號(hào)能量 numSymbols 1e4; % 每根天線的符號(hào)數(shù) % 發(fā)射端生成比特流 - QPSK符號(hào) - STBC編碼 dataBits randi([0 1], Nt, numSymbols * log2(modOrder)); symbols pskmod(dataBits, modOrder, pi/4, gray); % 每行是一根天線的符號(hào)流pskmod的第四個(gè)參數(shù)pi/4是星座旋轉(zhuǎn)角作用是避免星座點(diǎn)落在坐標(biāo)軸上便于可視化時(shí)區(qū)分第五個(gè)參數(shù)gray指定使用格雷映射。這里有個(gè)容易被忽略的細(xì)節(jié)符號(hào)能量Es被歸一化成了1這意味著在功率分配上每根天線發(fā)射的平均功率是相等的功率歸一化放到STBC里還要再做一次。STBC編碼用的是2x2 Alamouti碼這也是2發(fā)2收MIMO最經(jīng)典的編碼方式核心思想是把兩個(gè)符號(hào)在兩根天線和兩個(gè)時(shí)隙上展開(kāi)形成正交矩陣從而在接收端可以解耦出兩路信號(hào)獲得滿分集增益function code alamouti_encode(s1, s2) % 輸入: 兩個(gè)時(shí)隙的QPSK符號(hào) % 輸出: 2x2矩陣, 行是天線, 列是時(shí)隙 code [s1, -conj(s2); s2, conj(s1)]; end編碼矩陣的每一行對(duì)應(yīng)一根天線每一列對(duì)應(yīng)一個(gè)符號(hào)周期。第一根天線第一個(gè)時(shí)隙發(fā)s1、第二個(gè)時(shí)隙發(fā)-conj(s2)第二根天線反過(guò)來(lái)和第一根天線形成正交關(guān)系。接收端的優(yōu)勢(shì)在于這種正交設(shè)計(jì)讓我們不需要用復(fù)雜的線性檢測(cè)就能對(duì)兩路符號(hào)獨(dú)立做匹配這是Alamouti碼教科書(shū)式的結(jié)論也是這套工程把它作為默認(rèn)發(fā)射方案的原因。2.3 信道模型瑞利衰落與信噪比換算MIMO仿真的精髓在信道。這套工程用的是平坦瑞利衰落信道每個(gè)符號(hào)周期內(nèi)信道系數(shù)不變符號(hào)與符號(hào)之間獨(dú)立刷新天線間信道矩陣元素服從零均值復(fù)高斯分布實(shí)部和虛部方差各占二分之一% 信道生成: Nr x Nt 復(fù)高斯矩陣, 方差歸一化為1 H (randn(Nr, Nt) 1i*randn(Nr, Nt)) / sqrt(2); % 噪聲: 復(fù)高斯白噪聲, 方差由信噪比決定 noiseVar Es / (10^(snr_linear)); noise (randn(Nr, size(code,2)) 1i*randn(Nr, size(code,2))) ... / sqrt(2) * sqrt(noiseVar); % 接收信號(hào) Y H * code noise;這里最值得說(shuō)的是信噪比換算。工程里主循環(huán)遍歷的是EbN0_dB每比特信噪比但仿真時(shí)用在加性白噪聲方差里的是符號(hào)信噪比SNR兩者差一個(gè)log2(modOrder) * codeRate因子也就是每個(gè)符號(hào)攜帶的比特?cái)?shù)。在2x2 Alamouti配置下兩個(gè)時(shí)隙共傳兩個(gè)符號(hào)共4個(gè)比特碼率恰好是1所以SNR_dB EbN0_dB 10*log10(2)這個(gè)3dB的偏移是誤碼率曲線對(duì)齊理論值的關(guān)鍵很多曲線對(duì)不齊的翻車(chē)現(xiàn)場(chǎng)都出自這里。3. 核心算法拆解檢測(cè)器、信道估計(jì)與性能對(duì)比3.1 線性檢測(cè)ZF與MMSE的矩陣判決發(fā)射端先不討論STBC把接收信號(hào)模型簡(jiǎn)寫(xiě)成通用的空間復(fù)用形式Y(jié) H * S N其中S是Nt行、每個(gè)時(shí)隙一個(gè)符號(hào)的發(fā)送矩陣。檢測(cè)器要做的事情就是從Y里把S估計(jì)回來(lái)。這套工程實(shí)現(xiàn)了兩種線性檢測(cè)算法零均衡和最小均方誤差檢測(cè)。% ZF 檢測(cè): 直接求偽逆, 完全消除信道影響 W_zf (H * H) \ H; S_hat_zf W_zf * Y; % MMSE 檢測(cè): 在偽逆基礎(chǔ)上加噪聲方差項(xiàng) snrInv noiseVar / Es; W_mmse (H * H snrInv * eye(Nt)) \ H; S_hat_mmse W_mmse * Y;兩種檢測(cè)器差別不大就一行代碼的區(qū)別但行為差異很明顯。ZF追求把信道影響完全抵消付出的代價(jià)是放大了噪聲尤其在信道矩陣接近奇異時(shí)對(duì)噪聲的放大近乎失控所以低信噪比時(shí)誤碼率會(huì)很慘。MMSE在求逆時(shí)顯式加了一個(gè)snrInv * eye(Nt)項(xiàng)相當(dāng)于在“消除信道”和“抑制噪聲”之間取了折中這個(gè)加的對(duì)角陣系數(shù)就是信噪比的倒數(shù)信噪比越低正則項(xiàng)越大越傾向于濾掉噪聲。實(shí)踐中我一般會(huì)讓工程里兩個(gè)檢測(cè)器共用同一個(gè)主循環(huán)同一條信道跑完再切換方式這樣對(duì)比曲線才有意義。3.2 最大似然檢測(cè)遍歷星座組合的上限曲線線性檢測(cè)復(fù)雜度低但性能不是最優(yōu)工程里還配了一個(gè)最大似然檢測(cè)器作為性能上限參考。ML的思路非常暴力遍歷所有可能的發(fā)送符號(hào)組合找到讓接收信號(hào)與理想信號(hào)距離最近的那一組。在2發(fā)2收QPSK下四選一的16種組合窮舉完全可行function s_hat ml_detect(Y, H, constellation) % Y: Nr x T; H: Nr x Nt % constellation: QPSK四個(gè)星座點(diǎn) [Nr, T] size(Y); M length(constellation); s_hat zeros(Nt, T); for t 1:T bestDist inf; for n1 1:M for n2 1:M s_candidate [constellation(n1); constellation(n2)]; dist norm(Y(:,t) - H * s_candidate)^2; if dist bestDist bestDist dist; s_hat(:,t) s_candidate; end end end end end這段代碼把每個(gè)時(shí)隙的符號(hào)獨(dú)立判決。norm(...)^2計(jì)算的是接收向量與假設(shè)發(fā)送向量經(jīng)過(guò)信道后的歐氏距離距離最小者勝出。注意變量dist要和bestDist做對(duì)比初始值設(shè)為inf保證第一輪肯定能進(jìn)入更新分支。ML的性能是所有檢測(cè)算法的上限但復(fù)雜度隨天線數(shù)和調(diào)制階數(shù)指數(shù)爆炸比如4發(fā)4收16QAM就有16^4 65536種組合跑一次蒙特卡洛循環(huán)會(huì)慢到讓你懷疑人生。一般我會(huì)用ML曲線做2x2小配置的基準(zhǔn)線大配置只跑ZF和MMSE。3.3 導(dǎo)頻輔助的信道估計(jì)最小二乘估計(jì)與歸一化仿真里接收端直接拿到了完美信道H但實(shí)際系統(tǒng)信道矩陣是不知道的所以這套工程給出了一個(gè)最小二乘信道估計(jì)模塊。方法是在數(shù)據(jù)符號(hào)前插入收發(fā)兩端都知道的導(dǎo)頻序列用導(dǎo)頻位置接收到的信號(hào)反推信道function H_est ls_channel_estimate(Y_pilot, X_pilot) % X_pilot: Nt x Np 已知導(dǎo)頻 % Y_pilot: Nr x Np 導(dǎo)頻接收信號(hào) % 每根天線獨(dú)立做LS估計(jì) [Nr, Np] size(Y_pilot); Nt size(X_pilot, 1); H_est zeros(Nr, Nt); for rx 1:Nr % 最小二乘解: (X_pilot*X_pilot)^(-1) * X_pilot * y_rx H_est(rx, :) (X_pilot * X_pilot) \ X_pilot * Y_pilot(rx, :).; end end每個(gè)接收天線獨(dú)立估計(jì)出它到所有發(fā)射天線的信道增益。關(guān)鍵點(diǎn)是導(dǎo)頻矩陣要設(shè)計(jì)成行滿秩這樣X(jué)_pilot * X_pilot才可逆常見(jiàn)做法是讓導(dǎo)頻序列之間保持正交比如用Hadamard矩陣的行。工程里默認(rèn)導(dǎo)頻符號(hào)數(shù)Np等于發(fā)射天線數(shù)滿足可辨識(shí)條件。估計(jì)出來(lái)的信道直接用在下游的ZF或MMSE檢測(cè)里你可以在主循環(huán)里加一個(gè)配置開(kāi)關(guān)在“完美信道”和“LS估計(jì)信道”之間切換觀察信道估計(jì)誤差帶來(lái)的性能損失這個(gè)損失在2x2下大約有1dB左右放4x4會(huì)更明顯。4. 運(yùn)行與調(diào)試參數(shù)配置、曲線復(fù)現(xiàn)與常見(jiàn)問(wèn)題排查4.1 主循環(huán)與參數(shù)腳本整個(gè)仿真跑起來(lái)就一個(gè)入口所有可調(diào)項(xiàng)都在config_params.m里。主循環(huán)的結(jié)構(gòu)是典型的三層嵌套外層遍歷信噪比中層做蒙特卡洛平均內(nèi)層是發(fā)射信道接收檢測(cè)EbN0_dB 0:2:20; numTrials 100; % 每個(gè)信噪比下仿真次數(shù) ber_zf zeros(size(EbN0_dB)); ber_mmse zeros(size(EbN0_dB)); for idx 1:length(EbN0_dB) % 每比特信噪比轉(zhuǎn)符號(hào)信噪比: 需要考慮每個(gè)符號(hào)攜帶的比特?cái)?shù) snr_dB EbN0_dB(idx) 10*log10(log2(modOrder) * codeRate); noiseVar Es / (10^(snr_dB/10)); errZ 0; errM 0; totalBits 0; for trial 1:numTrials % 1. 發(fā)射端STBC編碼 % 2. 生成信道和噪聲 % 3. 分別用ZF / MMSE檢測(cè) % 4. 解調(diào)并統(tǒng)計(jì)誤比特?cái)?shù) end ber_zf(idx) errZ / totalBits; ber_mmse(idx) errM / totalBits; endnumTrials的取值直接影響曲線平滑度和運(yùn)行時(shí)間。我個(gè)人的習(xí)慣是先設(shè)10試跑一遍流程通不通確認(rèn)無(wú)誤碼率曲線形狀合理再開(kāi)100跑最終結(jié)果。運(yùn)行時(shí)間跟天線數(shù)和符號(hào)數(shù)是二次方關(guān)系4x4配置下建議把numSymbols降到2000不然一個(gè)完整信噪比范圍能跑到你懷疑電腦是不是死機(jī)了。4.2 復(fù)現(xiàn)第一張BER曲線的步驟想最快看到效果按我這個(gè)順序操作就行。第一步打開(kāi)config_params.m確認(rèn)Nt 2; Nr 2;modOrder 4這兩個(gè)參數(shù)組合下仿真速度最快。第二步直接運(yùn)行main_ber_simulation.m等進(jìn)度條走完命令窗口會(huì)打印出每個(gè)信噪比下的誤碼率。第三步運(yùn)行plot_results.m這時(shí)候會(huì)彈出兩張圖一張是ZF和MMSE的誤碼率對(duì)比另一張是容量隨信噪比變化的曲線圖。常見(jiàn)的坑是第一張圖里只有一條曲線因?yàn)樵肼曁蜁r(shí)MMSE和ZF收斂到一起了這是正常的不是代碼有問(wèn)題。真正要檢查的是曲線的斜率如果誤碼率隨信噪比增長(zhǎng)下降得比理論曲線慢很多多半是發(fā)射端功率歸一化沒(méi)做對(duì)回到2.2節(jié)確認(rèn)Es和編碼矩陣之間沒(méi)有多乘或少乘因子。4.3 排查從曲線不對(duì)到矩陣病態(tài)的踩坑記錄現(xiàn)象一總算完誤碼率結(jié)果恒等于0.5曲線平得像一條直線。原因幾乎是QPSK解映射和調(diào)制方式不匹配比如pskmod用的相位偏移是pi/4pskdemod也必須是同一個(gè)偏移否則每個(gè)符號(hào)都偏了一個(gè)固定角度判決結(jié)果等于隨機(jī)猜。解決方法是檢查收發(fā)兩端調(diào)制參數(shù)是否一字不差地一致?,F(xiàn)象二BER曲線在低信噪比區(qū)間飄忽不定在高信噪比區(qū)間又過(guò)于陡峭。原因通常是蒙特卡洛次數(shù)不夠高信噪比下誤碼率本身就低比如真實(shí)值是1e-5你只跑了1000個(gè)符號(hào)總共一個(gè)bit差錯(cuò)都沒(méi)有誤碼率統(tǒng)計(jì)出來(lái)是0畫(huà)在log坐標(biāo)上就是斷崖。解決方法是按目標(biāo)誤碼率反推最少符號(hào)數(shù)想看1e-4至少要傳10萬(wàn)個(gè)符號(hào)以上才可信?,F(xiàn)象三4x4配置跑著跑著拋出“矩陣接近奇異值”警告。原因是ZF求inv(H*H)時(shí)信道矩陣偶然出現(xiàn)病態(tài)尤其天線數(shù)多的時(shí)候這個(gè)概率會(huì)變大。解決方法是不要用inv顯式求逆改成(H*H) \ (H*Y)這種左除寫(xiě)法Matlab內(nèi)部會(huì)用高斯消元法處理數(shù)值穩(wěn)定性好很多或者直接切到MMSE檢測(cè)器多出來(lái)的正則項(xiàng)天然能壓制病態(tài)?,F(xiàn)象四曲線整體向右偏移且偏移量恰好是整數(shù)倍dB。原因是信噪比定義沒(méi)統(tǒng)一檢查是否把EbN0直接當(dāng)成了SNR來(lái)算噪聲方差。這個(gè)翻車(chē)點(diǎn)幾乎每個(gè)做通信仿真的都踩過(guò)記住一個(gè)口訣加性白噪聲是加在符號(hào)上的方差只認(rèn)符號(hào)信噪比。5. 二次開(kāi)發(fā)思路從STBC切換空間復(fù)用與實(shí)測(cè)信道接口這套工程的改造空間很大核心思路是把發(fā)射方案和檢測(cè)器解耦改成空間復(fù)用結(jié)構(gòu)。步驟是刪掉alamouti_encode讓兩根天線各自發(fā)送獨(dú)立的符號(hào)流接收端信號(hào)模型從Y H * code N變成Y H * S N其中S是2 x T矩陣。檢測(cè)器代碼完全不用改因?yàn)閆F和MMSE本來(lái)就建立在復(fù)用模型上ML檢測(cè)器也一樣能跑。切換后你會(huì)發(fā)現(xiàn)誤碼率比STBC差一些但頻譜效率翻倍了這是一個(gè)很典型的“分集與復(fù)用”取舍實(shí)驗(yàn)。再往后走可以試著把理想信道換成帶測(cè)量誤差的信道。工程里有一個(gè)信道估計(jì)的開(kāi)關(guān)把H替換成H_est跑一遍就能量化估計(jì)誤差對(duì)誤碼率的影響。如果要進(jìn)一步貼近實(shí)際系統(tǒng)我一般會(huì)用Matlab自帶的CDL信道模型替換平坦瑞利信道只需要寫(xiě)一個(gè)封裝函數(shù)把CDL輸出的沖激響應(yīng)卷進(jìn)發(fā)送信號(hào)里接口保持H的形態(tài)不變主程序邏輯一行都不用動(dòng)。這個(gè)改法的好處是不用碰檢測(cè)器訓(xùn)練對(duì)“接口穩(wěn)定”的直覺(jué)比反復(fù)調(diào)參更有價(jià)值。最后一個(gè)建議是給自己留一張對(duì)照表把調(diào)過(guò)的參數(shù)和對(duì)應(yīng)的性能變化記錄下來(lái)從那次之后我每次拆一個(gè)新工程都會(huì)強(qiáng)制自己走一遍“先看目錄、再跑基準(zhǔn)、最后做一次檢測(cè)器替換實(shí)驗(yàn)”的流程順著這條思路改代碼出問(wèn)題也能按層排查不會(huì)陷入亂試參數(shù)的泥潭。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取