理解OFDM技術原理

一、爲什麼要用OFDM?

  通信有一個長期的用戶需求——快,但是又受到可用電磁頻譜的物理限制——少,因而如何在較少可用的頻譜上更快的傳輸信息一直是通信技術發展的核心驅動力。
  常用的單載波傳輸(如ASK,FSK,和PSK等)在一個符號傳輸中使用單個載波承載信息,因而速率較低。想要提高傳輸速度,需要縮短碼元持續時間,對頻帶寬度需求增加,對均衡器和均衡算法要求提高,實現困難。
因而很自然地考慮將頻帶進行劃分,實現一段時域信號中包含多個頻段的信號分量(如下圖),不同頻段的信號承載不同的信息,可以實現多路信號的並行傳輸,常用的技術有FDM和OFDM。
在這裏插入圖片描述
  FDM將頻譜分割成多塊,並在多塊之間設置保護帶寬。這是因爲,保護帶寬可以避免不同頻段之間相互干擾,且便於使用濾波器的調製解調(濾波器一般爲非理想,也即濾波器邊沿不會很陡峭),但這樣會造成頻帶利用率下降。
在這裏插入圖片描述
  OFDM技術就正面直視並解決了這種載波相互干擾的問題,是 一種頻帶使用更加緊湊的特殊FDM ,如下圖。OFDM的解決方法就是引入了正交的特性,這裏正交的意思是,下圖中頻域採樣點(紅色箭頭)只與當前載波頻率有關,不受其他載波影響。這樣就可以在有較高頻帶利用率的情況下並行發送更多信息,也可以說:OFDM技術可以在較少帶寬中更快的發送信息。
在這裏插入圖片描述

二、如何實現OFDM?

  如何才能讓信號具有上圖所示的OFDM頻帶正交的特點呢?請先看下面兩個信號的構造過程:
在這裏插入圖片描述在這裏插入圖片描述
  上面兩個圖都表示,無限長週期正弦信號與同等長度的矩形門函數相乘得到我們常看到的被截斷的有限長載波信號,於此同時頻域完成頻譜的卷積過程得到中心頻點不同的形狀相同的sinc函數。如果將上圖兩個實傳信號相加,其頻譜可如下圖所示:
在這裏插入圖片描述
  先不用關心他們的橫座標對應的數值,上面這個實驗給我們啓發:選取一個長度爲Ts{{T}_{s}}的矩形窗函數乘以不同頻率的正弦信號(或餘弦信號)就可得到OFDM波形。通過傅里葉變換的知識,我們可以知道,矩形窗函數的長度Ts{{T}_{s}}決定着sinc函數的中心頻點距離第一零點的距離Δf\Delta f,如下圖所示(左側時域,右側頻域):
在這裏插入圖片描述在這裏插入圖片描述

  總的來說,要想實現OFDM,只需要滿足各相鄰子載波的頻率最小間隔滿足Δf=1Ts\Delta f=\frac{1}{{{T}_{s}}}

注意:

  • 這裏只是在講多載波頻率如何設置,沒有說幅度和相位的問題,因而可以引入PSK和QAM技術對ODFM進一步加速!
  • 上述爲基帶信號,實際場景在發送前還需要把基帶信號調製到相應的頻段上才能發射出去。

三、 OFDM的工程化實現

方法一:

