)
簡介這是一份面向通信方向初學者與有一定開發(fā)經(jīng)驗的工程師的Matlab源碼包用于計算QPSK調制下誤碼率隨信噪比變化的仿真運行即可直接得到誤碼率-信噪比波形免去自行搭建仿真環(huán)境的麻煩。包內共2個文件一個.m腳本完整實現(xiàn)信號生成、加噪、解調與誤碼率統(tǒng)計代碼注釋詳盡方便逐行閱讀另一個docx文檔給出了算法補充說明可作為擴展學習資料。壓縮包整體僅13KB輕量精簡尤其適合快速下載學習也可用于課程設計或畢業(yè)設計中的通信仿真部分。目前已有854人學習瀏覽經(jīng)過達摩老生親測校正質量可靠值得信任。通過這份資源讀者既能獲得可直接運行的QPSK誤碼率計算程序也能從注釋與文檔中理解仿真設計的完整思路掌握誤碼率性能分析方法減少自主摸索的時間成本。1. 拿到“matlab計算QPSK誤碼率隨信噪比變化的程序源碼”時先想清楚這三件事做QPSK誤碼率隨信噪比變化的仿真是通信方向學生和工程師繞不開的一道基礎題。你手里的這個matlab程序源碼目標不外乎是畫出一條誤碼率曲線讓它從高誤碼區(qū)一路降到低誤碼區(qū)并且跟理論值貼在一起但它真正考你的是信噪比怎么在仿真里換算、噪聲怎么加、統(tǒng)計多少次才算數(shù)。它適合剛開題需要跑通通信仿真流程的在校學生也適合要做鏈路預算或評估編碼增益的射頻工程師。這篇筆記不假裝見過某個具體壓縮包的內容而是把這一類程序背后最常見、最可靠的實現(xiàn)方案完整講透從調制映射到噪聲模型從主循環(huán)到避坑按你會實際動手的順序來。2. QPSK仿真為什么繞不開信噪比換算Eb/N0與SNR的差異與理論基礎2.1 QPSK調制與星座映射比特怎么變成I/Q兩路符號QPSK的全稱是Quadrature Phase Shift Keying一次傳輸兩個比特對應四個相位狀態(tài)。最常見的星座圖是把四個點放在單位圓的四個象限上實部叫I路虛部叫Q路每一路的幅度都是±1/√2這樣每個符號的平均功率剛好是1。做仿真時第一步永遠是把一串隨機的 0/1 比特流切成長度為 2 的塊再按映射表把每一塊變成一個復數(shù)符號。這個切分和映射過程看起來簡單但新手最容易在“比特順序”上翻車。matlab 里常見做法是先reshape成兩列再用bi2de把每一行轉成十進制索引這里要特別注意left-msb和right-msb的選擇它決定 01 和 10 映射到哪個符號。我一般會用格雷映射也就是相鄰相位只差一個比特的映射因為在高信噪比下最常見的錯誤是誤判成相鄰符號格雷映射能讓這類錯誤盡量只引起一個比特錯誤實測誤碼率也更接近理論值。M 4; % QPSK 階數(shù) k log2(M); % 每符號比特數(shù) 2 nBits 100000; % 總仿真比特數(shù) data randi([0 1], nBits, 1); % 隨機二進制信源 bitMatrix reshape(data, k, []); % 每行是一個兩比特組 symbolIdx bi2de(bitMatrix, left-msb); % 比特對 - 0~3 十進制索引這里reshape把長度為nBits的列向量變成nBits/2行 2 列的矩陣每一行對應一個 QPSK 符號。bi2de(..., left-msb)表示左邊的比特是高位于是 00→0、01→1、10→2、11→3。選left-msb還是right-msb會影響星座圖上四點的順序但對后續(xù)誤碼率結果沒有本質影響只要你發(fā)射和接收用同一套就行真正的坑在于后續(xù)de2bi轉回比特時也必須用同一個方向否則解調出來的比特流會完全錯亂曲線直接飄到天上。這一層還要注意不同的 matlab 版本對pskmod的默認映射行為不完全一樣較新版本默認走格雷映射老版本則可能是自然映射。如果你后續(xù)要用手寫判決而不是pskdemod就得保證自己的映射表和調制時用的完全一致否則會出現(xiàn)“星座點明明長得一模一樣誤碼率卻對不上理論曲線”的怪現(xiàn)象。這個細節(jié)在第四章我會專門展開。2.2 AWGN信道下的噪聲模型Eb/N0與SNR的換算公式誤碼率曲線的橫坐標到底用 SNR 還是 Eb/N0是這一類源碼里分歧最大的地方。做通信的人習慣用 Eb/N0因為它把調制階數(shù)的影響剝離開來對比不同調制方式時更公平但 matlab 的awgn函數(shù)只接受功率比 SNR所以你必須自己完成換算。QPSK 里每個符號攜帶 2 個比特符號功率歸一化為 1 時每比特能量 Eb Es/k 1/2。于是SNR_linear EbN0_linear * k SNR_dB EbN0_dB 10*log10(k) EbN0_dB 3.0103這個 3dB 的偏移量是 QPSK 仿真的標志性數(shù)字。如果你把 EbN0_dB 直接當成awgn的 SNR 參數(shù)傳進去實測誤碼率會比理論值偏大約 3dB——也就是曲線整體往左移看起來你“做出了更好的誤碼率曲線”實際上只是噪聲加少了。反過來如果有人拿 BPSKk1沒有這 3dB 偏移的代碼直接改成 QPSK不改換算就會得到完全錯誤的絕對信噪比指標。判斷一段代碼是否靠譜第一眼就應該看它有沒有做這個10*log10(k)的補償。EbN0_dB 6; % 目標每比特信噪比 snr_dB EbN0_dB 10*log10(k); % 換算成符號信噪比 rxSig awgn(txSig, snr_dB, measured);awgn的第三個參數(shù)measured表示先實測信號功率再加噪聲這能避免因濾波器或歸一化殘留導致的功率誤差如果你的調制信號已經(jīng)嚴格歸一化也可以省略這個參數(shù)直接按默認的 0dB 信號功率加噪。但要注意awgn的 SNR 定義是信號功率與噪聲功率之比不是信號幅度與噪聲幅度之比所以當你手寫噪聲時每一維噪聲功率應該是 N0/2而不是 N0。這個“2”是第四章第一個大坑的來源。2.3 理論誤碼率公式用erfc把Q函數(shù)落到matlab里有了星座映射和噪聲模型接下來需要一條理論曲線作為基準。QPSK 在 AWGN 信道下、采用格雷映射時誤碼率理論值可以寫成BER 0.5 * erfc(sqrt(EbN0_lin))這里 EbN0_lin 是線性值不是 dB 值。很多人會把 dB 值直接代進去算出來的理論曲線完全不對。注意這里用的是誤碼率 BER不是誤符號率 SERQPSK 的誤符號率理論值是erfc(sqrt(EbN0_lin))的高階修正形式約等于 BER 的兩倍。拿 SER 的理論值去對比仿真 BER曲線會始終高出一截怎么調噪聲模型都救不回來。EbN0_dB 0:8; EbN0_lin 10.^(EbN0_dB/10); ber_theory 0.5 * erfc(sqrt(EbN0_lin)); semilogy(EbN0_dB, ber_theory, k-, LineWidth, 1.5); hold on;matlab 里erfc是內置函數(shù)不需要額外裝工具箱qfunc也存在于通信工具箱里兩者差一個系數(shù)qfunc(x) 0.5*erfc(x/sqrt(2))。理論上這兩條路寫出來的數(shù)值是一樣的但qfunc在部分老版本里對輸入?yún)?shù)的向量化處理有邊界限制我建議直接用erfc少一層環(huán)境依賴。上面這段代碼把 0 到 8dB 的理論曲線算出來了后面仿真的實測點如果要和它對比橫坐標必須也是 EbN0而不是建模時的符號 SNR。這一節(jié)最后還要強調一個概念Eb/N0 和信噪比 SNR 不是一回事前者是每比特能量對噪聲功率譜密度的比后者是信號功率對噪聲功率的比。兩者之間差了10*log10(k)還差了采樣率相關的因子——如果你后面引入過采樣、匹配濾波或者升余弦脈沖成型SNR 表達式里還會多一項-10*log10(nSamp)。做基帶等效仿真的話我一般建議直接用 EbN0 作為主變量全程換算到符號 SNR 去加噪這樣理論曲線和實測點天然對齊。3. 在matlab里搭起QPSK誤碼率仿真的主循環(huán)信號生成、加噪、判決、統(tǒng)計3.1 用通信工具箱快速跑通第一版pskmod awgn 組合如果你機器上裝了 Communications Toolbox最快的一條路是用pskmod、awgn、pskdemod三個函數(shù)搭主循環(huán)。這個組合的好處是不用自己寫星座映射和最近鄰判決代碼短、出錯面窄特別適合先驗證整體思路。第一版我一般寫成下面這樣clear; clc; M 4; k log2(M); nBits 5e5; % 不要一上來就跑到1e7先小規(guī)模驗證 EbN0_dB 0:2:10; % 偶數(shù)格點先跑通再加密 ber_mc zeros(size(EbN0_dB)); for idx 1:length(EbN0_dB) data randi([0 1], nBits, 1); symIdx bi2de(reshape(data, k, []), left-msb); txSig pskmod(symIdx, M, pi/M, gray); % 格雷映射、相位偏移 pi/4 snr_dB EbN0_dB(idx) 10*log10(k); rxSig awgn(txSig, snr_dB, measured); rxSym pskdemod(rxSig, M, pi/M, gray); rxBits reshape(de2bi(rxSym(:), k, left-msb), [], 1); ber_mc(idx) mean(rxBits ~ data); end這一段里pskmod的第三個參數(shù)pi/M是相位偏移讓四個星座點位于 45°、135°、225°、315°這是 QPSK 教科書里最常見的畫法。第四個參數(shù)gray指定星座映射順序為格雷映射。de2bi(rxSym(:), k, left-msb)返回nSymbols行 2 列的矩陣轉置后按列reshape成 1D 比特流目的是把每個符號的兩位比特按順序排列回去。這行轉置加reshape的順序是所有腳本能否對齊的關鍵建議自己用很小的nBits比如 8單步調試確認映射無誤。mean(rxBits ~ data)是誤碼率的樸素估計它默認你的比特流沒有對齊延遲。如果實際系統(tǒng)中存在傳播延遲或濾波器群延遲你需要先做相關對齊再比較否則誤碼率會假性偏高但在基帶等效的單點仿真里發(fā)射和接收都是理想同步的所以這個簡單寫法沒問題。3.2 不用工具箱的手寫版映射、加噪、判決全流程很多工程機沒有通信工具箱或者你想徹底搞清楚每一步在算什么那就手寫整個鏈路。手寫版更能暴露對噪聲功率譜密度 N0 的理解是否到位我建議至少完整寫一遍即使最后跑通版本用的是工具箱函數(shù)。下面的代碼是完整的手寫版 QPSK 仿真clear; clc; M 4; k 2; constellation [11i, -11i, -1-1i, 1-1i] / sqrt(2); grayMap [0 1 3 2]; % 格雷映射: 00-0, 01-1, 11-3, 10-2 nBits 1e6; EbN0_dB 0:2:10; ber zeros(size(EbN0_dB)); for idx 1:length(EbN0_dB) EbN0_lin 10^(EbN0_dB(idx)/10); N0 1 / (k * EbN0_lin); % 歸一化條件下 Eb 1/k noiseVar N0 / 2; % 實部虛部各占一半噪聲功率 data randi([0 1], nBits, 1); symIdx bi2de(reshape(data, k, []), left-msb); txSig constellation(grayMap(symIdx1)).; noise sqrt(noiseVar) * (randn(size(txSig)) 1i*randn(size(txSig))); rxSig txSig noise; rxSym zeros(size(txSig)); for n 1:length(txSig) [~, minIdx] min(abs(rxSig(n) - constellation)); rxSym(n) grayMap(minIdx); % 映射回十進制索引 end rxBits reshape(de2bi(rxSym(:), k, left-msb), [], 1); ber(idx) mean(rxBits ~ data); end這里的核心是噪聲功率計算。因為星座點歸一化到單位功率符號能量 Es1每比特能量 Eb Es/k 1/k于是 N0 Eb / EbN0_lin 1/(k·EbN0_lin)。高斯白噪聲在 I、Q 兩路各占一半功率所以每路噪聲方差是 N0/2幅度標準差是sqrt(N0/2)。randn(...) 1i*randn(...)產(chǎn)生復高斯噪聲實部虛部獨立同分布這正是 AWGN 的復基帶等價形式。很多手寫代碼忘記給實部虛部分別乘sqrt(0.5)結果總噪聲功率變成 N0 而不是 N0/2實測曲線會整體右移 3dB。判決部分用暴力最近鄰遍歷。constellation只有 4 個點這個循環(huán)開銷可以忽略但如果你后面擴展到 16QAM 或 64QAM建議用knnsearch或者把星座點拆成實部虛部單獨判決否則循環(huán)會拖慢整個仿真。格雷映射在這里體現(xiàn)為grayMap(symIdx1)完成從索引到星座點的查表判決時又把最近的星座點通過grayMap(minIdx)映射回索引保證收發(fā)一致。grayMap的選擇會影響理論 BER 公式——只有格雷映射下0.5*erfc(sqrt(EbN0))才嚴格成立。3.3 把主循環(huán)包裝成腳本數(shù)據(jù)長度、信噪比范圍、隨機種子怎么定跑通單點仿真后要把它擴展成一條完整的曲線就需要考慮三個全局參數(shù)仿真比特數(shù)、信噪比范圍、是否固定隨機種子。固定隨機種子用rng(0)放在腳本開頭能讓每次運行結果可復現(xiàn)——這個習慣在調參階段非常重要否則你每次看到的曲線都是新一批隨機數(shù)無法判斷改動是否有效。rng(0); % 固定隨機種子保證可復現(xiàn) EbN0_dB 0:1:12; % 加密橫坐標但高信噪比區(qū)要加仿真量 nBitsMin 1e5; % 低信噪比區(qū)的基礎樣本數(shù) nBitsMax 2e7; % 高信噪比區(qū)的最大樣本數(shù) ber zeros(size(EbN0_dB)); for idx 1:length(EbN0_dB) if EbN0_dB(idx) 6 nBits nBitsMin; else nBits nBitsMax; end % ... 主仿真鏈路同 3.1 或 3.2復用同一份代碼... ber(idx) sum(errBits) / nBits; end逐點分配nBits的動機是誤碼率的統(tǒng)計精度。誤碼率的相對方差大約正比于1/sqrt(N_errors)在高信噪比區(qū)比如 10dB 以上誤碼率可能只有 1e-6如果還用 1e5 個比特整個仿真過程一個誤碼都碰不到曲線的尾部就會變成 0在 log 坐標上直接掉出圖外。常見做法是先跑一遍粗曲線觀察誤碼率在哪個 EbN0 區(qū)間低于 1e-4然后只對尾段增加樣本數(shù)。我自己的習慣是低信噪比區(qū)用 1e5每上升 2dB 提高一倍樣本量最多跑到 2e7 就打住——再往上不是不能跑而是單次仿真耗時會從秒級變成分鐘級且系統(tǒng)誤差比如awgn的measured估計誤差會開始主導加樣本的錢包邊際收益很低。主循環(huán)的寫法上for循環(huán)逐 dB 掃描最直觀也最容易加打印進度。也可以用arrayfun或parfor并行化但 QPSK 單次仿真本身很快并行化的收益要到大規(guī)模蒙特卡洛掃描時才體現(xiàn)。我更建議先把串行版跑通再用parfor替換最外層的for作為優(yōu)化手段不要在調試階段引入并行。4. 常見避坑與排查誤碼率曲線不平滑、信噪比偏3dB、判決方向不一致4.1 加噪功率算錯實測BER與理論曲線差3dB怎么排查現(xiàn)象仿真出的誤碼率曲線形態(tài)和理論曲線完全一致斜率一樣但整體向左或向右平移約 3dB高信噪比區(qū)尤其明顯。原因幾乎總是噪聲功率多加了或少加了一半。用awgn時把 EbN0 直接傳進去少了10*log10(k)的換算噪聲偏小曲線左移手寫噪聲時把 N0 當成總方差而不是每維方差噪聲偏大曲線右移。排查辦法很簡單在固定 EbN06dB 處打印當前理論的 BER 和實測 BER如果相差正好接近 3dB 對應的數(shù)量級就先檢查換算式里的 k再檢查噪聲方差有沒有多乘 2。EbN0_test 6; EbN0_lin 10^(EbN0_test/10); ber_theory_test 0.5 * erfc(sqrt(EbN0_lin)); % 理論值約為 0.0024實測若明顯小于它大概率是噪聲加少了這個 3dB 偏移的隱蔽之處在于它不改變曲線的形狀只改變橫坐標的偏移所以如果你只畫 semilogy 圖、不對照理論值肉眼很難發(fā)現(xiàn)。我見過不少人拿著一條“看起來很好”的曲線發(fā)到報告里結果評審老師一對照理論曲線就發(fā)現(xiàn)整體平移了。務必在圖上同時畫ber_theory和ber_mc并且兩者用同一橫坐標變量才能暴露這類問題。4.2 高信噪比下誤碼數(shù)為0統(tǒng)計窗口不夠與曲線斷裂現(xiàn)象仿真曲線在 EbN0 超過某個點之后誤碼率變成 0semilogy 圖上曲線突然掉到圖外。這不是系統(tǒng)做了什么神奇優(yōu)化純粹是統(tǒng)計樣本不夠。在誤碼率 1e-5 以下想要測到一個誤碼平均需要 1e5 個比特如果誤碼率為 1e-6你還用 1e6 個比特那么“剛好一個誤碼都沒出現(xiàn)”的概率約等于 37%任何一次仿真都可能撞上。解決思路不是無腦加樣本而是設一個最小誤碼數(shù)目標。targetErrors 100; % 至少統(tǒng)計到 100 個誤碼 while errTotal targetErrors % 繼續(xù)生成新一批數(shù)據(jù)累加誤碼數(shù)與總比特數(shù) % 每批之間共用同一 EbN0 end ber_est errTotal / nBitsTotal;“等夠誤碼數(shù)再停”比“固定跑多少個比特”在統(tǒng)計上更穩(wěn)因為它保證了相對估計誤差大致在 1/sqrt(100)10% 以內。代價是仿真時間不可控所以在循環(huán)里要加最大迭代次數(shù)防止在誤碼率 1e-8 這種極端條件下跑到天荒地老。另一個折中方案是按誤碼率量級分級設nBits像我在 3.3 里寫的那樣大部分場景都夠用。還有一個和零誤碼同源的現(xiàn)象低信噪比區(qū) BER 曲線抖動大。原因是誤碼事件相關性較強尤其在比特級統(tǒng)計時誤碼往往成串出現(xiàn)。解決辦法可以是增大隨機種子重擲次數(shù)把多次獨立仿真的誤碼數(shù)合并再算不要只跑一次就下結論。rng換不同種子跑 5 次取平均誤碼率曲線的光滑度會有明顯改善。4.3 接收端映射方向不一致星座點對了但全錯現(xiàn)象星座圖看起來四相位置完全正確解調的星座點與發(fā)射點重疊但逐比特對比時誤碼率高達 50%。原因是grayMap的使用在發(fā)射和接收兩端不對稱。比如發(fā)射端用pskmod(symIdx, M, pi/M, gray)接收端卻用pskdemod(rxSig, M, pi/M, gray)這兩個版本對同樣的復數(shù)信號解出的符號索引與你的de2bi解釋方式是否一致取決于 matlab 內部映射表的方向。更常見的是手寫映射表時grayMap [0 1 3 2]與pskmod內置的格雷順序不同導致某一象限的判決結果被映射錯。排查方法把發(fā)射的符號索引和接收判決的符號索引直接畫出來對比不要只比較最終的比特流。在nBits8的極小規(guī)模下打印symIdx和rxSym逐項核對。如果只有部分符號錯通常是某一列的比特位順序反了如果全部錯通常是映射表整體錯位。這里最穩(wěn)的寫法是收發(fā)共用同一個映射表常量不要在兩處分別定義。4.4 實部虛部交換一種只在復數(shù)信道上出現(xiàn)的隱蔽錯誤現(xiàn)象誤碼率曲線在高信噪比區(qū)域比理論高出大約一倍且不隨 EbN0 增加而趨于和理論重合而是始終保留一個固定的差距。原因發(fā)射時用txSig constellation(idx).如果寫成constellation(idx)而沒有轉置向量方向不對接收端判決時又恰好按行向量處理導致符號順序錯位。這種方向錯誤在低信噪比時被噪聲掩蓋誤碼率看起來還在理論附近一旦信噪比升高噪聲不再是主導因素系統(tǒng)性的符號錯亂就會顯露出來。% 錯誤寫法txSig 是行向量還是列向量會被后續(xù)加法廣播規(guī)則悄悄改變 txSig constellation(symIdx); % 可能變成行向量 noise sqrt(noiseVar) * randn(1, length(symIdx)); % 行噪聲 % 正確寫法統(tǒng)一為列向量 txSig constellation(symIdx).; noise sqrt(noiseVar) * (randn(length(symIdx), 1) 1i*randn(length(symIdx), 1));這類問題用size()逐一檢查就能發(fā)現(xiàn)但新手往往只盯著誤碼率數(shù)字忽略了中間變量的維度。我建議在每步操作后加一行assert(size(txSig,1) size(noise,1))讓維度錯誤在第一時間爆出來而不是等你對著曲線猜半天。這一條算是血淚經(jīng)驗matlab 的隱式擴展讓很多形狀問題被掩蓋等到最終結果異常時排查成本遠高于一開始的防御性檢查。5. 用三條驗證線路確認仿真沒白跑從單點數(shù)值到整條曲線擬合5.1 先驗單點再驗曲線最后驗斜率很多同學把仿真代碼一跑完看到一條下降的曲線就直接截圖放到報告里。這個習慣隱患很大因為誤碼率曲線只要大方向對了細節(jié)錯誤很難看出來。我給自己的驗證流程是三層第一層選一個中等信噪比點比如 EbN06dB把理論 BER 算出來實測值在它上下 20% 以內才算通過第二層把 0dB 到 4dB 區(qū)間內的實測曲線和理論曲線畫在同一張圖上允許的偏差是每點都在同一數(shù)量級第三層檢查曲線斜率高信噪比區(qū)每增加 1dB誤碼率應顯著下降如果某一段變成平緩甚至回升說明有系統(tǒng)錯誤或仿真點數(shù)不夠。EbN0_check 6; ber_theory_check 0.5 * erfc(sqrt(10^(EbN0_check/10))); ber_mc_check ber(EbN0_dB EbN0_check); fprintf(theory %.4e, simulated %.4e\n, ber_theory_check, ber_mc_check);這層驗證本質上是在檢驗“理論模型”與“仿真模型”的邊界條件是否一致。理論公式假定理想同步、無定時誤差、AWGN 信道如果你的仿真里加入成型濾波、載波同步或多徑信道理論曲線就不再適用這時候對比對象要換成更接近實際系統(tǒng)的鏈路級模型。對于沒有工具箱的純手寫仿真我建議至少保留理論曲線作為 sanity check不要直接拿別人的鏈路預算當基準。5.2 參數(shù)調優(yōu)仿真點數(shù)、信噪比步長、重復次數(shù)怎么取舍做蒙特卡洛 BER 仿真本質是用計算時間換統(tǒng)計精度。下面這張參數(shù)表是我跑 QPSK 時常用的起點按信號處理鏈路復雜度和機器性能調整參數(shù)低配起點標準配置說明每點仿真比特數(shù)1e51e6高信噪比區(qū)至少 1e7EbN0 范圍0:2:120:1:14步長 1dB 夠畫曲線0.5dB 用于精細對比隨機種子rng(0)rng(0) 5 次重復重復次數(shù)多用于低信噪比區(qū)平滑目標最小誤碼數(shù)50100保證相對誤差低于 10%信噪比步長從 2dB 細化到 1dB會直接影響高信噪比區(qū)的曲率表現(xiàn)但代價是總點數(shù)翻倍。如果不確定某個區(qū)間是否需要加密可以先跑 2dB 粗曲線找到曲線拐點通常是誤碼率從 1e-2 到 1e-5 那段再單獨加密這個區(qū)間。樣本數(shù)的分配上一個容易被忽略的點是EbN00dB 附近 BER 約 0.08用 1e5 個比特測試能得到約 8000 個誤碼統(tǒng)計已經(jīng)很穩(wěn)而 EbN010dB 附近 BER 約 4e-6需要 2.5e7 個比特才能得到 100 個誤碼。所以把大部分計算預算投給高信噪比區(qū)永遠是合算的。5.3 圖上驗證semilogy坐標系下的視覺檢查清單仿真結果的呈現(xiàn)方式也會影響排查效率。誤碼率曲線必須用semilogy或loglog在線性坐標下 1e-2 和 1e-5 看起來幾乎都是零無法判斷趨勢。畫圖時把理論曲線畫成實線黑線仿真點在圖上用圓圈標出不要用點線連接起來——仿真點是樣本估計不是連續(xù)函數(shù)用虛線連反而會誤導觀察。檢查時重點看三處曲線末端是否出現(xiàn)平臺期、曲線是否與理論曲線交叉、低信噪比區(qū)是否出現(xiàn)系統(tǒng)性偏移。出現(xiàn)平臺期是零誤碼交叉意味著某個區(qū)段內模型偏差方向反轉常見于映射錯亂或殘余符號間干擾系統(tǒng)性偏移則幾乎總是功率換算問題。semilogy(EbN0_dB, ber_theory, k-, LineWidth, 1.5); hold on; semilogy(EbN0_dB, ber_mc, b-o, MarkerSize, 6); grid on; xlabel(Eb/N0 (dB)); ylabel(BER); legend(Theory, Simulation, Location, southwest);圖本身也是最早能暴露問題的地方如果你的實測點在 0 到 4dB 區(qū)間比理論點低很多誤碼率更小第一反應不應該是高興而是幾乎可以斷定噪聲少加了——這是一個“看起來太好”恰是錯誤信號的高頻場景。反過來實測明顯差于理論則先檢查接收判決方向、噪聲方差、以及比特流對齊這三大元兇。6. 從“能跑”到“能復用”把QPSK腳本改造成參數(shù)化仿真函數(shù)驗證通過之后下一步是把散亂的腳本改造成一個參數(shù)化函數(shù)讓它的輸入是調制階數(shù)、EbN0范圍、目標誤碼數(shù)輸出是 BER 向量和耗時信息。這樣同一套代碼可以復用于 BPSK、16QAM甚至以后擴展 OFDM 子載波仿真。function [ber, EbN0_dB] simulateBER(M, EbN0_dB, doPlot) if nargin 3, doPlot false; end k log2(M); % 星座點和格雷映射表可按 M 生成這里只列 QPSK constellation [11i, -11i, -1-1i, 1-1i] / sqrt(2); grayMap [0 1 3 2]; ber zeros(size(EbN0_dB)); for idx 1:length(EbN0_dB) % 內部復用 3.2 的加噪、判決鏈路 end if doPlot semilogy(EbN0_dB, 0.5*erfc(sqrt(10.^(EbN0_dB/10))), k-); hold on; semilogy(EbN0_dB, ber, b-o); end end函數(shù)化的好處不只是代碼整潔更重要的是把“調制方式選擇”“噪聲模型”“判決規(guī)則”這三個變點隔離出來以后換方案時只需要改星座生成和映射表。我自己最早的 QPSK 腳本就是滿屏全局變量的面條代碼后來在對比 16QAM 時吃了大虧——改動一個參數(shù)結果完全亂了。從那以后我養(yǎng)成的習慣是任何要跑超過三天的仿真腳本第一天就寫成函數(shù)哪怕參數(shù)少也要讓每個輸入變量的含義明確。如果你以后要在這個基礎上做信道編碼對比、加卷積碼或 LDPC還可以把simulateBER里的加噪和判決部分單獨抽成channelModel和demodulator兩個子函數(shù)這樣誤碼率統(tǒng)計邏輯與具體調制方案解耦?;仡^看QPSK 誤碼率仿真永遠是通信鏈路仿真里最透明、最不容易出錯的模塊但恰恰因為簡單很多人忽略了系統(tǒng)化驗證。從固定隨機種子開始到逐點核對樣本量再到最后曲線與理論的吻合每一步都能篩出幾類不同的問題。希望這份操作路徑能幫你少走幾趟彎路也希望你那版源碼跑出來的第一條曲線就是一條跟理論貼得漂亮、可信度經(jīng)得起追問的曲線。本文還有配套的精品資源點擊獲取