MATLAB程序:OFDM信號發送與接收

clear all;
close all;
carrier_count=200;%子載波數
symbols_per_carrier=12;%每子載波含符號數
bits_per_symbol=4;%每符號含比特數,16QAM調製
IFFT_bin_length=512;%FFT點數
PrefixRatio=1/4;%保護間隔與OFDM數據的比例 1/6~1/4
GI=PrefixRatio*IFFT_bin_length ;%每一個OFDM符號添加的循環前綴長度爲1/4*IFFT_bin_length  即保護間隔長度爲128
beta=1/32;%窗函數滾降係數
GIP=beta*(IFFT_bin_length+GI);%循環後綴的長度20
SNR=15; %信噪比dB
%==================================================
%================信號產生===================================
baseband_out_length = carrier_count * symbols_per_carrier * bits_per_symbol;%所輸入的比特數目  200*12*4
carriers = (1:carrier_count) + (floor(IFFT_bin_length/4) - floor(carrier_count/2));%共軛對稱子載波映射  複數數據對應的IFFT點座標
conjugate_carriers = IFFT_bin_length - carriers + 2;%共軛對稱子載波映射  共軛複數對應的IFFT點座標
rand( 'twister',0);
baseband_out=round(rand(1,baseband_out_length));%輸出待調製的二進制比特流
%==============16QAM調製====================================

complex_carrier_matrix=qam16(baseband_out);%列向量

complex_carrier_matrix=reshape(complex_carrier_matrix',carrier_count,symbols_per_carrier)';%symbols_per_carrier*carrier_count 矩陣

figure(1);
plot(complex_carrier_matrix,'*r');%16QAM調製後星座圖
axis([-4, 4, -4, 4]);
grid on
%=================IFFT===========================
IFFT_modulation=zeros(symbols_per_carrier,IFFT_bin_length);%添0組成IFFT_bin_length IFFT 運算 
IFFT_modulation(:,carriers ) = complex_carrier_matrix ;%未添加導頻信號 ,子載波映射在此處
IFFT_modulation(:,conjugate_carriers ) = conj(complex_carrier_matrix);%共軛複數映射
%========================================================
figure(2);
stem(0:IFFT_bin_length-1, abs(IFFT_modulation(2,1:IFFT_bin_length)),'b*-')%第一個OFDM符號的頻譜
grid on
axis ([0 IFFT_bin_length -0.5 4.5]);
ylabel('Magnitude');
xlabel('IFFT Bin');
title('OFDM Carrier Frequency Magnitude');

figure(3);
plot(0:IFFT_bin_length-1, (180/pi)*angle(IFFT_modulation(2,1:IFFT_bin_length)), 'go')
hold on
stem(0:carriers-1, (180/pi)*angle(IFFT_modulation(2,1:carriers)),'b*-');%第一個OFDM符號的相位
stem(0:conjugate_carriers-1, (180/pi)*angle(IFFT_modulation(2,1:conjugate_carriers)),'b*-');
axis ([0 IFFT_bin_length -200 +200])
grid on
ylabel('Phase (degrees)')
xlabel('IFFT Bin')
title('OFDM Carrier Phase')
%=================================================================

signal_after_IFFT=ifft(IFFT_modulation,IFFT_bin_length,2);%OFDM調製 即IFFT變換
time_wave_matrix =signal_after_IFFT;%時域波形矩陣,行爲每載波所含符號數,列ITTF點數,N個子載波映射在其內,每一行即爲一個OFDM符號
figure(4);
subplot(3,1,1);
plot(0:IFFT_bin_length-1,time_wave_matrix(2,:));%第一個符號的波形
axis([0, 700, -0.2, 0.2]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('OFDM Time Signal, One Symbol Period');

%===========================================================
%=====================添加循環前綴與後綴====================================
XX=zeros(symbols_per_carrier,IFFT_bin_length+GI+GIP);%GI=128,GIP=20
for k=1:symbols_per_carrier;%12
    for i=1:IFFT_bin_length;%512
        XX(k,i+GI)=signal_after_IFFT(k,i);%129--640
    end
    for i=1:GI;%1--128
        XX(k,i)=signal_after_IFFT(k,i+IFFT_bin_length-GI);%添加循環前綴  %後128個數據放到前面
    end
    for j=1:GIP;
        XX(k,IFFT_bin_length+GI+j)=signal_after_IFFT(k,j);%添加循環後綴  前20個數據放到後面
    end
end

time_wave_matrix_cp=XX;%添加了循環前綴與後綴的時域信號矩陣,此時一個OFDM符號長度爲IFFT_bin_length+GI+GIP=660
subplot(3,1,2);
plot(0:length(time_wave_matrix_cp)-1,time_wave_matrix_cp(2,:));%第一個符號添加循環前綴後的波形
axis([0, 700, -0.2, 0.2]);
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 %12
windowed_time_wave_matrix_cp(i,:) = real(time_wave_matrix_cp(i,:)).*rcoswindow(beta,IFFT_bin_length+GI)';%加窗  升餘弦窗
end  
subplot(3,1,3);
plot(0:IFFT_bin_length-1+GI+GIP,windowed_time_wave_matrix_cp(2,:));%第一個符號的波形
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);
windowed_Tx_data(1:IFFT_bin_length+GI+GIP)=windowed_time_wave_matrix_cp(1,:);
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)';%加窗後 循環前綴與後綴不疊加 的串行信號
%=================================================================
temp_time1 = (symbols_per_carrier)*(IFFT_bin_length+GI+GIP);%加窗後 循環前綴與後綴不疊加 發送總位數
figure (5)
subplot(2,1,1);
plot(0:temp_time1-1,Tx_data );%循環前綴與後綴不疊加 發送的信號波形
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);%循環後綴與循環前綴相疊加 發送信號波形
grid on
ylabel('Amplitude (volts)')
xlabel('Time (samples)')
title('OFDM Time Signal')