基帶ODFM信號表達式:z(t)=k=0N1Bkcos(2πfkt)z\left( t \right)=\sum\limits_{k=0}^{N-1}{{{B}_{k}}\cos \left( 2\pi {{f}_{k}}t \right)}
爲了可承載很多的信息比特,z(t)=k=0N1Bke2πfktz\left( t \right)=\sum\limits_{k=0}^{N-1}{{{\mathbf{B}}_{k}}{{e}^{2\pi {{f}_{k}}t}}},其中Bk=ak+jbk{{\mathbf{B}}_{k}}={{a}_{k}}+j{{b}_{k}}
展開後可以得到:
Re{z(t)}=k=0N1akcos(2πfkt)bksin(2πfkt)\operatorname{Re}\left\{ z\left( t \right) \right\}=\sum\limits_{k=0}^{N-1}{{{a}_{k}}\cos \left( 2\pi {{f}_{k}}t \right)-{{b}_{k}}sin\left( 2\pi {{f}_{k}}t \right)}
Im{z(t)}=k=0N1aksin(2πfkt)+bkcos(2πfkt)\operatorname{Im}\left\{ z\left( t \right) \right\}=\sum\limits_{k=0}^{N-1}{{{a}_{k}}sin\left( 2\pi {{f}_{k}}t \right)+{{b}_{k}}\cos \left( 2\pi {{f}_{k}}t \right)}
OFDM射頻信號:
在這裏插入圖片描述其中,sk(t)=akcos2π(fk+fc)tbksin2π(fk+fc)t{{s}_{k}}\left( t \right)={{a}_{k}}\cos 2\pi \left( {{f}_{k}}+{{f}_{c}} \right)t-{{b}_{k}}\sin 2\pi \left( {{f}_{k}}+{{f}_{c}} \right)t
依賴上面推導,可以使用的調製解調架構如下:
在這裏插入圖片描述在這裏插入圖片描述
  通過以上這種方法來實現OFDM信號併發射出去需要耗費很多的混頻器,且要求正弦振盪器和餘弦振盪器嚴格正交,工程實現起來很困難,因而出現了下面基於DFT和IDFT的方法。

