如有專業問題或者需要模擬可以點下面付費諮詢連結。
2020/5/12更新(感謝評論區@趙武休息下 提出的錯誤,已修改。):
挺多同學私信問子載波間隔、頻寬、OFDM符號長度之間的關係?最開始學到這裡可能有點迷糊。我儘量說下我的理解。再加一個例子,大家可以推推。
先定義變數:
:有效資料部分符號時間
:迴圈字首長度
:OFDM符號長度,
:子載波個數
:子載波間隔,
:頻寬,
:取樣時間間隔,
(時域頻域的關係)
:取樣頻率,
(1s的取樣點數)
他們之間的關係:
(1)首先對於OFDM訊號,形象點說在時域上是訊號的疊加。在頻域上是多個子載波並列。
下面以四個子載波(太多了費時)為例畫圖:
時域上圖示
頻域上子載波分佈圖示
(2)子載波間隔等於有效資料部分持續時間的倒數(時域與頻域的關係嘛),也就是
(3)頻寬和子載波的關係,時域上是訊號的疊加,頻域的關係:
可能有人畫圖看了,明顯頻寬不是
呀,比這個大,如下圖
按描述應該為7個,但實際上是8個?
是因為在實際中採用的頻寬並不是整個,如下圖:
頻寬只取有用的那部分,3dB頻寬?
(4)OFDM符號的持續時間,因為迴圈字首是OFDM符號的最後四分之一部分,總的OFDM符號長度就是有效資料部分長度加上迴圈字首長度了:
(5)關於取樣時間間隔
和取樣速率
:
:取樣時間間隔,
(時域頻域的關係)
:取樣頻率,
(1s的取樣點數)
具體舉個例子:
IEEE 802。11a WLAN PHY層標準的主要引數:
IEEE 802。11a WLAN PHY層標準的主要引數
其他引數以保護間隔長度為基礎進行定義。為了把保護間隔所佔用的功率減小到1dB,(OFDM符號長度定為4us,除去GI外有效資料部分的長度為3。2us,進而可得子載波間隔為
。標準採用48個並行子載波進行資料傳輸,這樣當調製方式為BPSK或16QAM時,可以提供的未編碼資料速率分別為
和
。
IEEE 802。11a中使用了52個子載波(實際上應為53個,其中k=0處的直流子載波上不傳輸符號),由於IFFT演算法基於2點,故採用64點的IFFT。53個子載波在頻率分配時分別在編號低端和高階留有6個和5個空符號,即k=一32…,一27,27,…,31,這樣就可以保證系統的子載波頻譜集中,從而使得系統佔用的頻譜頻寬儘可能窄,以節約頻譜資源,減少通道間干擾。所以,52個非零子通道對映到64點輸入的IFFT當中應按照下面圖所指定的方式,把子通道1~26對映到相同標號的IFFT輸入埠;而子通道一26~-1被對映到標記為38~63的IFFT輸入埠;其餘的IFFT輸入埠,即27~37輸入空值。
採用64點IFFT意味著系統的取樣間隔為0.05us,這樣取樣頻率至少應該是20M samples/s。
子載波與IFFT序號的對映關係
原文:
記得點贊喔
記得點贊喔
記得點贊喔
收藏是點讚的幾倍,哭唧唧QAQ
記得看最後的更新!!!!!!!!!!!!!!!
目錄:
一、說明
二、ofdm總體概述
三、基本原理
四、過程中涉及的技術
五、OFDM基本引數的選擇
六、OFDM的MATLAB模擬程式
七、雙擊展開。。。 是不存在的
一、說明
0。能找到這篇文章,說明對ofdm已經有一點了解,所以其原理就不再贅述,這篇程式碼的目的只是希望能對ofdm整個過程有一個理解;
1。看書上ofdm介紹挺簡單的,自己來模擬才發現很多知識點都不知道;
2。花了很長時間才理清整個ofdm過程,網上的程式都是一段一段的,不能直接理解整個過程。所以想著自己來做一個完整過程的模擬,加深理解;
3。基帶訊號能完成整個過程,但是想加進頻帶傳輸這一部分,就完整了;
4。通道部分想用瑞利通道的,程式寫出來了,但是誤差和通道估計這一塊還不是很明白,所以就先用的高斯通道;
5。不足之處歡迎指正。。。。
二、概述
OFDM是一種特殊的多載波傳輸方案,它可以被看作是一種調製技術,也可以被當作一種複用技術。
簡單來說:OFDM是一種多載波的傳輸方法,它將頻帶劃分為多個子通道並行傳輸資料,將高速資料流分成多個並行的低速資料流,然後調製到每個通道的子載波上進行傳輸。由於它將非平坦衰落無線通道轉化成多個正交平坦衰落的子通道,從而可消除通道波形間的干擾,達到對抗多徑衰落的目的。
正交頻分複用(OFDM)是對多載波調製(MCM)的一種改進,在。它的特點是:
各子載波相互正交,所以擴頻調製後的頻譜可以相互重疊,不但減少了子載波間的相互干擾,還大大提高了頻譜利用率。
選擇OFDM的一個很大的原因是該系統能夠很好的對抗頻率選擇性衰落和窄帶干擾。在單載波系統中,一次衰落或者干擾會導致整個鏈路失效,但是在多載波系統中,某一時刻只會有少部分的子通道受到深衰落的影響。
三、基本原理
3.1
OFDM系統收發機的
典型(根據實際需要可添/刪部分)
框圖如下:
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調製器相位的準確性,將會更加精確。
五、OFDM基本引數的選擇
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。
六、OFDM的MATLAB模擬主程式
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);%導頻數量
for img=1:N_fft %資料位置
if mod(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按行取
if data_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));
for jj=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’);
hold on;
semilogy(SNR,Ber,‘r-o’);
hold on;
legend(‘4PSK調製、卷積碼譯碼前(有擴頻)’,‘4PSK調製、卷積碼譯碼後(有擴頻)’);
hold on;
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調製、卷積譯碼、有擴頻’);
七、能看到這裡,如果有丟丟幫助的話,emmmm點個贊~唄
整個程式流程
本來對每一步都有講解註釋的,但是程式編輯多了感覺不美觀,就刪掉了。比如擴頻,其原理、作用、如何實現~
八、程式碼及說明
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
=[];
for
I
=
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);%導頻數量
for img=1:N_fft %資料位置
if mod(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按行取
if data_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));
for jj=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’);
hold on;
semilogy(SNR,Ber,‘r-o’);
hold on;
legend(‘4PSK調製、卷積碼譯碼前(有擴頻)’,‘4PSK調製、卷積碼譯碼後(有擴頻)’);
hold on;
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就行,參考另一篇文章就懂了),連結:
5。本來打算解釋解釋原理的,但是想著網上資料很多,就不獻醜了~
2019.9.12更新:
1。這本來是去年這時候寫的了,寫得很粗糙,不過把整個系統介紹了一下,應該好理解一點。沒想到有這麼多人看,而且還點讚了,十分感謝大家。
2.評論區需要原始碼的同學越來越多,我不能及時看到,所以我設定了關注才能評論。
沒關注的同學私信我留郵箱也可以噠。我還寫了一些其他通訊專業的基礎文章,大家也可以看看。
2020/4/15更新:
3。本文的程式屬很基礎的,我後來在這基礎上用OFDM做了其他的一些通訊模擬,大家應該也用不上就沒寫在這裡面。大家如果是第一次接觸ofdm的話,有一本白色封面的韓國人的書(當然,有 中譯本)挺不錯的,看一看,一週不到就可以了。
書名:MIMO-OFDM無線通訊技術及MATLAB實現
4.因為沒想到這麼多人想要matlab檔案,郵箱懶得發。我傳csdn和GitHub啦。
csdn好像那個積分是系統自己設定的,要是大家有多的可以用積分下載呀( ̄▽ ̄)~*,我也可以攢攢積分啦。
沒有積分就用GitHub吧。
最後,想要個贊啦。