%=================未加窗發送信號頻譜==================================
symbols_per_average = ceil(symbols_per_carrier/5);%符號數的1/5,10行
avg_temp_time = (IFFT_bin_length+GI+GIP)*symbols_per_average;%點數,10行數據,10個符號
averages = floor(temp_time1/avg_temp_time);
average_fft(1:avg_temp_time) = 0;%分成5段
for a = 0:(averages-1)
 subset_ofdm = Tx_data_withoutwindow (((a*avg_temp_time)+1):((a+1)*avg_temp_time));%
 subset_ofdm_f = abs(fft(subset_ofdm));%將發送信號分段求頻譜
 average_fft = average_fft + (subset_ofdm_f/averages);%總共的數據分爲5段,分段進行FFT,平均相加
end
average_fft_log = 20*log10(average_fft);
figure (6)
subplot(2,1,1);
plot((0:(avg_temp_time-1))/avg_temp_time, average_fft_log)%歸一化  0/avg_temp_time  :  (avg_temp_time-1)/avg_temp_time
hold on
plot(0:1/IFFT_bin_length:1, -35, 'rd')
grid on
axis([0 0.5 -40 max(average_fft_log)])
ylabel('Magnitude (dB)')
xlabel('Normalized Frequency (0.5 = fs/2)')
title('OFDM Signal Spectrum without windowing')
%===============加窗的發送信號頻譜=================================
symbols_per_average = ceil(symbols_per_carrier/5);%符號數的1/5,10行
avg_temp_time = (IFFT_bin_length+GI+GIP)*symbols_per_average;%點數,10行數據,10個符號
averages = floor(temp_time1/avg_temp_time);
average_fft(1:avg_temp_time) = 0;%分成5段
for a = 0:(averages-1)
 subset_ofdm = Tx_data(((a*avg_temp_time)+1):((a+1)*avg_temp_time));%利用循環前綴後綴未疊加的串行加窗信號計算頻譜
 subset_ofdm_f = abs(fft(subset_ofdm));%分段求頻譜
 average_fft = average_fft + (subset_ofdm_f/averages);%總共的數據分爲5段,分段進行FFT,平均相加
end
average_fft_log = 20*log10(average_fft);
subplot(2,1,2)
plot((0:(avg_temp_time-1))/avg_temp_time, average_fft_log)%歸一化  0/avg_temp_time  :  (avg_temp_time-1)/avg_temp_time
hold on
plot(0:1/IFFT_bin_length:1, -35, 'rd')
grid on
axis([0 0.5 -40 max(average_fft_log)])
ylabel('Magnitude (dB)')
xlabel('Normalized Frequency (0.5 = fs/2)')
title('Windowed OFDM Signal Spectrum')
%====================添加噪聲============================================
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);%標準差sigma
noise=randn(1,((symbols_per_carrier)*(IFFT_bin_length+GI))+GIP)*noise_scale_factor;%產生正態分佈噪聲序列

%noise=wgn(1,length(windowed_Tx_data),noise_sigma,'complex');%產生復GAUSS白噪聲信號 

Rx_data=windowed_Tx_data +noise;%接收到的信號加噪聲
%=====================接收信號  串/並變換 去除前綴與後綴==========================================
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:IFFT_bin_length+GI);%去除循環前綴與循環後綴,得到有用信號矩陣

%============================================================
%================================================================