方法二:

  OFDM基帶信號z(t)=k=0N1Bke2πfktz\left( t \right)=\sum\limits_{k=0}^{N-1}{{{\mathbf{B}}_{k}}{{e}^{2\pi {{f}_{k}}t}}}和IDFT變換x[n]=1Nk=0N1X[k]ej2πkNnx\left[ n \right]=\frac{1}{N}\sum\limits_{k=0}^{N-1}{X\left[ k \right]{{e}^{j2\pi \frac{k}{N}n}}}在計算結構上很相似,且計算係數都爲離散複數Bk{{\mathbf{B}}_{k}}X[k]X\left[ k \right](這裏不考慮固定係數1N\frac{1}{N}的影響,但不同點在於OFDM基帶表達式的輸出爲連續信號,而IDFT計算得到離散信號,因而他們之間相差一個D/A變換器,也即對IDFT輸出信號進行D/A處理即可得到OFDM基帶信號輸出。
  另外, 需要爲實數(不包含虛部),因而需要根據DFT變換的性質,構造對稱共軛的Bk=[Bk,conj(Bk)]{{\mathbf{{B}'}}_{k}}=\left[ {{\mathbf{B}}_{k}},conj\left( {{\mathbf{B}}_{k}} \right) \right]作爲IDFT的輸入。
  IFFT和FFT是IDFT和DFT的快速實現方法,常用的有基2的FFT和基4的FFT,其通過蝶形運算大大簡化了DFT的計算量。
  基於FFT的OFDM調製解調方法如下:
在這裏插入圖片描述在這裏插入圖片描述

  • 輔助技術一:循環前綴和循環後綴
    ![在這裏插入圖片描述](https://img-blog.csdnimg.cn/2020062115144399.png
      爲了消除碼間串擾(ISI)需要在兩個OFDM符號之間引入保護間隔GI,如果採用全零的簡單保護間隔會引起載波間干擾(ICI),最好的方法是需要添加循環前綴(CP),其長度約爲OFDM符號長度的1/4~1/6。
      通常我們只關注因相鄰OFDM符號滯後引起的ISI而添加CP,在一些場景中也會有超前的情況,同樣的道理需要添加循環後綴(CS)。
    在這裏插入圖片描述  相比於用戶0,用戶1和用戶2分別有滯後和超前的情況,因而需要CP和CS同時使用,添加方法如下所示。
    在這裏插入圖片描述
  • 輔助技術二:餘弦滾降窗
      一個OFDM符號內的多個載波時域疊加,對應地,頻域中多個sinc函數也會疊加,效果如下圖所示。可見其頻譜並不是個理想矩形,而是有明顯的帶外輻射現象。爲了減弱這種帶外輻射,需要對時域多載波疊加信號進行加窗處理,常用的加窗方法是加餘弦窗函數。
    在這裏插入圖片描述
    在這裏插入圖片描述在這裏插入圖片描述

四、基於FFT的OFDM實現Matlab代碼

clear all;
close all;
carrier_count=200;
%這個程序中OFDM子載波個數爲512,其中400即carrier_count*2爲數據符號,其餘賦0值。
symbols_per_carrier=20;%每個子載波上的符號數,在這裏即爲OFDM符號的個數。
bits_per_symbol=4;%OFDM符號的每個子載波上傳輸的比特數。4比特通常採用16QAM調製。
IFFT_bin_length=512;%FFT長度,也即一個OFDM符號的子載波的個數。
PrefixRatio=1/4;%循環前綴的比率,即循環前綴與OFDM符號長度的比值,通常在 1/6~1/4之間。
GI=PrefixRatio*IFFT_bin_length ;%保護間隔的長度,這裏爲128。
beta=1/32;%升餘弦窗的滾降係數。
GIP=beta*(IFFT_bin_length+GI);%循環後綴的長度,這裏爲20
SNR=30; %本程序考慮加性高斯白噪聲信道,這裏信噪比爲30dB。

%===============================OFDM信號產生=============================
baseband_out_length = carrier_count * symbols_per_carrier * bits_per_symbol;
%計算傳輸數據總的比特數,爲200*20*4=16000比特。16000比特的構成爲20個OFDM符號,每個OFDM
%符號200個子載波,每個子載波傳輸4比特信息。
carriers=(1:carrier_count)+(floor(IFFT_bin_length/4) - floor(carrier_count/2));
%計算OFDM符號子載波的序號,carriers中存放的序號是29~228。 
conjugate_carriers = IFFT_bin_length - carriers + 2;
%計算OFDM符號子載波的序號,conjugate_carriers中存放的序號是282~481rand( 'twister',0)
baseband_out=round(rand(1,baseband_out_length));
%產生16000比特待傳輸的二進制比特流。這裏存放的是發送的二進制信號與後面解調後的二進制信號比
%較,可以計算誤碼率。

%16QAM調製並繪製星座圖
complex_carrier_matrix=qam16(baseband_out);
%調用子程序qam16進行16QAM調製。將baseband_out中的二進制比特流,每4比特轉換爲一個16QAM信
%號,即將二進制比特流每4比特轉換爲-3-3j、-3+3j、3-3j、3+3j、-1-3j、-1+3j、1-3j、1+3j、%-3-j、-3+j、3-j、3+j、-1-j、-1+j、1-j、1+j中的一個。轉換後complex_carrier_matrix爲%1*4000矩陣。
complex_carrier_matrix=reshape(complex_carrier_matrix',carrier_count,symbols_per_carrier)';
%轉換complex_carrier_matrix中的數據爲carrier_count*symbols_per_carrier矩陣,這裏爲%20*200矩陣。
figure(1);
plot(complex_carrier_matrix,'*r');% 繪製16QAM星座圖
axis([-4, 4, -4, 4]);
title('16QAM調製後星座圖');
grid on

%IFFT,即進行OFDM調製。
IFFT_modulation=zeros(symbols_per_carrier,IFFT_bin_length);
%將symbols_per_carrier*IFFT_bin_length矩陣賦0值,這裏將20*512矩陣賦0值。這裏512%IFFT的長度,也是OFDM符號子載波的個數。
 IFFT_modulation(:,carriers ) = complex_carrier_matrix ;
%20*200的complex_carrier_matrix的數據賦給IFFT_modulation的第29~228列,即給512個子%載波中的29~229個子載波賦值。
IFFT_modulation(:,conjugate_carriers ) = conj(complex_carrier_matrix);
%20*200的complex_carrier_matrix的數據賦給512個子載波中的第282~481個子載波。
%這段程序構造了512個子載波的OFDM符號,並且各個子載波上的數據是共軛對稱的。這樣做的目的是經過%IFFT後形成的OFDM符號均爲實數。另外,在512個子載波中,僅有400個子載波爲數據,其餘爲0值。相%當於補零,補零的目的是通常IFFT的長度應該爲2的整數次冪。
signal_after_IFFT=ifft(IFFT_modulation,IFFT_bin_length,2);%IFFT實現OFDM調製。
time_wave_matrix=signal_after_IFFT;%
figure(2);
plot(0:IFFT_bin_length-1,time_wave_matrix(2,:));%畫一個OFDM信號的時域表現
axis([0, 512, -0.4, 0.4]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('OFDM Time Signal, One Symbol Period');


%添加循環前綴與循環後綴
XX=zeros(symbols_per_carrier,IFFT_bin_length+GI+GIP);
%IFFT_bin_length+GI+GIP爲OFDM、循環前綴、循環後綴長度之和。
for k=1:symbols_per_carrier
        for i=1:IFFT_bin_length
            XX(k,i+GI)=signal_after_IFFT(k,i);
        end
        for i=1:GI
            XX(k,i)=signal_after_IFFT(k,i+IFFT_bin_length-GI);%添加循環前綴
        end
        for j=1:GIP
            XX(k,IFFT_bin_length+GI+j)=signal_after_IFFT(k,j);%添加循環後綴
        end
end
time_wave_matrix_cp=XX;%帶循環前綴與循環後綴的OFDM符號。
figure(3);
plot(0:length(time_wave_matrix_cp)-1,time_wave_matrix_cp(2,:));
%畫帶循環前綴與循環後綴的OFDM信號的時域波形 
axis([0, 600, -0.3, 0.3]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('OFDM Time Signal with CP, One Symbol Period');
%OFDM符號加窗
windowed_time_wave_matrix_cp=zeros(1,IFFT_bin_length+GI+GIP);
for i = 1:symbols_per_carrier 
windowed_time_wave_matrix_cp(i,:) =real(time_wave_matrix_cp(i,:)).*rcoswindow(beta,IFFT_bin_length+GI)';
%調用rcoswindow產生升餘弦窗,對帶循環前綴與循環後綴的OFDM符號加窗。
end  
figure(4);
plot(0:IFFT_bin_length-1+GI+GIP,windowed_time_wave_matrix_cp(2,:));
%畫加窗後的OFDM符號
axis([0, 700, -0.2, 0.2]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('OFDM Time Signal Apply a Window , One Symbol Period');

%生成發送信號,並串變換
windowed_Tx_data=zeros(1,symbols_per_carrier*(IFFT_bin_length+GI)+GIP);
%注意並串變換後數據的長度爲symbols_per_carrier*(IFFT_bin_length+GI)+GIP,這裏考慮了循環前綴與循環後綴的重疊相加。
windowed_Tx_data(1:IFFT_bin_length+GI+GIP)=windowed_time_wave_matrix_cp(1,:);
%賦第一個加窗帶循環前綴後綴的OFDM符號至windowed_Tx_data,即發送串行數據。
for i = 1:symbols_per_carrier-1 
windowed_Tx_data((IFFT_bin_length+GI)*i+1:(IFFT_bin_length+GI)*(i+1)+GIP)=windowed_time_wave_matrix_cp(i+1,:);%並串變換,循環前綴與循環後綴重疊相加
end
Tx_data_withoutwindow=reshape(time_wave_matrix_cp',(symbols_per_carrier)*(IFFT_bin_length+GI+GIP),1)';
%不加窗數據並串變換
Tx_data=reshape(windowed_time_wave_matrix_cp',(symbols_per_carrier)*(IFFT_bin_length+GI+GIP),1)';
%加窗數據,但按照循環前綴與循環後綴不重疊相加進行並串變換。此時數據長度爲%(symbols_per_carrier)*(IFFT_bin_length+GI+GIP)。
temp_time1 = (symbols_per_carrier)*(IFFT_bin_length+GI+GIP);
%加窗,循環前綴與循環後綴不重疊數據長度,即爲發送的總的數據比特數
figure (5)
subplot(2,1,1);
plot(0:temp_time1-1,Tx_data );%畫循環前綴與循環後綴不重疊相加OFDM信號的時域波形
grid on
ylabel('Amplitude (volts)')
xlabel('Time (samples)')
title('OFDM Time Signal')
temp_time2 =symbols_per_carrier*(IFFT_bin_length+GI)+GIP;
%加窗,循環前綴與循環後綴重疊相加數據長度
subplot(2,1,2);
plot(0:temp_time2-1,windowed_Tx_data);
%畫循環前綴與循環後綴重疊相加OFDM信號的時域波形
grid on
ylabel('Amplitude (volts)')
xlabel('Time (samples)')
title('OFDM Time Signal')

%====================經過加性高斯白噪聲信道=======----================== 
Tx_signal_power = var(windowed_Tx_data);% 計算信號功率
linear_SNR=10^(SNR/10);% 轉換對數信噪比爲線性幅度值
noise_sigma=Tx_signal_power/linear_SNR;%計算噪聲功率,也就是方差
noise_scale_factor = sqrt(noise_sigma);% 計算標準差
noise=randn(1,((symbols_per_carrier)*(IFFT_bin_length+GI))+GIP)*noise_scale_factor;% 產生功率爲noise_scale_factor高斯噪聲
Rx_data=windowed_Tx_data +noise;
%在發送數據上加噪聲,相當於OFDM信號經過加性高斯白噪聲信道。

%==========================OFDM信號解調=============================== 
Rx_data_matrix=zeros(symbols_per_carrier,IFFT_bin_length+GI+GIP);
%存放並行的接收數據
for i=1:symbols_per_carrier
    Rx_data_matrix(i,:)=Rx_data(1,(i-1)*(IFFT_bin_length+GI)+1:i*(IFFT_bin_length+GI)+GIP);% 串並變換
end
Rx_data_complex_matrix=Rx_data_matrix(:,GI+1:GI+IFFT_bin_length);
% 去掉循環前綴與循環後綴,取出OFDM符號傳輸的數據
Y1=fft(Rx_data_complex_matrix,IFFT_bin_length,2);% 求FFT,即OFDM信號解調
Rx_carriers=Y1(:,carriers);
% 取出carriers序號對應的子載波上的發送數據,去掉加入的零及共軛對稱部分
Rx_phase =angle(Rx_carriers);% 計算接收信號的相位特性
Rx_mag = abs(Rx_carriers);% 計算接收信號的幅度特性
[M, N]=pol2cart(Rx_phase, Rx_mag);%轉換極座標數據爲直角座標數據 
Rx_complex_carrier_matrix = complex(M, N);%兩個直角座標的實數據爲構成複數據。
figure(7);
plot(Rx_complex_carrier_matrix,'*r');%畫接收信號的星座圖 
axis([-4, 4, -4, 4]);
title('SNR=30dB接收數據星座圖');
grid on
function [complex_qam_data]=qam16(bitdata)
%輸入參數:bitdata爲二進制數碼流
%輸出參數:complex_qam_data爲16QAM覆信號
X1=reshape(bitdata,4,length(bitdata)/4)';%將二進制數碼流以4比特分段
d=1;
%轉換4比特二進制碼爲十進制碼1~16,生成mapping映射表中的索引。
for i=1:length(bitdata)/4;
    for j=1:4
        X1(i,j)=X1(i,j)*(2^(4-j));
    end
    source(i,1)=1+sum(X1(i,:));
end
%16QAM映射表,該表中存放的是16對,每對兩個實數,標識星座位置。
mapping=[-3*d 3*d; -d  3*d;d  3*d;3*d  3*d;-3*d  d; -d  d; d  d;3*d  d; -3*d  -d; -d  -d; d  -d;3*d  -d;-3*d  -3*d;-d  -3*d; d  -3*d;3*d  -3*d];
for i=1:length(bitdata)/4
    qam_data(i,:)=mapping(source(i),:);%數據映射
end
complex_qam_data=complex(qam_data(:,1),qam_data(:,2));
%組合爲複數形式,形成16QAM信號。
end
function [rcosw]=rcoswindow(beta, Ts) 
%輸入參數:beta爲升餘弦窗滾降係數,Ts爲IFFT長度加循環前綴長度
t=0:(1+beta)*Ts;
rcosw=zeros(1,(1+beta)*Ts);
%計算升餘弦窗,共有三部分
for i=1:beta*Ts;
rcosw(i)=0.5+0.5*cos(pi+ t(i)*pi/(beta*Ts));%計算升餘弦窗第一部分
end
rcosw(beta*Ts+1:Ts)=1;%升餘弦窗第二部分
for j=Ts+1:(1+beta)*Ts+1;
        rcosw(j-1)=0.5+0.5*cos((t(j)-Ts)*pi/(beta*Ts));%計算升餘弦窗第三部分
end
rcosw=rcosw';% 轉換爲列向量
end

參考文章:

  1. 《深入淺出通信原理》,陳愛軍
  2. 《MIMO-OFDM系統原理、應用及仿真》,李莉
  3. 《通信原理》,樊昌信
  4. https://www.bilibili.com/video/BV12z411B7y9?from=search&seid=3227339177102192107
  5. https://blog.csdn.net/qq_16923717/article/details/83623571
  6. https://blog.csdn.net/rs_network/article/details/50682369
  7. https://blog.csdn.net/a493823882/article/details/80058002
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章