目录
正交频分复用(Orthogonal Frequency Division Multiplexing,OFDM)是一种高效的无线通信技术,广泛应用于现代通信系统中,如Wi-Fi、4G/5G蜂窝网络等。OFDM通过将高速数据流分割成多个低速子数据流,并在多个正交子载波上并行传输,从而有效对抗多径衰落和频率选择性衰落。在OFDM系统中,通常还会使用诸如4QAM(4-Quadrature Amplitude Modulation,四元幅度调制)这样的调制方案来增加频谱效率。循环前缀(Cyclic Prefix,CP)的添加和删除是OFDM中的关键步骤,用于消除符号间干扰(Inter-Symbol Interference,ISI)和子载波间干扰(Inter-Carrier Interference,ICI)。
1. OFDM调制
在传统的单载波调制系统中,数据符号的传输速率通常受到信道带宽的限制。而在OFDM系统中,高速数据流被分割成多个低速子数据流,每个子数据流都使用不同的子载波进行调制。这些子载波在频域上是正交的,即它们在一个OFDM符号周期内整数倍频点上的交叉点处相互正交,从而允许它们在接收端被无干扰地分离。
在OFDM调制中,高速数据流首先被分割成多个低速子数据流。每个子数据流都使用不同的子载波进行调制。这些子载波在频域上是正交的,从而允许它们在接收端被无干扰地分离。OFDM符号的形成可以通过逆快速傅里叶变换(IFFT)来实现。OFDM调制可以表示为:
在OFDM调制过程中,输入的比特流首先经过星座映射(如QAM、PSK等)转换成复数符号序列。然后,通过串并转换将高速数据流分割成多个低速子数据流。接下来,对每个子数据流进行逆快速傅里叶变换(IFFT)操作,将频域的子载波映射到时域上,形成OFDM符号。最后,在每个OFDM符号前添加循环前缀(CP),以消除多径传播引起的符号间干扰(ISI)和子载波间干扰(ICI)。
OFDM解调过程是调制的逆过程。首先,去除接收到的OFDM符号的循环前缀。然后,对剩余的符号进行快速傅里叶变换(FFT),将时域信号转换回频域。在频域上,由于子载波的正交性,可以无干扰地分离出每个子载波上的数据。最后,通过并串转换和星座逆映射恢复出原始的比特流。
2. 4QAM映射
4QAM是一种数字调制方案,其中每个符号携带2比特的信息。在4QAM中,根据输入比特的不同组合,选择四个不同的幅度和相位组合之一来表示该符号。
3. 循环前缀的添加和删除
循环前缀是通过将OFDM符号的最后一部分复制到符号的前面来形成的。这样做的好处是,即使信号在传输过程中发生了时延,只要时延不超过循环前缀的长度,接收端仍然可以通过移除循环前缀来恢复原始的OFDM符号,从而避免ISI和ICI。添加循环前缀的操作可以表示为:
在接收端,循环前缀被简单地丢弃,以恢复原始的OFDM符号:
4. MATLAB仿真
在MATLAB中进行OFDM系统的误码率仿真通常涉及以下步骤:
1.生成随机比特流。
2.使用4QAM或其他调制方案将比特流映射到复数符号。
3.构建OFDM符号,包括IFFT操作、添加循环前缀等。
4.通过信道模型,模拟信号在无线环境中的传输,包括添加噪声和其他干扰。
5.在接收端,执行与发送端相反的操作:去除循环前缀、FFT操作、解调和比特判决。
6.计算并记录误码率。
..........................................................................
% 生成随机的二进制比特流用于发送测试
BitsTx = floor(rand(1,NumLoop*NumSubc)*2);
% 将比特流重组成2位一组的符号,并进行2进制到10进制的转换
SymQAMtmp = reshape(BitsTx,2,NumLoop*NumSubc/2).';
SymQAMtmptmp = bi2de(SymQAMtmp,2,'left-msb');
% 利用查表法进行QAM星座映射
QAMTable = [-1-i -1+i 1-i 1+i];
SymQAM = QAMTable(SymQAMtmptmp+1);
% IFFT变换
SymIFFT = zeros(NumSubc,NumLoop);
SymIFFTtmp = reshape(SymQAM,NumSubc/2,NumLoop);
SymIFFTtmptmp = zeros(NumSubc,NumLoop);
SymIFFTtmptmp(1,:) = real(SymIFFTtmp(1,:)); % 实数
SymIFFTtmptmp(NumSubc/2+1,:) = imag(SymIFFTtmp(1,:)); % 实数
% 这么安排矩阵的目的是为了构造共轭对称矩阵
SymIFFTtmptmp(2:NumSubc/2,:) = SymIFFTtmp(2:NumSubc/2,:);
SymIFFTtmptmp((NumSubc/2+2):NumSubc,:) = flipdim(conj(SymIFFTtmp(2:NumSubc/2,:)),1);
SymIFFT = ifft(SymIFFTtmptmp,NumSubc,1);%按列做ifft
% 添加循环前缀
NumAddPrefix = NumSubc + NumCP;
% 通过信道传输
SymCP = zeros(NumAddPrefix,NumLoop);
RowPrefix = (NumSubc - NumCP + 1):NumSubc;% 转置成矢量
SymCP = [SymIFFT(RowPrefix,:);SymIFFT];
SymCh = zeros(1,(NumSubc + NumCP)*NumLoop);
SymChtmp = SymCP(:).'; % 进行这个转置操作之后就成了一个矢量
Ch = [1 1/2 1/4];% 多径信道系数
SymChtmptmp = filter(Ch,1,SymChtmp);
% 添加加性高斯白噪声 (AWGN)
BerSnrTable = zeros(20,3);
for snr=0:30% SNR范围
BerSnrTable(snr+1,1) = snr;
SymCh = awgn(SymChtmptmp,snr,'measured');
% 移除循环前缀
SymDeCP = zeros(NumSubc,NumLoop);
SymDeCPtmp = reshape(SymCh,NumSubc + NumCP,NumLoop);
SymDeCP = SymDeCPtmp((NumCP+1+SyncDelay):NumAddPrefix+SyncDelay,:);
% FFT变换
SymFFT = fft(SymDeCP,NumSubc,1);
% 决策解码(包括DeQAM)
SymDec = zeros(NumSubc,NumLoop);
SymEqtmp(1,:) = SymFFT(1,:)+i*SymFFT(NumSubc/2+1,:);
SymEqtmp(2:NumSubc/2,:) = SymFFT(2:NumSubc/2,:);
for m = 1:NumLoop
for n = 1:NumSubc/2
Real = real(SymEqtmp(n,m));
Imag = imag(SymEqtmp(n,m));
if( abs((Real -1)) < abs((Real +1)))
SymDec(2*n-1,m) = 1;
else
SymDec(2*n-1,m) = 0;
end
if( abs((Imag -1)) < abs((Imag +1 )) )
SymDec(2*n,m) = 1;
else
SymDec(2*n,m) = 0;
end
end
end
% -------------------------------------------------------------------------
TestSymDec = zeros(NumSubc,NumLoop);
TestSymEqtmp(1,:) = SymFFT(1,:)+i*SymFFT(NumSubc/2+1,:);
TestSymEqtmp(2:NumSubc/2,:) = SymFFT(2:NumSubc/2,:);
TestSymEqtmp1 = reshape(TestSymEqtmp,1,NumSubc*NumLoop/2);
min_d = zeros(size(TestSymEqtmp1));
min_ddd = zeros(1,NumSubc*NumLoop);
d = zeros(4,1);
min_index = 0;
for ii = 1:1:(NumSubc*NumLoop/2)
for jj = 1:4
d(jj) = abs(TestSymEqtmp(ii) - QAMTable(jj));
end
[min_d(ii),min_index] = min(d);
switch min_index
case 1
min_ddd(2*ii-1) = 0 ;
min_ddd(2*ii) = 0 ;
case 2
min_ddd(2*ii-1) = 0 ;
min_ddd(2*ii) = 1 ;
case 3
min_ddd(2*ii-1) = 1 ;
min_ddd(2*ii) = 0 ;
case 4
min_ddd(2*ii-1) = 1 ;
min_ddd(2*ii) = 1 ;
otherwise
fprintf('Impossible error!!! \n\n');
end
end
% 将解码后的符号转换为比特流,并计算误码率
BitsRx = zeros(1,NumSubc*NumLoop);
BitsRx = SymDec(:).';
[Num,Ber] = symerr(BitsTx,BitsRx)
BerSnrTable(snr+1,2) = Num ;
BerSnrTable(snr+1,3) = Ber ;
end
% 绘制误码率曲线
figure(1);
semilogy(BerSnrTable(:,1),BerSnrTable(:,3),'b-o');
up4017
误码率仿真结果如下所示: