初识OFDM(一):OFDM原理
1. 为什么使用OFDM? 单载波与多载波
OFDM其实是一种FDM(多载波)技术,就与之对应的就是单载波技术。单载波技术的信道拥有一个很宽的带宽,而为了保证传输没有ISI(码间干扰),根据奈奎斯特准则要求[1]:
需要保证 H ( f ) H(f) H(f)在 [ − R s 2 , R s 2 ] [-\frac{R_s}{2},\frac{R_s}{2}] [−2Rs,2Rs]中是一个常数( R s R_s Rs表示波特率,表示符号传输的速率,而符号则是一个数据的意思,根据数据的进制而决定长度)。对此我们通常使用的方法是设计一个均衡滤波器抵消信道带来的不平坦频响,用发射和接收滤波器利用滚降升余弦函数去构造一个平坦的信道,实现一个无ISI的传输
在单载波系统中,为了保证高速率传输, R s R_s Rs要尽可能的大。信号带宽增加后,信道带宽如果小于信号带宽就会引起快衰落。我们就需要一个非常复杂的均衡器来抵消这个快衰落,而这个均衡器是难以设计的。
有没有变得办法呢?显然是有的。如同常见的处理非线性问题一样,我们如果使用微元法只看很窄的一段频响,他是不是就接近平坦而很容易实现ISI呢?,这样均衡器设计起来就简单很多了。因此我们把一个宽带信号拆分成多个窄带信号再分别用不同的子载波进行传输,这就是多载波技术。
2. OFDM的原理
而什么是OFDM(正交频分复用,正交多载波)呢?我们从时域上来看,当我们使用了多载波技术后,首先把需要发送的信号做一个串并转换,譬如我数据本身1ms发送一个数据,现在我要发送8个数据,使用单载波这需要8ms,我现在将原本的信道变为8个子信道后,这8个子信道只需要在8ms内也发送8个数据就可以。也就是说一个单一信道变为了8ms传输他所分到的那部分数据,8ms后合并就行。这就增大了符号长度,对时延的容忍度大大增加了,ISI就不容易产生。
现在八个子信道就需要8个不同的子载波了。而这8个子载波的频率显然不能完全一致,否则无法区分开需要频分复用,但他们又要离得越近越好,因为这样总带宽的以节省。那么最近是多少呢?最终发现子载波之间的间隔
Δ
f
\Delta f
Δf至少是子信道的波特率,即
Δ
f
=
1
T
s
y
m
\Delta f=\frac{1}{T_{sym}}
Δf=Tsym1(
T
s
y
m
=
N
∗
T
T_{sym}=N*T
Tsym=N∗T),当然后续我们引入了GI和VC之后,这里不是
T
s
y
m
T_{sym}
Tsym而是
T
u
s
e
d
T_{used}
Tused。可以证明
{
e
j
2
π
f
k
t
}
k
=
0
N
−
1
\{e^{j2\pi f_kt}\}_{k=0}^{N-1}
{ej2πfkt}k=0N−1
是正交的,这就是子载波。
而具体OFDM是如何实现的呢?
我们在基带上用滤波器来说明
首先,数据经过串并转换,每个子信道上会走M个数据,这是就可以进行QAM或是PSK,被映射成一个复数
X
k
X_k
Xk=
(
s
k
1
,
s
k
2
)
(s_{k1},s_{k2})
(sk1,sk2)。此时发送的信号
x
(
t
)
x(t)
x(t)就可以写作
x
k
(
t
)
=
s
k
1
c
o
s
2
π
f
k
t
−
s
k
2
s
i
n
2
π
f
k
t
=
R
e
(
X
k
e
j
2
π
f
k
t
)
x_k(t)=s_{k1}cos2\pi f_k t-s_{k2}sin2 \pi f_kt=Re(X_ke^{j2\pi f_kt})
xk(t)=sk1cos2πfkt−sk2sin2πfkt=Re(Xkej2πfkt)
x ( t ) = ∑ k x k ( t ) x(t)=\sum_k{x_k(t)} x(t)=k∑xk(t)
而因为子载波正交,这个解调是很容易的。这就完成了多载波的发射和接收
而之后,人们发现上面的过程可以用IDFT或是IFFT大大简化。[2]
3 OFDM的保护间隔
为什么需要保护间隔呢?虽然传输时间增加大大的减少了ISI的干扰,但是时延扩展仍然存在,虽然微弱但这破坏了正交性。为此,我们增加保护间隔避开时延扩展。
所谓保护间隔就是让出时延扩展时间,来避免码间干扰。保护间隔有多种方法,包括ZP,CP,CS。
- ZP:补零,即在GI中发0
- CP:在GI中加上符号的尾巴
- CS:在GI中加上符号的头
根据之前所说,此时如果GI时间小于时延扩展,那么不会产生ISI。而如果GI时间大于时延扩展,ISI就被彻底消灭了。然而事实不是这样在实际操作中,会出现符号定时偏差(STO),这导致FFT窗并不是准确的在OFDM符号的起点进行变换,进而造成ISI。[2]中描述:
- 当FFT窗早于前一个符号末端,ISI
- 晚于当前符号的起始点,ISI和ICI都会出现
这也是ZP不被广泛使用的原因,STO的出现不会导致使用CP方法的OFDM出现ICI,而使用ZP的则会
除了ISI和ICI,OFDM还会出现ACI(邻道干扰)问题,这时候我们会引入VC即虚拟子波,即一个符号内两侧的子波不用于传输任何信号,这会导致利用率从 N N N下降到 N u s e d N_{used} Nused
4 OFDM 传输系统仿真
以下代码参考了[2]和[3],但力求读懂每一步
% OFDM实现
clear all;
% 选择CP或ZP
NgType = 2; %对于ZP或CP NgType = 1或2
if NgType == 1
nt = 'CP';
elseif NgType == 2
nt = 'ZP';
end
% 选择信道类型
Ch = 1;
if Ch == 0
chType ='AWGN'; %高斯白噪声信道
Target_neb = 100;
else %多经瑞利信道
chType ='CH';
Target_neb = 500;
end
figure(Ch+1);
clf;
PowerdB = [0 -8 -17 -21 -25]; %信道抽头功率特性'dB'
Delay = [0 3 5 6 8]; %信道时延
Power = 10.^(PowerdB/10); %信道抽头功率特性 '线性'
Ntap = length(PowerdB); %抽头数
Lch = Delay(end)+1; %信道长度,TDL最大抽头数
Nbps = 2; %调制阶数 2/4/6
M = 2^Nbps; %QPSK、16-QAM、64-QAM
Nfft = 64; %FFT大小
% Ng = 3
Ng = Nfft/4; %保护间隔(GI)长度,若没有保护间隔,Ng = 0
Nsym = Nfft + Ng; %符号周期
% 调整Nvc
% VC是不用于传输的子载波,拥有保护带宽,导致传输速率下降到N_used/N
Nvc = Nfft/4; %Nvc若等于0,则没有VC(虚拟子载波)
% Nvc = 0; %Nvc若等于0,则没有VC(虚拟子载波)
Nused = Nfft - Nvc; %Nused为用于传输数据的子载波数
EbN0 = [0:2:20]; %Eb/N0
% EbN0 = 50; %Eb/N0
N_iter = 1e5; %对于每一次EbN0的迭代次数
Nframe = 3; %每一帧的符号数,一个OFDM帧由三个OFDM符号组成
sigPow = 0; %初始信号功率
file_name = ['OFDM_BER_' chType '_' nt '_' 'GL' num2str(Ng) '.dat'];
fid = fopen(file_name,'w+');
norms = [1 sqrt(2) 0 sqrt(10) 0 sqrt(42)]; %BPSK 4-QAM 16-QAM,幅值,用于归一化
for i = 0:length(EbN0)
% 设置伪随机的种子为0,保证每次的计算结果是相同的
randn('state',0);
rand('state',0);
% Ber2=ber(); %初始化BER
Neb = 0; %初始化误比特数
Ntb = 0; %初始化总比特数
for m = 1:N_iter %迭代次数
X = randi([0 M-1],1,Nused*Nframe); % 返回0--M-1之间的一个长度为Nused*Nframe的向量,一帧被拆分为子载波数*符号数个量
Xmod = qammod(X,M,'gray')/norms(Nbps); % 使用格雷码做QAM,变为复数形式
if NgType~=2 % x_GI表示增加了GI的x
x_GI = zeros(1,Nframe*Nsym);
elseif NgType == 2 % Zero Padding,头尾都有零,因此长度要增加
x_GI = zeros(1,Nframe*Nsym+Ng);
end
% kk1 = 1:Nused/2;
% kk2 = Nused/2+1:Nused;
kk1 = [1:Nused/2];
kk2 = [Nused/2+1:Nused];
kk3 = 1:Nfft;
kk4 = 1:Nsym;
for k = 1:Nframe %以下处理针对一个OFDM符号
% 第一步倒置,把x从f/2移到0处,详见我的知乎提问,陈老师专栏
% https://zhuanlan.zhihu.com/p/386509272
if Nvc~= 0
X_shift = [0 Xmod(kk2) zeros(1,Nvc-1) Xmod(kk1)];
else
X_shift = [Xmod(kk2) Xmod(kk1)];
end
% 发送
% 注意此处仍然在基带,发送需要上载波
x = ifft(X_shift);
x_GI(kk4) = guard_interval(Ng,Nfft,NgType,x); %增加CP或ZP,增加后总长度为N_sym
% 向后平移到下一个符号
kk1 = kk1 + Nused;
kk2 = kk2 + Nused;
kk3 = kk3 + Nfft;
kk4 = kk4 + Nsym;
end
% 能量检测
if i == 0 %只测量信号功率
sigPow_temp = x_GI*x_GI';
end
if Ch==0
y = x_GI; % 没有信道,把噪声忽略了?
else %多径衰落信道
% TDL模型,本质上就是考虑了多径的时延和功率
% 生成抽头数个瑞利信道
channel = (randn(1,Ntap)+1j*randn(1,Ntap)).*sqrt(Power/2);
h = zeros(1,Lch);
h(Delay+1) = channel; % 冲激函数采样
y = conv(x_GI,h);
end
if i == 0 %只测量信号功率
y1 = y(1:Nframe*Nsym);
sigPow = sigPow + y1*y1';
continue;
end
%******************** 信道 ***********************%
% SNR这里是EsN0,看陈老湿的解释
% https://zhuanlan.zhihu.com/p/335954327
% 具体来说,SNR是指EsN0,而Es有能量用于发送CP了,倒置后面的一项
snr = EbN0(i) + 10*log10(Nbps*(Nused/Nfft)); %%方便fig标号,(1),原书公式
% snr = EbN0(i) + 10*log10(Nbps);
% snr = EbN0(i) + 10*log10(Nbps*(Nfft/Nsym)); %%方便fig标号,(3)CP消耗能量
noise_msg = sqrt((10.^(-snr/10))*sigPow/2);
% 获得幅度后,噪声是瑞两个高斯噪声
y_GI = y + noise_msg*(randn(size(y)) + 1j*randn(size(y)));
% 接收端
% kk1也是因为头尾都是0
kk1 = (NgType==2)*Ng + [1:Nsym];
kk2 = 1:Nfft;
kk3 = 1:Nused;
kk4 = (Nused/2 + Nvc + 1):Nfft;
kk5 = (Nvc~=0)+[1:Nused/2];
if Ch ==1
H = fft([h zeros(1,Nfft-Lch)]); %信道频率响应,做Nfft点采样,因此要补0
H_shift(kk3) = [H(kk4) H(kk5)]; %得到均衡器
end
for k =1:Nframe
Y(kk2) = fft(remove_GI(Ng,Nsym,NgType,y_GI(kk1)));
Y_shift = [Y(kk4) Y(kk5)];
if Ch ==0
Xmod_r(kk3) = Y_shift;
else
Xmod_r(kk3) = Y_shift./H_shift; %均衡器,去h^-1
end
kk1 = kk1 + Nsym;
kk2 = kk2 + Nfft;
kk3 = kk3 + Nused;
kk4 = kk4 + Nfft;
kk5 = kk5 + Nfft;
end
X_r = qamdemod(Xmod_r*norms(Nbps),M,'gray');
Neb = Neb + sum(sum(de2bi(X_r,Nbps)~=de2bi(X,Nbps))); % 错误的个数
Ntb = Ntb + Nused*Nframe*Nbps;
% if Neb>Target_neb
% break
% end
end
if i == 0
sigPow = sigPow/Nsym/Nframe/N_iter;
fprintf('Signal power= %11.3e\n', sigPow);
fprintf(fid,'%%Signal power= %11.3e\n%%EbN0[dB] BER\n', sigPow);
else
Ber = Neb/Ntb;
fprintf('EbN0=%3d[dB], BER=%4d/%8d=%11.3e\n', EbN0(i), Neb,Ntb,Ber)
fprintf(fid, '%d\t%11.3e\n', EbN0(i), Ber);
if Ber<1e-6
break;
end
end
end %end for i
if(fid~=0)
fclose(fid);
end
disp('sumualtion is finished');
plot_ber(file_name,Nbps);
%%%%选择CP或ZP
if Ch == 1
if NgType == 1
a = load(file_name);
save('ofdm_basic_myself3_cp16_rayleigh','a');
elseif NgType == 2
b = load(file_name);
save('ofdm_basic_myself3_zp16_rayleigh','b');
end
end
5 reference
[1] 通信原理 第2版 [李晓峰 编著] 2014年版
[2] MIMO-OFDM 无线通信技术及MATLAB 实现文章来源:https://www.toymoban.com/news/detail-781403.html
[3] https://zhuanlan.zhihu.com/p/385096476文章来源地址https://www.toymoban.com/news/detail-781403.html
到了这里,关于初识OFDM(一):OFDM原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!