%==============================================================
%                      OFDM解碼   16QAM解碼
%=================FFT變換=================================
Y1=fft(Rx_data_complex_matrix,IFFT_bin_length,2);%OFDM解碼 即FFT變換
Rx_carriers=Y1(:,carriers);%除去IFFT/FFT變換添加的0,選出映射的子載波
Rx_phase =angle(Rx_carriers);%接收信號的相位
Rx_mag = abs(Rx_carriers);%接收信號的幅度
figure(7);
polar(Rx_phase, Rx_mag,'bd');%極座標座標下畫出接收信號的星座圖
%======================================================================


[M, N]=pol2cart(Rx_phase, Rx_mag); %將極座標轉化爲直角座標

Rx_complex_carrier_matrix = complex(M, N);%創建複數
figure(8);
plot(Rx_complex_carrier_matrix,'*r');%XY座標接收信號的星座圖
axis([-4, 4, -4, 4]);
grid on
%====================16qam解調==================================================
Rx_serial_complex_symbols = reshape(Rx_complex_carrier_matrix',size(Rx_complex_carrier_matrix, 1)*size(Rx_complex_carrier_matrix,2),1)' ;
%並行數據轉換成串行數據
Rx_decoded_binary_symbols=demoduqam16(Rx_serial_complex_symbols);%解調


%============================================================
baseband_in = Rx_decoded_binary_symbols;

figure(9);
subplot(2,1,1);
stem(baseband_out(1:100));
subplot(2,1,2);
stem(baseband_in(1:100));
%================誤碼率計算=============================================
bit_errors=find(baseband_in ~=baseband_out);
bit_error_count = size(bit_errors, 2) 
ber=bit_error_count/baseband_out_length


function [rcosw]=rcoswindow(beta, Ts)
%定義升餘弦窗,其中beta爲滾降係數,Ts爲包含循環前綴的OFDM符號的長度,Ts爲正偶數

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';%變換爲列向量

    
function [complex_qam_data]=qam16(bitdata)
%modulation of 16QAM,modulate bitdata to 16QAM complex signal
X1=reshape(bitdata,4,length(bitdata)/4)';
d=1;%min distance of symble 
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,:));%convert to the number 1 to 16
end
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),:);%data mapping
 end
 complex_qam_data=complex(qam_data(:,1),qam_data(:,2));
 
function [demodu_bit_symble]=demoduqam16(Rx_serial_complex_symbols)
%將得到的串行16QAM數據解調成二進制比特流
complex_symbols=reshape(Rx_serial_complex_symbols,length(Rx_serial_complex_symbols),1);
d=1;
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];
  complex_mapping=complex(mapping(:,1),mapping(:,2));
  for i=1:length(Rx_serial_complex_symbols);
      for j=1:16;
          metrics(j)=abs(complex_symbols(i,1)-complex_mapping(j,1));
      end
      [min_metric  decode_symble(i)]= min(metrics) ;  %將離某星座點最近的值賦給decode_symble(i)
  end
  
  decode_bit_symble=de2bi((decode_symble-1)','left-msb');
   demodu_bit_symble=reshape(decode_bit_symble',1,length(Rx_serial_complex_symbols)*4);
      
 
function [complex_signal_matrix]=qpsk(baseband_out)
%modulation of QPSK,modulate bitdata to QPSK complex signal
convert_matrix = reshape(baseband_out',2,length(baseband_out)/2)' ;%矩陣轉換,每相鄰2比特組成一個符號
modulo_baseband = bi2de(convert_matrix,'left-msb');%2500*1的十進制矩陣  即將每兩個二進制符號轉換爲一個10進制數
carrier_matrix = reshape(modulo_baseband,carrier_count,symbols_per_carrier)';%生成 時間-載波25*100 矩陣 100個子載波  每個子載波上25個OFDM符號
carrier_matrix = [zeros(1,carrier_count); carrier_matrix];% 添加一個差分調製的初始相位
for i = 2:(symbols_per_carrier + 1) %從每個子載波的第一個符號開始調製
carrier_matrix(i,:) = rem(carrier_matrix(i,:) + carrier_matrix (i-1,:), 2^bits_per_symbol) ;% 差分調製 (差分編碼)
end

carrier_matrix = carrier_matrix*((2*pi)/(2^bits_per_symbol));%相位映射 (0,0)=0 -->0;  (0,1)=1 -->90;  (1,0)=2-->180;     (1,1)=3  -->270
[X, Y]=pol2cart(carrier_matrix, ones(size(carrier_matrix,1),size(carrier_matrix,2))); % 由極座標向複數座標轉化 第一參數爲相位 第二參數爲幅度  幅度均爲1
complex_signal_matrix = complex(X, Y);

程序沒有問題,可以運行,將這些代碼放到同一文件夾下,子文件名要和定義的函數名一致,單獨運行函數是沒有結果的,只需要運行第一個程序即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章