天天看點

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);
           

程式沒有問題,可以運作,将這些代碼放到同一檔案夾下,子檔案名要和定義的函數名一緻,單獨運作函數是沒有結果的,隻需要運作第一個程式即可。

繼續閱讀