之前看到了一篇大神写的有关OFDM系统的仿真实现的MATLAB(文章链接在最后),在文章中他讲到:
本系统中IFFT得到的时域信号虽然全为实的,但含有负数,这对于采用IM/DD的光通信系统是不行的。
所以我就写了一篇ACO-OFDM系统的MATLAB仿真。众所周知,ACO-OFDM系统架构在奇数子载波在讯号,偶数子载波不载讯号。在埃尔米特对称处理之后,实数信号且保持反对称之特性,此特性使每一信号在对应位置上皆有其相反数存在。随后再将得到之信号做对零做限幅处理,使发送信号皆为正实数,满足强度调制/直接检测技术之要求。在接收器方面在经过快速傅立叶转换成频率域信号并经过等化器消除信道增益后,只取奇数子载波部份之结果,即为发送器之资讯。
在此声明,本人小白,第一次在CSDN上写文章,也是刚刚学习OFDM,所以我的代码中有大量的借鉴。并且,在源代码的基础上去除了对PAPR处理的操作、TS训练序列和信道均衡。我想做一个简化版的MATLAB程式码,以供像我这样的初学者学习。
代码在下方,有人也许会问为什么代码复制了无法运行,因为里面的qam16是源代码中的一个function,没有这个当然无法运行了。想要完整程式码,请认准源代码作者,就当支持一下这位大神博主了。
clc
clear all;
close all;
Nt_carr=256; %子载波数=FFT点数---256
Np_carr=Nt_carr/2-1; %实际子载波数---127
Sig_per_carr=500; %每子载波含符号数---500
bits_per_symbol=4; %每符号含比特数,16QAM调制---4
CP_Ratio=1/8;
CP_length=CP_Ratio*Nt_carr;%循环前缀长度
TS_length=Nt_carr+CP_length;%训练序列长度
SNR=20;
%==================================================
%================信号产生===================================
baseband_out_length=Np_carr * Sig_per_carr * bits_per_symbol; %所输入的比特数目 127*500*4
% rand( 'twister',0);
baseband_out=round(rand(1,baseband_out_length));%输出待调制的二进制比特流
%==============16QAM调制====================================
complex_carrier_matrix=qam16(baseband_out);%列向量
figure;
plot(complex_carrier_matrix,'*r');%16QAM调制后星座图
title('16QAM调制星座图');
axis([-5,5,-5,5]);
grid on %显示网格线
axis square
%==============串并变换====================================
%矩阵转置时附加有取共轭
complex_carrier_matrix1=reshape(complex_carrier_matrix',Np_carr,Sig_per_carr)';%串并变换Sig_per_carr*Nt_carr 矩阵
%complex_carrier_matrix1=conj(reshape(complex_carrier_matrix',Nt_carr,Sig_per_carr)')%两次转置
%==============埃尔米特映射====================================
carriers=(1:Np_carr)+1;%共轭对称子载波映射 复数数据对应的IFFT点坐标
conjugate_carriers=Nt_carr-carriers+2;%共轭对称子载波映射 共轭复数对应的IFFT点坐标
IFFT_modulation=zeros(Sig_per_carr,Nt_carr);%添0组成IFFT_bin_length IFFT 运算
IFFT_modulation(:,carriers )=complex_carrier_matrix1 ;%未添加导频信号 ,子载波映射在此处
IFFT_modulation(:,carriers(2:2:end) )=0;
IFFT_modulation(:,conjugate_carriers )=conj(complex_carrier_matrix1);%共轭复数映射
IFFT_modulation(:,conjugate_carriers(2:2:end) )=0;
%=================IFFT===========================
time_wave_matrix=ifft(IFFT_modulation,Nt_carr,2);%OFDM调制 即IFFT行变换
%时域波形矩阵,行为每载波所含符号数,列IFFT点数,N个子载波映射在其内,每一行即为一个OFDM符号
figure;
plot(0:Nt_carr-1,time_wave_matrix(1,:));%第一个OFDM符号的时域波形
axis([0,Nt_carr-1, -0.6, 0.6]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('IFFT');
% =================对零限幅===========================
time_wave_matrix_0=time_wave_matrix;
time_wave_matrix_0(find(time_wave_matrix<0))=0;
figure;
plot(0:Nt_carr-1,time_wave_matrix_0(1,:));
axis([0,Nt_carr-1, -0.6, 0.6]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('对零限幅');
figure;
stem(0:Nt_carr-1, abs(IFFT_modulation(2,1:Nt_carr)),'b*-')%第一个OFDM符号的频谱
grid on
axis ([0 Nt_carr -0.5 4.5]);
ylabel('Magnitude');
xlabel('IFFT Bin');
title('第一个OFDM符号各频率对应的幅度(幅频响应)');
figure;
stem(0:Nt_carr-1, (180/pi)*angle(IFFT_modulation(2,1:Nt_carr)), 'b*-')
hold on
plot(0:Nt_carr-1, (180/pi)*angle(IFFT_modulation(2,1:Nt_carr)), 'go')
axis ([0 Nt_carr -200 +200])
grid on
ylabel('Phase (degrees)')
xlabel('IFFT Bin')
title('第一个OFDM符号各频率对应的相位(相频响应)')
figure;
subplot(211)
plot(0:Nt_carr-1,time_wave_matrix_0(1,:));%第一个OFDM符号的时域波形
axis([0,Nt_carr-1+CP_length, -0.6, 0.6]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('发送端第一个OFDM符号的时域波形');
%=====================添加循环前缀CP====================================
CP=time_wave_matrix_0(:,Nt_carr-CP_length+(1:CP_length));
time_wave_matrix_add_CP=[CP,time_wave_matrix_0];
subplot(212)
plot(0:Nt_carr-1+CP_length,time_wave_matrix_add_CP(1,:));%第一个OFDM符号的时域波形
axis([0,Nt_carr-1+CP_length, -0.6, 0.6]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('发送端第一个OFDM符号的时域波形(加CP)');
%=========================并串转换======================================
time_wave_matrix=reshape(time_wave_matrix_add_CP',(Nt_carr+CP_length)*Sig_per_carr,1)';
%=========================经过高斯噪声信道======================================
received_time_wave_matrix=awgn(time_wave_matrix,SNR,'measured');
%===========================串并转换========================================
received_time_wave_matrix_add_CP=reshape(received_time_wave_matrix',Nt_carr+CP_length,Sig_per_carr)';%去除训练序列
figure;
subplot(311)
plot(0:Nt_carr-1+CP_length,received_time_wave_matrix_add_CP(1,:));%接收端第一个OFDM符号的时域波形(含CP)
axis([0,Nt_carr-1+CP_length, -0.6, 0.6]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('接收端第一个OFDM符号的时域波形(含CP)');
%=====================去除循环前缀CP====================================
received_time_wave_matrix=received_time_wave_matrix_add_CP(:,CP_length+1:CP_length+Nt_carr);%去CP
subplot(312)
plot(0:Nt_carr-1,real(received_time_wave_matrix(1,:)));%接收端第一个OFDM符号的时域波形(含CP)
axis([0,Nt_carr-1+CP_length, -0.6, 0.6]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('接收端去除CP后的第一个OFDM符号的时域波形(实部)');
subplot(313)
plot(0:Nt_carr-1,imag(received_time_wave_matrix(1,:)));%接收端第一个OFDM符号的时域波形(含CP)
axis([0,Nt_carr-1+CP_length, -0.6, 0.6]);
grid on;
ylabel('Amplitude');
xlabel('Time');
title('接收端去除CP后的第一个OFDM符号的时域波形(虚部)');
%=================================FFT======================================
received_equilibrium_Hermite=fft(received_time_wave_matrix,Nt_carr,2);
received_equilibrium_Hermite=2*received_equilibrium_Hermite;
%===========================解埃尔米特映射==================================
received_equilibrium=received_equilibrium_Hermite(:,carriers);
received_equilibrium(:,(2:2:end))=0;
%=============================并串转换=====================================
received_complex_carrier_matrix1=reshape(received_equilibrium',Np_carr*Sig_per_carr,1)';
figure;
plot(received_complex_carrier_matrix1,'*r');%接收端星座图
title('接收端(16QAM解调制前)星座图');
axis([-5,5,-5,5]);
grid on %显示网格线
axis square
%===========================16QAM解调==================================
demodu_baseband_out=deqam16(received_complex_carrier_matrix1);
[~,ber]=symerr(demodu_baseband_out,baseband_out);
ber_carriers=zeros(1,Np_carr);
for j=1:Np_carr:2
for i=1:Sig_per_carr
for k=1:bits_per_symbol
if demodu_baseband_out((i-1)*Np_carr*bits_per_symbol+(j-1)*bits_per_symbol+k)~=baseband_out((i-1)*Np_carr*bits_per_symbol+(j-1)*bits_per_symbol+k)
ber_carriers(j)=ber_carriers(j)+1;
end
end
end
end
figure;
plot(1:Np_carr,ber_carriers,'--r*');
title('各子载波误码个数')
ylabel('误码个数');
xlabel('子载波编号');
xlim([1 Np_carr]);
grid on;
引用文章:基于16QAM调制的OFDM系统仿真实现(MATLAB)