學號:20021210595? ? 姓名:楊嬋
轉載自:https://blog.csdn.net/qq_41687938/article/details/89404046?utm_medium=distribute.pc_feed.none-task-blog-cf-2.nonecase&depth_1-utm_source=distribute.pc_feed.none-task-blog-cf-2.nonecase&request_id=5f3396988c9fb674c6724f02
【嵌牛導讀】本文介紹ofdm的基本原理以及仿真程序
【嵌牛鼻子】ofdm,matalb
【嵌牛提問】ofdm仿真涉及哪些參數和技術
【嵌牛正文】
因為是復制過來,如果出現圖片顯示不完整以及需要源程序請點擊下面鏈接查看原文:
OFDM完整仿真過程及解釋(MATLAB) - 子木的文章 - 知乎 https://zhuanlan.zhihu.com/p/57967971
后面的更新沒有同步,點上面鏈接可以看更新部分。
一、說明
二、ofdm總體概述
三、基本原理
四、過程中涉及的技術
五、OFDM基本參數的選擇
六、OFDM的MATLAB仿真程序
0.能找到這篇文章,說明對ofdm已經有一點了解,所以其原理就不再贅述,這篇代碼的目的只是希望能對ofdm整個過程有一個理解;
1.看書上ofdm介紹挺簡單的,自己來仿真才發現很多知識點都不知道;
2.花了很長時間才理清整個ofdm過程,網上的程序都是一段一段的,不能直接理解整個過程。所以想著自己來做一個完整過程的仿真,加深理解;
3.基帶信號能完成整個過程,但是想加進頻帶傳輸這一部分,就完整了;
4.信道部分想用瑞利信道的,程序寫出來了,但是誤差和信道估計這一塊還不是很明白,所以就先用的高斯信道;
5.不足之處歡迎指正。。。。
OFDM是一種特殊的多載波傳輸方案,它可以被看作是一種調制技術,也可以被當作一種復用技術。
簡單來說:OFDM是一種多載波的傳輸方法,它將頻帶劃分為多個子信道并行傳輸數據,將高速數據流分成多個并行的低速數據流,然后調制到每個信道的子載波上進行傳輸。由于它將非平坦衰落無線信道轉化成多個正交平坦衰落的子信道,從而可消除信道波形間的干擾,達到對抗多徑衰落的目的。
正交頻分復用(OFDM)是對多載波調制(MCM)的一種改進,在。它的特點是:各子載波相互正交,所以擴頻調制后的頻譜可以相互重疊,不但減少了子載波間的相互干擾,還大大提高了頻譜利用率。
選擇OFDM的一個很大的原因是該系統能夠很好的對抗頻率選擇性衰落和窄帶干擾。在單載波系統中,一次衰落或者干擾會導致整個鏈路失效,但是在多載波系統中,某一時刻只會有少部分的子信道受到深衰落的影響。
3.1OFDM系統收發機的典型(根據實際需要可添/刪部分)框圖如下:
OFDM收發機框圖
其中,上半部分對應于發射機鏈路,下半部分對應于接收機鏈路。
發送端將被傳輸的數字信號轉換成子載波幅度和相位的映射,并進行離散傅里葉變換(IDFT),將數據的頻譜表達式變到時域上。IFFT和IDFT變換的作用相同,只是有更高的計算效率,所以適用于所有的應用系統。接收端進行與發送端相反的操作,用FFT變換分解,子載波的幅度和相位最終轉換回數字信號。
這里理解為傳輸的頻域信號是因為IFFT是從頻域到時域,實際上這里IFFT充當的是一個實現子載波正交的作用,具體可以推導其DFT公式。知乎里公式編輯太麻煩了。
3.2 OFDM調制與解調
一個OFDM符號之內包括多個經過調制的子載波的合成信號,其中每個子載波都可以收到psk(相移鍵控)和qam(正交幅度調制)的調制。
OFDM發射機將信息比特流映射成一個psk或qam符號序列,之后將串行的符號序列轉換為并行符號流。每N個經過串并轉換的符號被不同的子載波調制。
OFDM符號是N個并行符號的復合信號,若單個串行符號的傳輸時間(周期)是Ts,則一個OFDM符號的持續時間(周期)Tsym=N*Ts。
頻域調制信號X[k]的頻率為:fk=k/Tsym,子載波數量為N,則k=0,1,2.....N-1。(由DFT原理推導)
為什么要用?怎么用?
4.1 保護間隔
多徑信道會對OFDM符號造成ISI影響,破壞了子載波間的正交性。故需要采取一些方法來消除多徑信道帶來的符號間干擾(ISI)影響,即插入保護間隔。
保護間隔有兩種插入方法:一種是補零(zp),即在保護間隔中填充0;另一種是插入循環前綴(cp)或循環后綴(cs)實現OFDM的循環擴展(為了某種連續性)。
zp是在保護間隔內不插入任何信號,但是在這種情況下,由于多徑傳播的影響,會產生載波間干擾(ICI),即不同的子載波間會產生干擾。
一般采用cp。cp是將OFDM后部的采樣復制到前面,長度為Tcp,故每個符號的長度為Tsym=Tsub+Tcp,Tsub為數據部分子載波數。Tcp大于或等于多徑時延,符號間的ISI影響將被限制在保護間隔中,因此不會影響下一個OFDM的FFT變換。
4.2交織
交織的作用是將突發錯誤轉換為隨機錯誤,有利于前向糾錯碼的譯碼,提高了整個通信系統的可靠性。交織由兩個變換過程組成。第一次變換保證了相鄰的編碼比特被映射到不相鄰的子載波上。第二次變換保證了相鄰的編碼比特被分別映射到星座圖的重要和非重要比特上,避免出現長時間的低比特位映射。
交織塊的長度Ncbps,對qpsk、16qam、64qam分別為2、4、6,s=Ncbps/2,d=16。
4.3信道編碼
由于移動通信存在干擾和衰落,在信號傳輸過程中將出現差錯,故對數字信號必須采用糾、檢錯技術,即糾、檢錯編碼技術,以增強數據在信道中傳輸時抵御各種干擾的能力,提高系統的可靠性。
這里的信道編碼一般采用卷積編碼,Viterbi譯碼。
卷積編碼是現代數字通信系統中常見的一種前向糾錯碼,區別于常規的線性分組碼,卷積編碼的碼字輸出不僅與當前時刻的信息符號輸入有關,還與之前輸入的信息符號有關。
4.4 擴頻
“擴頻通信技術是一種信息傳輸方式,其信號所占有的頻帶寬度遠大于所傳信息必需的最小帶寬;頻帶的擴展是通過一個獨立的碼序列來完成,用編碼及調制的方法來實現的,與所傳信息數據無關;在接收端則用同樣的碼進行相關同步接收、解擴及恢復所傳信息數據”
根據香農定理,帶寬和信噪比可用互換,擴頻擴展了帶寬,則對信噪比的要求可降低。
4.5 導頻
導頻不攜帶信息,導頻是雙方已知的數據,是用來做信道估計的。
在接收機中,雖然利用接收到的段訓練序列、長訓練序列可以進行信道均衡、頻率偏差校正,但符號還會存在一定的剩余偏差,且偏差會隨著時間的累積而累積,會造成所有子載波產生一定的相位偏移。因此,還需要不斷地對參考相位進行跟蹤。要能實現這個功能,需要在52個非0子載波中插入導頻符號。
4.6 RF(射頻)調制
OFDM調制器的輸出產生了一個基帶信號,將此基帶信號與所需傳輸的頻率進行混頻操作,利用模擬技術或數字上變頻可完成。由于數字調制技術提高了處理I、Q信道之間的匹配性和數字IQ調制器相位的準確性,將會更加精確。
5.1 各種OFDM參數的選擇就是需要在多項要求沖突中進行折衷考慮。通常來說,首先要確認3個參數:帶寬、比特率、及保護間隔。
5.1.1 按照慣例,保護間隔的時間長度應該為應用移動環境信道的時延擴展均方根值的2~4倍。
5.1.2 確定保護間隔之后,則OFDM符號周期長度就確定了。為了最大限度的減少由于插入保護比特所帶來的信噪比的損失,OFDM符號周期長度遠遠大于保護間隔長度。但是符號周期又不能任意大,否則就需要更多的子載波,帶寬不變,子載波間隔就變小,系統的實現復雜度就提高了,而且還加大了系統的峰值平均功率比,同時系統對頻率偏差更加敏感。因此,一般選擇符號周期長度是保護間隔的5倍,這樣,由于插入保護比特所造成的信噪比損耗只有1dB左右。
5.1.3 確定保護間隔和符號周期長度之后,子載波的數量可由-3dB帶寬除以子載波間隔(即去掉保護間隔之后的符號周期的倒數)得到。或者可由所要求比特速率除以每個子信道的比特速率來確定子載波的數量。每個信道中所傳輸的比特速率可由調制類型、編碼速率、和符號速率來確定。
5.2 有用符號持續時間T
T對子載波之間間隔、譯碼的等待周期都有影響,為了保持數據的吞吐量,子載波數目和FFT的長度要有相對較大的數量,這就導致符號持續時間變長。總之,符號周期長度的選擇以保證信道的穩定為前提。
5.3 子載波數
N=1/T
其數值與FFT處理過的復數點數相對應,需適應數據速率和保護間隔的要求。
5.4 調制模式
OFDM系統的調制模式基于功率和頻譜利用率來選擇,可采用qam、psk。
為了使所有的點有相同的平均功率,二進制序列映射后的復數要歸一化。(BPSK\QPSK\16QAM\64QAM分別對應乘以1、1/根號2、1/根號10、1/根號42),解調的時候再變回去。
5.5 以具體實例說明;
要求:(1)比特率為25Mbit/s(2)可容忍的時延擴展為200ns(3)帶寬小于18MHz。
1)由200ns時延擴展得保護間隔為800ns;
2)由保護間隔800ns得符號周期長度6*800ns=4.8us;
3)子載波的間隔選取4.8-0.8=4us的倒數,即250KHz;
4)由所要求的比特速率與OFDM符號速率的比值,每個符號需要傳送的比特:(25Mbit/s)/(1/4.8us)=120bit。
5)為了完成上面120bit/符號,有兩種選擇:利用16QAM和碼率為1/2的編碼方法,這樣每個子載波攜帶2bit的有用信息,因此需要60個子載波;另一種是利用QPSK和碼率為3/4的編碼方法,每個子載波攜帶1.5bit信息。因此需要80個子載波,然而80個子載波意外著帶寬:80*250KHz=20MHz,大于所給帶寬要求,故取第一種,即60個子載波。可利用64點IFFT來實現,剩余4個子載波補0.
clc;
clear;
%————————————————————————————————————————————————————————%
%q1:ifft點數難道不是應該等于子載波數嗎?子載波數與ifft點數的關系?
%a:ifft點數等于子載波數
%q2:對矩陣進行fft?
%a:y可以是一向量或矩陣,若y為向量,則Y是y的FFT,并且與y具有相同的長度。若y為一矩陣,則Y是對矩陣的每一列向量進行FFT。
%q3:怎么對ofdm信號上變頻
%————————————————————————————————————————————————————————%
%%參數設置
N_sc=52;? ? ? %系統子載波數(不包括直流載波)、number of subcarrier
N_fft=64;? ? ? ? ? ? % FFT 長度
N_cp=16;? ? ? ? ? ? % 循環前綴長度、Cyclic prefix
N_symbo=N_fft+N_cp;? ? ? ? % 1個完整OFDM符號長度
N_c=53;? ? ? ? ? ? % 包含直流載波的總的子載波數、number of carriers
M=4;? ? ? ? ? ? ? %4PSK調制
SNR=0:1:25;? ? ? ? %仿真信噪比
N_frm=10;? ? ? ? ? ? % 每種信噪比下的仿真幀數、frame
Nd=6;? ? ? ? ? ? ? % 每幀包含的OFDM符號數
P_f_inter=6;? ? ? %導頻間隔
data_station=[];? ? %導頻位置
L=7;? ? ? ? ? ? ? ? %卷積碼約束長度
tblen=6*L;? ? ? ? ? %Viterbi譯碼器回溯深度
stage=3;? ? ? ? ? % m序列的階數
ptap1=[1 3];? ? ? % m序列的寄存器連接方式
regi1=[1 1 1];? ? % m序列的寄存器初始值
%%基帶數據數據產生
P_data=randi([0 1],1,N_sc*Nd*N_frm);
%%信道編碼(卷積碼、或交織器)
%卷積碼:前向糾錯非線性碼
%交織:使突發錯誤最大限度的分散化
trellis=poly2trellis(7,[133 171]);? ? ? %(2,1,7)卷積編碼
code_data=convenc(P_data,trellis);
%%qpsk調制
data_temp1=reshape(code_data,log2(M),[])';? ? ? ? ? ? %以每組2比特進行分組,M=4
data_temp2=bi2de(data_temp1);? ? ? ? ? ? ? ? ? ? ? ? ? ? %二進制轉化為十進制
modu_data=pskmod(data_temp2,M,pi/M);? ? ? ? ? ? ? % 4PSK調制
%figure(1);
scatterplot(modu_data),grid;%星座圖(也可以取實部用plot函數)
%%擴頻
%————————————————————————————————————————————————————————%
%擴頻通信信號所占有的頻帶寬度遠大于所傳信息必需的最小帶寬
%根據香農定理,擴頻通信就是用寬帶傳輸技術來換取信噪比上的好處,這就是擴頻通信的基本思想和理論依據。
%擴頻就是將一系列正交的碼字與基帶調制信號內積
%擴頻后數字頻率變成了原來的m倍。碼片數量=2(符號數)* m(擴頻系數)
%————————————————————————————————————————————————————————%
code=mseq(stage,ptap1,regi1,N_sc);? ? % 擴頻碼的生成
code=code * 2 - 1;? ? ? ? %將1、0變換為1、-1
modu_data=reshape(modu_data,N_sc,length(modu_data)/N_sc);
spread_data=spread(modu_data,code);? ? ? ? % 擴頻
spread_data=reshape(spread_data,[],1);
%%插入導頻
P_f=3+3*1i;? ? ? ? ? ? ? ? ? ? ? %Pilot frequency
P_f_station=[1:P_f_inter:N_fft];%導頻位置(導頻位置很重要,why?)
pilot_num=length(P_f_station);%導頻數量
forimg=1:N_fft? ? ? ? ? ? ? ? ? ? ? ? %數據位置
ifmod(img,P_f_inter)~=1? ? ? ? ? %mod(a,b)就是求的是a除以b的余數
data_station=[data_station,img];
end
end
data_row=length(data_station);
data_col=ceil(length(spread_data)/data_row);
pilot_seq=ones(pilot_num,data_col)*P_f;%將導頻放入矩陣
data=zeros(N_fft,data_col);%預設整個矩陣
data(P_f_station(1:end),:)=pilot_seq;%對pilot_seq按行取
ifdata_row*data_col>length(spread_data)
data2=[spread_data;zeros(data_row*data_col-length(spread_data),1)];%將數據矩陣補齊,補0是虛載頻~
end;
%%串并轉換
data_seq=reshape(data2,data_row,data_col);
data(data_station(1:end),:)=data_seq;%將導頻與數據合并
%%IFFT
ifft_data=ifft(data);
%%插入保護間隔、循環前綴
Tx_cd=[ifft_data(N_fft-N_cp+1:end,:);ifft_data];%把ifft的末尾N_cp個數補充到最前面
%%并串轉換
Tx_data=reshape(Tx_cd,[],1);%由于傳輸需要
%%信道(通過多經瑞利信道、或信號經過AWGN信道)
Ber=zeros(1,length(SNR));
Ber2=zeros(1,length(SNR));
forjj=1:length(SNR)
rx_channel=awgn(Tx_data,SNR(jj),'measured');%添加高斯白噪聲
%%串并轉換
Rx_data1=reshape(rx_channel,N_fft+N_cp,[]);
%%去掉保護間隔、循環前綴
Rx_data2=Rx_data1(N_cp+1:end,:);
%%FFT
fft_data=fft(Rx_data2);
%%信道估計與插值(均衡)
data3=fft_data(1:N_fft,:);
Rx_pilot=data3(P_f_station(1:end),:); %接收到的導頻
h=Rx_pilot./pilot_seq;
H=interp1( P_f_station(1:end)',h,data_station(1:end)','linear','extrap');%分段線性插值:插值點處函數值由連接其最鄰近的兩側點的線性函數預測。對超出已知點集的插值點用指定插值方法計算函數值
%%信道校正
data_aftereq=data3(data_station(1:end),:)./H;
%%并串轉換
data_aftereq=reshape(data_aftereq,[],1);
data_aftereq=data_aftereq(1:length(spread_data));
data_aftereq=reshape(data_aftereq,N_sc,length(data_aftereq)/N_sc);
%%解擴
demspread_data=despread(data_aftereq,code);? ? ? % 數據解擴
%%QPSK解調
demodulation_data=pskdemod(demspread_data,M,pi/M);? ?
De_data1=reshape(demodulation_data,[],1);
De_data2=de2bi(De_data1);
De_Bit=reshape(De_data2',1,[]);
%%(解交織)
%%信道譯碼(維特比譯碼)
trellis=poly2trellis(7,[133 171]);
rx_c_de=vitdec(De_Bit,trellis,tblen,'trunc','hard');? %硬判決
%%計算誤碼率
[err,Ber2(jj)]=biterr(De_Bit(1:length(code_data)),code_data);%譯碼前的誤碼率
[err,Ber(jj)] = biterr(rx_c_de(1:length(P_data)),P_data);%譯碼后的誤碼率
end
figure(2);
semilogy(SNR,Ber2,'b-s');
holdon;
semilogy(SNR,Ber,'r-o');
holdon;
legend('4PSK調制、卷積碼譯碼前(有擴頻)','4PSK調制、卷積碼譯碼后(有擴頻)');
holdon;
xlabel('SNR');
ylabel('BER');
title('AWGN信道下誤比特率曲線');
figure(3)
subplot(2,1,1);
x=0:1:30;
stem(x,P_data(1:31));
ylabel('amplitude');
title('發送數據(以前30個數據為例)');
legend('4PSK調制、卷積譯碼、有擴頻');
subplot(2,1,2);
x=0:1:30;
stem(x,rx_c_de(1:31));
ylabel('amplitude');
title('接收數據(以前30個數據為例)');
legend('4PSK調制、卷積譯碼、有擴頻');
本來對每一步都有講解注釋的,但是程序編輯多了感覺不美觀,就刪掉了。比如擴頻,其原理、作用、如何實現~
1.盡量把每一句程序都注釋,能達到初學者拿到程序就能懂的程度;
2.下面這段程序是上變頻之前的,包含了畫圖,對ofdm信號有一個直觀的感受(與上面圖片中的流程可能沖突,這里僅僅是為了畫圖解釋,所以這也是最開始學容易繞暈的地方)
clear;
%% 參數設置
sub_carriers=2048;%子載波數
T =1/ sub_carriers;
time = [0:T:1-T];% Nifft份,每份相隔T
Lp=4984;
P_Tx=(rand(1,Lp)>0.5);%(bits)%產生1個長為Lp的數據包:
conv_out=convolutional_en(P_Tx);%(卷積編碼):
interleave_table = interleav_matrix(ones(1,2*(Lp+8)));
interleav_out = interleaving(conv_out ,interleave_table);%(交織器)
x=qpsk(interleav_out);%(4QAM 調制)
L=length(x);%信號長度
s=48;
symbol_used_len=L/s;%把輸入分為S個符號,每個符號長為symbol_used_len
%循環前綴的長度
cp=256;
%每一個OFDM符號的抽樣值應補‘0’個數zeros_pad
zeros_pad=sub_carriers-symbol_used_len;
%每一個OFDM符號一側應該補‘0’個數zeros_pad_side
zeros_pad_side=zeros_pad/2;
%對輸入信號進行分割,分割為s個符號,再對每個符號進行FFT運算,實現OFDM解調,并保證能量不變
time_domain_x_link=[];
forI=0:(s-1)
? ? %對輸入進行分割
x_temp=x(I*symbol_used_len+1:I*symbol_used_len+symbol_used_len);
? ? %對每個分割的部分進行補零操作,使其長為sub_carriers
x_temp_pad=[zeros(1,zeros_pad_side),x_temp,zeros(1,zeros_pad_side)];
? ? %對每個符號進行IFFT運算
? ? time_domain_x_temp=ifft(x_temp_pad)*sqrt(sub_carriers);
? ? %對每個符號添加循環前綴
time_domain_x_cp_temp=[time_domain_x_temp(sub_carriers-cp+1:sub_carriers),time_domain_x_temp];
? ? %將符號連接成為串行數據流
? ? time_domain_x_link=[time_domain_x_link,time_domain_x_cp_temp];
end
sum_xI = real(time_domain_x_link);
sum_xQ = imag(time_domain_x_link);
figure;
num=1000;%畫出前num個點
xaxis? = zeros(length(time(1:num)));
plot(time(1:num), sum_xI(1:num),'b:', time(1:num), sum_xQ(1:num),'g:', time(1:num), abs(sum_xI(1:num)+j*sum_xQ(1:num)),'k-', time(1:num), xaxis,'r-');
ylabel('y'),xlabel('t'),
title(['前', num2str(num),'個點經ifft的QAM符號實部之和虛部之和以及實部與虛部的絕對值波形']),
legend('實部之和','虛部之和','絕對值');
3.與上面圖片流程相符的代碼
代碼前面的問題也是我在這個過程中遇到的,困擾了好久,可以帶著問題看看。歡迎討論。
clc;
clear;
%————————————————————————————————————————————————————————%
%q1:fft點數難道不是應該等于子載波數嗎?子載波數與ifft點數的關系?
%q2:對矩陣進行fft?
%q3:怎么對ofdm信號上變頻
%q4:基帶速率是多少?怎么實現?
%q5傳輸頻帶是多少?怎么實現?
%q6子載波間隔是多少?怎么實現?
%q7符號周期是多少?怎么實現?
%————————————————————————————————————————————————————————%
%%參數設置
N_sc=52;? ? ? %系統子載波數(不包括直流載波)、number of subcarrier
N_fft=64;? ? ? ? ? ? % FFT 長度
N_cp=16;? ? ? ? ? ? % 循環前綴長度、Cyclic prefix
N_symbo=N_fft+N_cp;? ? ? ? % 1個完整OFDM符號長度
N_c=53;? ? ? ? ? ? % 包含直流載波的總的子載波數、number of carriers
M=4;? ? ? ? ? ? ? %4PSK調制
SNR=0:1:25;? ? ? ? %仿真信噪比
N_frm=10;? ? ? ? ? ? % 每種信噪比下的仿真幀數、frame
Nd=6;? ? ? ? ? ? ? % 每幀包含的OFDM符號數
P_f_inter=6;? ? ? %導頻間隔
data_station=[];? ? %導頻位置
L=7;? ? ? ? ? ? ? ? %卷積碼約束長度
tblen=6*L;? ? ? ? ? %Viterbi譯碼器回溯深度
stage=3;? ? ? ? ? % m序列的階數
ptap1=[1 3];? ? ? % m序列的寄存器連接方式
regi1=[1 1 1];? ? % m序列的寄存器初始值
%%基帶數據數據產生
P_data=randi([0 1],1,N_sc*Nd*N_frm);
%%信道編碼(卷積碼、或交織器)
%卷積碼:前向糾錯非線性碼
%交織:使突發錯誤最大限度的分散化
trellis=poly2trellis(7,[133 171]);? ? ? %(2,1,7)卷積編碼
code_data=convenc(P_data,trellis);
%%qpsk調制
data_temp1=reshape(code_data,log2(M),[])';? ? ? ? ? ? %以每組2比特進行分組,M=4
data_temp2=bi2de(data_temp1);? ? ? ? ? ? ? ? ? ? ? ? ? ? %二進制轉化為十進制
modu_data=pskmod(data_temp2,M,pi/M);? ? ? ? ? ? ? % 4PSK調制
%figure(1);
scatterplot(modu_data),grid;%星座圖(也可以取實部用plot函數)
%%擴頻
%————————————————————————————————————————————————————————%
%擴頻通信信號所占有的頻帶寬度遠大于所傳信息必需的最小帶寬
%根據香農定理,擴頻通信就是用寬帶傳輸技術來換取信噪比上的好處,這就是擴頻通信的基本思想和理論依據。
%擴頻就是將一系列正交的碼字與基帶調制信號內積
%擴頻后數字頻率變成了原來的m倍。碼片數量=2(符號數)* m(擴頻系數)
%————————————————————————————————————————————————————————%
code=mseq(stage,ptap1,regi1,N_sc);? ? % 擴頻碼的生成
code=code * 2 - 1;? ? ? ? %將1、0變換為1、-1
modu_data=reshape(modu_data,N_sc,length(modu_data)/N_sc);
spread_data=spread(modu_data,code);? ? ? ? % 擴頻
spread_data=reshape(spread_data,[],1);
%%插入導頻
P_f=3+3*1i;? ? ? ? ? ? ? ? ? ? ? %Pilot frequency
P_f_station=[1:P_f_inter:N_fft];%導頻位置(導頻位置很重要,why?)
pilot_num=length(P_f_station);%導頻數量
forimg=1:N_fft? ? ? ? ? ? ? ? ? ? ? ? %數據位置
ifmod(img,P_f_inter)~=1? ? ? ? ? %mod(a,b)就是求的是a除以b的余數
data_station=[data_station,img];
end
end
data_row=length(data_station);
data_col=ceil(length(spread_data)/data_row);
pilot_seq=ones(pilot_num,data_col)*P_f;%將導頻放入矩陣
data=zeros(N_fft,data_col);%預設整個矩陣
data(P_f_station(1:end),:)=pilot_seq;%對pilot_seq按行取
ifdata_row*data_col>length(spread_data)
data2=[spread_data;zeros(data_row*data_col-length(spread_data),1)];%將數據矩陣補齊,補0是虛載頻~
end;
%%串并轉換
data_seq=reshape(data2,data_row,data_col);
data(data_station(1:end),:)=data_seq;%將導頻與數據合并
%%IFFT
ifft_data=ifft(data);
%%插入保護間隔、循環前綴
Tx_cd=[ifft_data(N_fft-N_cp+1:end,:);ifft_data];%把ifft的末尾N_cp個數補充到最前面
%%并串轉換
Tx_data=reshape(Tx_cd,[],1);%由于傳輸需要
%%信道(通過多經瑞利信道、或信號經過AWGN信道)
Ber=zeros(1,length(SNR));
Ber2=zeros(1,length(SNR));
forjj=1:length(SNR)
rx_channel=awgn(Tx_data,SNR(jj),'measured');%添加高斯白噪聲
%%串并轉換
Rx_data1=reshape(rx_channel,N_fft+N_cp,[]);
%%去掉保護間隔、循環前綴
Rx_data2=Rx_data1(N_cp+1:end,:);
%%FFT
fft_data=fft(Rx_data2);
%%信道估計與插值(均衡)
data3=fft_data(1:N_fft,:);
Rx_pilot=data3(P_f_station(1:end),:); %接收到的導頻
h=Rx_pilot./pilot_seq;
H=interp1( P_f_station(1:end)',h,data_station(1:end)','linear','extrap');%分段線性插值:插值點處函數值由連接其最鄰近的兩側點的線性函數預測。對超出已知點集的插值點用指定插值方法計算函數值
%%信道校正
data_aftereq=data3(data_station(1:end),:)./H;
%%并串轉換
data_aftereq=reshape(data_aftereq,[],1);
data_aftereq=data_aftereq(1:length(spread_data));
data_aftereq=reshape(data_aftereq,N_sc,length(data_aftereq)/N_sc);
%%解擴
demspread_data=despread(data_aftereq,code);? ? ? % 數據解擴
%%QPSK解調
demodulation_data=pskdemod(demspread_data,M,pi/M);? ?
De_data1=reshape(demodulation_data,[],1);
De_data2=de2bi(De_data1);
De_Bit=reshape(De_data2',1,[]);
%%(解交織)
%%信道譯碼(維特比譯碼)
trellis=poly2trellis(7,[133 171]);
rx_c_de=vitdec(De_Bit,trellis,tblen,'trunc','hard');? %硬判決
%%計算誤碼率
[err,Ber2(jj)]=biterr(De_Bit(1:length(code_data)),code_data);%譯碼前的誤碼率
[err,Ber(jj)] = biterr(rx_c_de(1:length(P_data)),P_data);%譯碼后的誤碼率
end
figure(2);
semilogy(SNR,Ber2,'b-s');
holdon;
semilogy(SNR,Ber,'r-o');
holdon;
legend('4PSK調制、卷積碼譯碼前(有擴頻)','4PSK調制、卷積碼譯碼后(有擴頻)');
holdon;
xlabel('SNR');
ylabel('BER');
title('AWGN信道下誤比特率曲線');
figure(3)
subplot(2,1,1);
x=0:1:30;
stem(x,P_data(1:31));
ylabel('amplitude');
title('發送數據(以前30個數據為例)');
legend('4PSK調制、卷積譯碼、有擴頻');
subplot(2,1,2);
x=0:1:30;
stem(x,rx_c_de(1:31));
ylabel('amplitude');
title('接收數據(以前30個數據為例)');
legend('4PSK調制、卷積譯碼、有擴頻');
4.上面就是整個基帶傳輸過程,其實上變頻和下變頻也很簡單,將信號分為IQ路,分別乘cos和-sin即可,關于這一步,可以參考我另一篇8PSK調制的文章,在那篇文章里有相似的原理。鏈接:https://blog.csdn.net/qq_41687938/article/details/89514982和賊詳細的8PSK調制與解調詳細過程 - 子木的文章 - 知乎 https://zhuanlan.zhihu.com/p/47258287
5.本來打算解釋解釋原理的,但是想著網上資料很多,就不獻丑了,想打王者了~