OFDM完整仿真过程及解释(MATLAB)
参考二
调制与变频、基带信号与射频信号中的IQ调制(又称矢量调制)
问题
1、信噪比定义,作用
2、为什么导频位置重要
上半部分对应于发射机链路,下半部分对应于接收机链路
过程介绍–发送端: OFDM发射机的输入位首先要进行编码(有冗余),以减少特定信道的误差,编码后的位通过==调制在相位和正交(IQ)==平面上映射成星座,得到的IQ数据用复数表示。在IQ数据中插入导频和保护频带,形成频域OFDM符号。频域OFDM符号通过反离散傅里叶变换(IDFT)转化为时域(IFFT和IDFT变换的作用相同,只是有更高的计算效率,所以适用于所有的应用系统;IDFT 可以并行地从接受信号中恢复搭载在子载波上的信号),再通过并行到串行(P/S)的转换转化为一维(1D)。循环前缀(Cyclic Prefix,CP),是将时域IQ数据从末尾的一段复制到时域IQ数据的开头,形成一个完整的时域OFDM符号,然后,基带IQ数据流(经过DAC,一般指数模转换器。数模转换器,又称D/A转换器,简称DAC,它是把数字量转变成模拟的器件)被向上转换为射频(RF) 上变频,并通过RF前端进行空中广播。通过无线信道传播的无线电波被接收机的射频前端接收并下变频为基带数字IQ数据。
过程介绍–接收端:载波同步器回收时域OFDM符号,并将其发送到基带接收器。在接收机上,首先去除CP,其余的IQ数据通过FFT转换到频域(用FFT变换分解,子载波的幅度和相位最终转换回数字信号。DFT 操作可以并行生成多个互相正交的子载波)。信道均衡器估计信道的响应,并对接收到的被衰落信道扭曲的IQ数据进行均衡。接下来,经过均衡的频域IQ数据被解调为软位(浮点数),再由信道解码器将其进一步解码为二进制位。输出的比特流被送到下一层,并回收成数据包。请注意,信道均衡是针对衰减而不是加性高斯白噪声(AWGN)信道的。
这里理解为传输的频域信号是因为IFFT是从频域到时域,实际上这里IFFT充当的是一个实现子载波正交的作用,具体可以推导其DFT公式
DFT 和 IDFT 可以并行完成,故大大减小了 OFDM 的系统复杂度,降低了 OFDM 系统实现的难度
1、为什么要进行信道估计?
无线环境是复杂多变的,信号在传播过程中就会受到各种各样的干扰,到达接收端时,信号的幅度、相位和频率都会发生改变,而信道估计和信道均衡的作用就是尽可能恢复出信号。
举一个简单的栗子来说,
假如发送端发送了一个正弦信号6sin(2t),由于信道的影响,接收端接到的信号变成了3sin(2t+8),信号经过无线信道的传输后幅度和相位都发生了变化(也就是幅度衰减一半,相位增加了8),如果在接收端现在已经通过相应的信道估计算法估计出了这个信道的特性(也就是幅度衰减一半,相位增加了8),那么接收端在后续接收其他信号的时候就会对接收到的信号进行相应的补偿。假如说发送端又发送了一个信号8sin(2t+2),通过信道传输之后,接收端接收到的信号变成了4sin(2t+10),那么接收端由于刚才已经通过第一次接收到的信号估计出了信道的特性,那么他就可以直接把信号补偿为8sin(2t+2)(幅度增加一倍,相位减去8),这样在接收端就可以复原出发送端发送的原信号。
2、信道频域响应是啥?CFR
一个OFDM符号之内包括多个经过调制的子载波的合成信号,其中每个子载波都可以收到psk(相移键控)和qam(正交幅度调制)的调制。
OFDM发射机将信息比特流映射成一个psk或qam符号序列,之后将串行的符号序列转换为并行符号流。每N个经过串并转换的符号被不同的子载波调制。
OFDM符号是N个并行符号的复合信号,若单个串行符号的传输时间(周期)是Ts,则一个OFDM符号的持续时间(周期)Tsym=N*Ts。
频域调制信号X[k]的频率为:fk=k/Tsym,子载波数量为N,则k=0,1,2…N-1。(由DFT原理推导)
(一)信道编码
纠错检错
提高系统的可靠性。
这里的信道编码一般采用卷积编码,Viterbi译码。
(二)交织
(三)扩频
导频不携带信息,导频是双方已知的数据,是用来做信道估计的。
在接收机中,虽然利用接收到的段训练序列、长训练序列可以进行信道均衡、频率偏差校正,但符号还会存在一定的剩余偏差,且偏差会随着时间的累积而累积,会造成所有子载波产生一定的相位偏移。因此,还需要不断地对参考相位进行跟踪。要能实现这个功能,需要在52个非0子载波中插入导频符号。
(五)保护间隔
多径信道会对OFDM符号造成ISI影响,破坏了子载波间的正交性。故需要采取一些方法来消除多径信道带来的符号间干扰(ISI)影响,即插入保护间隔。
保护间隔有两种插入方法:一种是补零(zp),即在保护间隔中填充0;另一种是插入循环前缀(cp)或循环后缀(cs)实现OFDM的循环扩展(为了某种连续性)。
一般采用cp。cp是将OFDM后部的采样复制到前面,长度为Tcp,故每个符号的长度为Tsym=Tsub+Tcp,Tsub为数据部分子载波数。Tcp大于或等于多径时延,符号间的ISI影响将被限制在保护间隔中,因此不会影响下一个OFDM的FFT变换。
(六)RF射频调制
信道估计
ML
信道均衡技术是指为了提高衰落信道中的通信系统的传输性能而采取的一种抗衰落措施。常用的均衡算法主要分成
线性均衡算法和非线性均衡算法[9],线性均衡算法主要有迫零(Zero Forcing,ZF)均衡算法和最小均方误差(Minimum Mean Square Error,MMSE)均衡算法等。
ZF 均衡算法较为简单,只是在信道估计结果的基础上通过简单的矩阵运算就可以恢复出发射端发送的信号,但是由于ZF均衡没有考虑噪声的影响,在消除干扰的同时也放大了噪声,造成通信系统的误码率性能下降,尤其是在信噪比较低的条件下;
MMSE均衡算法考虑了噪声的影响,其目标是使得发送端发射的数据与接收端估计的数据的均方误差达到最小,相比于 ZF 均衡算法,MMSE 算法在低信噪比时性能要好于 ZF算法,但是 MMSE 算法需要噪声的先验知识,并且其算法的计算复杂度较高。
非线性均衡算法主要有判决反馈算法、最大似然算法和 Turbo迭代算法等。
判决反馈均衡主要是通过常用的均衡准则预测和判决后干扰抵消[10],能够有效使得码间干扰对系统性能的影响变小,提高数据传输的正确性,特别是在信道严重失真时非常适用。
最大似然均衡算法主要是进行多次的搜索,寻找出接收向量和所有可能的后处理向量之间的最小欧氏距离,此时对应的向量就是均衡后的信号[11]。
Turbo均衡主要是通过反复均衡以及信道译码来得到发射信号的迭代算法[12],由于要迭代计算,因此复杂度也非常高。
参考文献:面向C_V2X通信的基于深度学习的联合信道估计与均衡方法_陈成瑞
具体理论可参考: 调制与变频、基带信号与射频信号中的IQ调制(又称矢量调制)
调制是使得一个信号(称为载波,例如光、电压正弦波)的某些参数(例如电压、频率等)随着另一个信号(称为我们想要发送的信息,例如二进制0,1串)的变化而变化的过程。
1)如果调制与变频都存在,信号一定是先调制到基带信号,然后在进行变频成为射频信号,最后通过天线发射出去。所以一般情况下,调制后的信号频率较低,有低通形式,变频后的信号频率较高,有带通形式,这里的频率是相对的。有时候可能只进行调制就直接把信号变到想要的频率上并使用天线发射,就不用再变频。而现在我们的移动通信频段较高,难以一次调制到想要的频段,所以一般都是要先调制后变频甚至要多次变频。
注:
4G的频率和频段是:1880-1900MHz、2320-2370MHz、2575-2635MHz。
5G有2个频段:FR1:450-6000MHZ(现已试点部署的)、FR2:24250-52600MHZ(称为毫米波频段)。
基带信号:经过基带调制的信号,频率较低,信号频谱从零频附近开始,具有低通形式的信号。这种基带信号由于频率较低,一般不能直接发送进行远距离通信,而要对基带信号进行进一步的变频操作,将频谱搬到较高的频率处用天线进行发射信号。
分为模拟基带信号和数字基带信号:模拟信号要通过ADC采样变成离散的数字信号,然后对数字信号进行调制为数字基带信号,然后进行DAC转换为模拟基带信号(或者DAC之前可以进行数字上变频DUC,相应接收端ADC之后可以进行数字下变频DDC),最后可以进行模拟变频或者直接发射。注:有时候调制称为基带调制,变频也称为射频调制。
数字调制方法:
利用数字去控制载波的状态,二进制数字调制就只有两种状态,例如2ASK/OOK、2FSK、2PSK、2DPSK。
多进制调制就是有多种状态,还是用二进制表示,例如载波有4种状态,当判决得到第二种状态时就知道传的是二进制01。载波的多种状态我们可以用载波的幅度与相位来区分。多进制常用的有QPSK(只用4种相位区分),QAM(用幅度与相位区分,不同的幅度与相位结合可以变成各种QAM,例如16QAM,64QAM等)。
模拟变频方法(模拟信号调制):
载波指具有较高频率的正弦波。分为调幅和调频(调相)。
调幅:调幅( AM)、 双边带( DSB ) 、单边带( SSB ) 和残留边带( VSB )
调频:FM、PM、窄带调频、宽带调频。
通信中非线性调制又称为角度调制,是指调制信号控制高频载波的频率或相位,而载波的幅度保持不变。角度调制后信号的频谱不再保持调制信号的频谱结构,会产生与频谱搬移不同的新的频率成分,而且调制后信号的带宽一般要比调制信号的带宽大很多。从传输频带的利用率来讲,非线性调制是不经济的,但它具有较好的抗噪声性能,在不增加信号发送功率的前提下,可以用增加带宽的方法来换取输出信噪比的提高,且传输带宽越宽,抗噪声性能就越好。非线性调制分为频率调制(FM)和相位调制(PM),它们之间可相互转换。
线性顾名思义就是已调信号的些参数随着调制信号做线性变化,一般我们学的线性调制有AM,DSB,VSB,SSB
矢量调制是一种非常强大的调制方案,因为它可生成任意的载波相位和幅度。在这种调制方案中,基带数字信息被分离成两个独立的分量: I ( 同相) 和Q ( 正交) 分量。这些I 和Q 分量随后组合形成基带调制信号。I 和Q 分量最重要的特性是它们是独立的分量( 正交)。
基本原理:Acos(wt+α)=Acos(α)cos(wt)+Asin(α)sin(wt)改变常数cos(wt)和sin(wt)幅度,就可以得到任意幅度、任意相位的cos函数,并可以利用这些函数去表示不同的信息。对此,通信原理上通常会用一种抽象的说法来约定表示方式,就是所谓的星座图。
通信信号处理中为什么要分为I、Q两路
把要传输的数据分成并行的两路(I和Q路)分别进行扩频/加扰。分成两路并行处理的目的是充分利用星座图进行调制,星座图有X和Y轴,正好对应I和Q路。
I/Q两路采样可以降低采样率,可以获取信号的相位信息:
1.方便地将信号采用复信号的方法表示;
2.是可以降低每个支路的采样率(因为如果用幅度检波后的 采样率将是其两倍),降低对ADC的要求;
3.是可以保留原始信号的相位信息。
基本参数
对于OFDM信号,形象点说在时域上是信号的叠加。在频域上是多个子载波并列(正交的)。图见OFDM完整仿真过程及解释(MATLAB)
OFDM帧由一个导频和一个数据OFDM符号组成
5.1 各种OFDM参数的选择就是需要在多项要求冲突中进行折衷考虑。通常来说,首先要确认3个参数:带宽、比特率、及保护间隔。
5.1.1 确定OFDM保护间隔TGI
按照惯例,保护间隔的时间长度应该为应用移动环境信道的时延扩展均方根值的2~4倍。
5.1.2 确定OFDM符号周期长度 TS
为了最大限度的减少由于插入保护比特所带来的信噪比的损失,OFDM符号周期长度远远大于保护间隔长度。但是符号周期又不能任意大,否则就需要更多的子载波,带宽不变,子载波间隔就变小,系统的实现复杂度就提高了,而且还加大了系统的峰值平均功率比,同时系统对频率偏差更加敏感。因此,一般选择符号周期长度是保护间隔的5倍,这样使插入保护比特所造成的信噪比损耗只有1dB左右。
信噪比损耗怎么就只有1db了?
有效数据部分符号长度 Tu=TS-TGI,子载波频率间隔Δf=1/Tu
5.1.3 确定子载波的数量 N =带宽B/Δf=数据速率/子信道比特速率1/Ts
可由-3dB带宽除以子载波间隔(即去掉保护间隔之后的符号周期的倒数)得到。或者可由所要求比特速率除以每个子信道的比特速率来确定子载波的数量。每个信道中所传输的比特速率可由调制类型、编码速率、和符号速率来确定。
为什么用3db带宽
5.2 有用符号持续时间Tu
对子载波之间间隔、译码的等待周期都有影响,为了保持数据的吞吐量,子载波数目和FFT的长度要有相对较大的数量,这就导致符号持续时间变长。总之,符号周期长度的选择以保证信道的稳定为前提。
5.3 子载波数N
其数值与FFT处理过的复数点数相对应,需适应数据速率和保护间隔的要求。
OFDM系统的调制模式基于功率和频谱利用率来选择,可采用qam、psk。
为了使所有的点有相同的平均功率,二进制序列映射后的复数要归一化。(BPSK\QPSK\16QAM\64QAM分别对应乘以1、1/根号2、1/根号10、1/根号42),解调的时候再变回去。
5.5 每帧包含的OFDM符号数
5.6 以具体实例说明;
要求:(1)比特率为25Mbit/s(2)可容忍的时延扩展为200ns(3)带宽小于18MHz。
1)由200ns时延扩展得保护间隔为800ns;
2)由保护间隔800ns得符号周期长度TS= 6*800ns=4.8us;
3)子载波频率间隔Δf=1/Tu=1/(4.8-0.8)us,即250KHz;
4) 由所要求比特速率除以每个子信道的比特速率来确定子载波的数量:
由所要求的比特速率与OFDM符号速率的比值,每个符号需要传送的比特:(25Mbit/s)/(1/4.8us)=120bit。
5)为了完成上面120bit/符号,有两种选择:利用16QAM和编码效率为1/2的编码方法,这样每个子载波携带2bit的有用信息,因此需要60个子载波;另一种是利用QPSK和码率为3/4的编码方法,每个子载波携带1.5bit信息。因此需要80个子载波,然而80个子载波意外着带宽:80*250KHz=20MHz,大于所给带宽要求,故取第一种,即60个子载波。可利用64点IFFT来实现,剩余4个子载波补0.
举例
IEEE 802.11a WLAN PHY层标准的主要参数:
其他参数以保护间隔长度为基础进行定义。
- 为了把保护间隔所占用的信噪比减小到1dB,(OFDM符号长度定为Tsym=4us
- 子载波频率间隔为 1/(4-0.8)us=312.5khz
- 数据比特速率==每个子信道的比特速率(1/TS)子载波的数量
标准采用48个并行子载波进行数据传输,这样当调制方式为BPSK或16QAM时,可以提供的未编码数据速率分别为
4811/4us=12Mb/s,484*1/4=48MB/S.
IEEE 802.11a中使用了52个子载波(实际上应为 53个,其中k=0处的直流子载波上不传输符号),由于IFFT算法基于2点,故采用64点的IFFT。
采样间隔Tsam=Tu/N=(4-0.8)/64=0.05us 采样频率Fs=1/Tsam=至少应该是20M samples/s
六、OFDM的MATLAB仿真主程序
%参数定义设置
N_sc=52; %系统子载波数(不包括直流载波)、number of subcarrierA
N_fft=64; % FFT 长度
N_cp=16; % 循环前缀长度、Cyclic prefix
N_symbo=N_fft+N_cp; % 1个完整OFDM符号长度
N_c=53; % 包含直流载波的总的子载波数、number of carriers
M=4; %4PSK调制
SNR=0:1:25; %仿真信噪比
N_frm=10; % 每种信噪比下的仿真帧数、frame
Nd=6; % 每帧包含的OFDM符号数
P_f_inter=6; %导频间隔
data_station=[]; %导频位置
L=7; %卷积码约束长度
tblen=6*L; %Viterbi译码器回溯深度
stage = 3; % m序列的阶数
ptap1 = [1 3]; % m序列的寄存器连接方式
regi1 = [1 1 1]; % m序列的寄存器初始值
%% 基带数据数据产生
%% 信道编码(卷积码、或交织器)
matlab实现卷积编码’适合小白理解学习
在maltab中有现成的函数来实现卷积编码。即:
trellis = poly2trellis(ConstraintLength,CodeGenerator);
code_data = convenc(P_data,trellis);
%-----------------------------------------------------------------------------%
trellis = poly2trellis(ConstraintLength,CodeGenerator);
trellis = poly2trellis(ConstraintLength,CodeGenerator);
其中trellis是一个网格表,用来规定我们使用的卷积编码的规则(比如几输入、几输出、几个寄存器之类的东西,也就是我们前面说的为什么C1 = S1+S3,C2 = S1+S2+S3这类的。)
- ConstraintLength是描述每一路输入的长度,CodeGenerator描述输入和模2加法器的连接关系(8进制计数)
.
这是我用的一个(2,1,7)卷积编辑器的例子
一般我们用(n,k,L)来描述卷积码,即我们输入k个信息比特经过卷积码编成n个比特(n一定是大于k的,就是加进去了冗余来进行纠错),L是编码的约束长度。这个编码器由n个模2加法器和L*k-1级移位寄存器组成。trellis = poly2trellis(7,[133 171])
可以看出这个7就是S1-S7,二进制1011011可以用八进制的133表示,二进制1111001可以用八进制171表示。1和0分别表示是否连接,连接用1表示,不连接用0表示。
code_data=convenc(P_data,trellis);
这个函数比较简单,其中P_data表示输入的二进制比特,trellis是上一个函数设置的网格规则,code_data表示输出的二进制比特,大家可以试验一下,输入1比特会输出2比特。
两个函数,一个制定规则,一个实现信道编码。后续了解卷积编码的解码过程!
%% qpsk调制
data_temp1= reshape(code_data,log2(M),[])'; %以每组2比特进行分组,M=4
data_temp2= bi2de(data_temp1); %二进制转化为十进制
modu_data=pskmod(data_temp2,M,pi/M); % 4PSK调制
% figure(1);
scatterplot(modu_data),grid; %星座图(也可以取实部用plot函数)
%% 扩频
%扩频通信信号所占有的频带宽度远大于所传信息必需的最小带宽
%根据香农定理,扩频通信就是用宽带传输技术来换取信噪比上的好处,这就是扩频通信的基本思想和理论依据。
%扩频就是将一系列正交的码字与基带调制信号内积
%扩频后数字频率变成了原来的m倍。码片数量 = 2(符号数)* m(扩频系数)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 插入导频
P_f=3+3*1i; %Pilot frequency
P_f_station=[1:P_f_inter:N_fft]; %导频位置(导频位置很重要)N_fftFFT 长度 P_f_inter=6; %导频间隔
pilot_num=length(P_f_station);%导频数量
for img=1:N_fft %数据位置
if mod(img,P_f_inter)~=1 %mod(a,b)就是求的是a除以b的余数
data_station=[data_station,img];
end
end
data_row=length(data_station);
data_col=ceil(length(spread_data)/data_row);
pilot_seq=ones(pilot_num,data_col)*P_f;%将导频放入矩阵
data=zeros(N_fft,data_col);%预设整个矩阵
data(P_f_station(1:end),:)=pilot_seq;%对pilot_seq按行取
if data_row*data_col>length(spread_data)
data2=[spread_data;zeros(data_row*data_col-length(spread_data),1)];%将数据矩阵补齐,补0是虚载频~
end;
%% 串并转换
%% IFFT
%% 插入保护间隔、循环前缀
%% 并串转换
%% DA
%% 上变频
%% 信道(通过多经瑞利信道、或信号经过AWGN信道)
%% 下变频
%% AD
%% 串并转换
%% 去掉保护间隔、循环前缀
%% FFT
%% 信道估计与插值(均衡)
%% 信道校正
%% 并串转换
%% 解扩
%% QPSK解调
%% (解交织)
%% 信道译码(维特比译码)
%% 计算误码率
%%参数设置
para = 128; %Number of parallel channel to transmit要发送的并行信道数,子载波数N
fftlen = 128; %FFT length 子载波数与FFT处理过的复数点数相对应
noc = 128; %Number of carrier
nd = 6; %Number of information OFDM symbol for one loop 周期ofdm符号数,每帧包含的OFDM符号数
ml = 2; %Modulation:QPSK
sr = 250000; %Symbol rate 符号速率
br = sr.*ml; %Bit rate per carrier
gilen = 32; %length of guard interval
。。。
%%%%% qpsk调制 %%%%%%%%%%%%%%%%%%%%
seldata = rand(1,para*nd*ml)>0.5; %串行数据
paradata = reshape(seldata,para,nd*ml); %串并转换,行数变为para子载波数,每行个数 每帧周期ofdm符号数*调制阶数=每个调制符号比特数
[ich,qch] = qpskmod(paradata,para,nd,ml); %调制
%归一化
kmod = 1/sqrt(2); ich1 = ich.*kmod; qch1 = qch.*kmod;
%%为了使所有的点有相同的平均功率,二进制序列映射后的复数要归一化。(BPSK\QPSK\16QAM\64QAM分别对应乘以1、1/根号2、1/根号10、1/根号42),解调的时候再变回去。
%IFFT
x = ich1 + qch1 *1j;
%%%%%%%%%%%%%% demoluation %%%%%%%%%%%%%%
ich7 = ich6./kmod;
qch7 = qch6./kmod;
demodata = qpskdemod(ich7,qch7,para,nd,ml);
%%%%%%%%%%%%%% 并串转换 %%%%%%%%%
demodata1 = reshape(demodata,1,para*nd*ml);
%%%%%%%%%%%%%%% Bit Error Rate %%%%%%%%%%%
noe2 = sum(abs(demodata1-seldata));
nod2 = length(seldata);
https://zhuanlan.zhihu.com/p/284010086
瑞利衰落信道
接收信号幅度服从瑞利分布;此外若有一部分散射分量强于其他,服从莱斯分布,衰落过程为莱斯衰落
均衡就是把符号间干扰去除的过程
在时域上,观测信号是输入信号和系统响应的线卷积,表达为: y = H x + n y = Hx + n y=Hx+n 。
并行传输能将频率选择性衰落,转化成多个平坦衰落(符号带宽<<相干带宽,符号周期长),这便是OFDM的优势了
信道系数h的理解
当我们说高斯白噪声信道时,描述这种信道下,接收端信号的表达式是: y=x+n
等到介绍衰落信道时,此时接收端信号的表达式是: y = h x + n
在衰落信道中,衰落信道对信号的作用,是不仅对信号乘以了h,还加上了噪声。
信道对输入的信号影响是幅度、频率和相位,因此h是一个复数,可写成 a + b j a + bj a+bj ,转化成 A e j θ A{e^{j\theta }} Ae jθ 也是可以的。
噪声一般考虑是接收机的热噪声。加噪声的过程都是在接收机中做的
原文链接:https://blog.csdn.net/weixin_44283855/article/details/113950025
代码:https://gitee.com/joannne/OFDM-basic
ofdm_fading_sim4.m
代码中可以看到导频的位置与间隔。我设置的有16个导频符号,间隔为4。
%%%%%%%%%%%%%%%%%%%%% OFDM仿真 %%%%%%%%%
%%%%%%%%%%%%%%%%%%%%% ofdm_fading_sim4.m %%%%%%%%%
%%%%%%%%% data:2020年11月17日 author:飞蓬大将军 %%%%%%%%%%
%%%%%程序说明
%%%多径衰落信道下的OFDM传输
%%%调制方式:QPSK
%%%信道编码方式:无
%%%导频方式:==梳状类型==
%%%sim系列说明
%%%sim2:接收端不做捕获和同步,也不做信道估计,假设知道信道条件,后续版本考虑信道估计
%%%sim3:发送端插入梳状导频、接收端采用LS和MMSE信道估计算法
%%%sim4:尝试解决sim3中遗留问题,并将LS均衡方法、MMSE均衡方法与完美均衡(即接收端知道h,直接fft来做均衡)
%%%% 仿真环境
%软件版本:MATLAB R2019a
%********************** 程序主体 ************%
%%%%%%%%%%%%%%%%%%%%% 参数设置 %%%%%%%%%%%%%%%%%%%
para = 48; %Number of parallel channel to transmit
fftlen = 64; %FFT length
noc = 64; %Number of carrier
nd = 1; %Number of information OFDM symbol for one loop
ml = 2; %Modulation:QPSK
sr = 250000; %Symbol rate 符号速率
br = sr.*ml; %Bit rate per carrier
gilen = 16; %length of guard interval
%%%%%%%%%%比特信噪比设置
%%%先设置大的,程序运行正确后,再设更多的信噪比设置,以画误码率曲线
% ebn0_temp = 80;
ebn0_temp = 1:1:30;
ber_fading_ls_linear = zeros(1,length(ebn0_temp));
ber_fading_ls_spline = zeros(1,length(ebn0_temp));
ber_fading_mmse = zeros(1,length(ebn0_temp));
ber_fading_per = zeros(1,length(ebn0_temp));
%%%%%%%导频信息
Nps = 4; %导频间隔,起始
B_pilot = 1; %导频起始位置,第1号子载波
Np = fftlen/Nps; %导频数量
for kkk = 1:length(ebn0_temp)
ebn0 = ebn0_temp(kkk); %Eb/No
%%%%%%%%%%%%%%%%%%%%%%%%%% Fading initialization %%%%%%%%%%%%%%
PowerdB=[-1 -8 -17 -21 -25]; % 信道抽头功率特性
Delay=[0 3 5 6 8]; % 信道时延,示例
% Delay=[0 3 5 56 78]; % 信道时延
Power=10.^(PowerdB/10); % 信道抽头功率特性 '线性'
Ntap=length(PowerdB); % 信道抽头数
Lch=Delay(end)+1; % 信道长度
%%%%%%%%%%%%%%%%%%%%% 主循环 %%%%%%%%%%%%%
nloop = 20000; %Number of sumulation loops
noe2_ls_linear_temp = 0; %Number of error data of LS_linear
noe2_ls_spline_temp = 0; %Number of error data of LS_spline
noe2_mmse_temp = 0; %Number of error data of MMSE
noe2_per_temp = 0; %Number of error data of perfect compensation
nod = 0; %Number of transmitted data
for iii = 1:nloop
%%%%%%%%%%%%%%%%% 发射机 %%%%%%%%%%%%%%%%%%%
seldata = rand(1,para*nd*ml)>0.5; %串行数据
% seldata = ones(1,para*nd*ml); %用于调试程序
paradata = reshape(seldata,para,nd*ml); %串并转换
[ich,qch] = qpskmod(paradata,para,nd,ml); %调制
kmod = 1/sqrt(2);
ich1 = ich.*kmod;
qch1 = qch.*kmod;
ch1 = ich1 + qch1*1j;
%%%%%%%%%%%将导频进行插入 梳状
% Xp = 2*(randn(1,Np)>0)-1; % Pilot sequence generation
% Xp = 2*randi([0 1],1,Np) - 1;
Xp = 2*ones(Np,nd) - 1;
%%%方式一:
X = zeros(fftlen,nd);
ip = 0;
pilot_loc = []; #预留导频位置
for k=1:fftlen
if mod(k,Nps)==1
temp = floor(k/Nps)+1;
X(k,:) = Xp(temp,:);
% X(k) = Xp(floor(k/Nps)+1);
pilot_loc = [pilot_loc k];
ip = ip+1;
else
X(k,:) = ch1(k-ip,:);
end
end
%%%%%方式二:可以先把导频位置和数据位置算出来,比如kk1,kk2,相应放入
%%%%%%%%%%%% IFFT %%%%%%%%%%
y = ifft(X);
ich2 = real(y);
qch2 = imag(y);
%%%观察信号功率
% spow2 = sum(sum(ich2.^2+ qch2.^2))/nd./para;
%%%%%%%% 添加保护间隔 %%%%%%%%
[ich3,qch3] = giins(ich2,qch2,fftlen,gilen,nd);
fftlen2 = fftlen + gilen;
%**************** Attenuation Calculation **************
% %%%方式一:
% spow = sum(ich3.^2+ qch3.^2)/nd./para;
% attn = 0.5*spow*sr/br*10.^(-ebn0/10);
% attn = sqrt(attn);
%%%方式二:
% snr = ebn0 + 10*log10(2);
% attn = sqrt(10.^(-snr/10)*spow/2);
%以上两种方式表达是一样的
%%%方式三:
spow4 = sum(ich3.^2+ qch3.^2)/nd./fftlen2;
esn0 = ebn0 + 10*log10(para/fftlen2) + 10*log10(ml);
attn2 = 0.5*spow4*10.^(-esn0/10);
attn2 = sqrt(attn2);
% aaa = 1; %用于调试
%*************** 衰落信道 Fading channel ***************%
channel = (randn(1,Ntap) + 1j * randn(1,Ntap)).*sqrt(Power/2);
h = zeros(1,Lch);
h(Delay+1) = channel;
y = conv(ich3 + 1j*qch3,h);
ifade = real(y(:,1:length(ich3)));
qfade = imag(y(:,1:length(ich3)));
spow5 = sum(ifade.^2+ qfade.^2)/nd./fftlen2;
% %%%方式四:
% esn0 = ebn0 + 10*log10(para/fftlen2) + 10*log10(ml);
% attn2 = 0.5*spow5*10.^(-esn0/10);
% attn2 = sqrt(attn2);
%
%%%%%不管哪种方式,以attn传入
attn = attn2;
%*********************** 接收机 *******************%
%%%%%%%%%%假设已经完美同步上
%%%%%%%%%% AWGN addition %%%%%%%%%
[ich4,qch4] = comb(ifade,qfade,attn);
%%%%%%%% 去掉保护间隔 %%%%%%%%
[ich5,qch5] = girem(ich4,qch4,fftlen2,gilen,nd);
%%%%%%%%%%%%%% FFT %%%%%%%%
rx = ich5 + qch5.*1i;
ry = fft(rx);
% ich6 = real(ry);
% qch6 = imag(ry);
%%%%%%% 信道估计 %%%%
for m=1:3
if m==1
H_est_ls_linear = LS_CE(ry.',Xp.',pilot_loc,fftlen,Nps,'linear');
% method='LS-linear'; % LS estimation with linear interpolation
elseif m==2
H_est_ls_spline = LS_CE(ry.',Xp.',pilot_loc,fftlen,Nps,'spline');
% method='LS-spline'; % LS estimation with spline interpolation
else
% H_est_mmse = MMSE_CE(ry.',Xp.',pilot_loc,fftlen,Nps,h,SNR);
H_est_mmse = MMSE_CE(ry.',Xp.',pilot_loc,fftlen,Nps,h,ebn0);
% method='MMSE'; % MMSE estimation
end
end % end for count'
%%%%%%%% 信道均衡 %%%%
%%%注意A的共轭转置和转置的区别,前者是A',后者是A.'
%%%%采用导频估计出的h,进行均衡
ry_ls_linear_temp = ry./(H_est_ls_linear.');
ry_ls_spline_temp = ry./(H_est_ls_spline.');
ry_mmse_temp = ry./(H_est_mmse.');
%%%假设接收端完美知道h,进行均衡
H = fft([h,zeros(1,fftlen-Lch)].');
ry_per_temp = ry./H;
%%%%%%%%%% 去除导频
ip = 0;
for k=1:fftlen
if mod(k,Nps)==1
% temp = floor(k/Nps)+1;
% X(k,:) = Xp(temp,:);
% % X(k) = Xp(floor(k/Nps)+1);
% pilot_loc = [pilot_loc k];
ip = ip+1;
else
ry_ls_linear(k-ip,:) = ry_ls_linear_temp(k,:);
ry_ls_spline(k-ip,:) = ry_ls_spline_temp(k,:);
ry_mmse(k-ip,:) = ry_mmse_temp(k,:);
ry_per(k-ip,:) = ry_per_temp(k,:);
end
end
%%%%%%%%%%%%%% demoluation %%%%%%%%%%%%%
demodata_ls_linear = qpskdemod(real(ry_ls_linear)./kmod,imag(ry_ls_linear)./kmod,para,nd,ml);
demodata_ls_spline= qpskdemod(real(ry_ls_spline)./kmod,imag(ry_ls_spline)./kmod,para,nd,ml);
demodata_mmse = qpskdemod(real(ry_mmse)./kmod,imag(ry_mmse)./kmod,para,nd,ml);
demodata_per = qpskdemod(real(ry_per)./kmod,imag(ry_per)./kmod,para,nd,ml);
%%%%%%%%%%%%%% 并串转换 %%%%%%%%%
demodata1_ls_linear = reshape(demodata_ls_linear,1,para*nd*ml);
demodata1_ls_spline = reshape(demodata_ls_spline,1,para*nd*ml);
demodata1_mmse = reshape(demodata_mmse,1,para*nd*ml);
demodata1_per = reshape(demodata_per,1,para*nd*ml);
%%%%%%%%%%%%%%% Bit Error Rate %%%%%%%%%%%
noe2_ls_linear = sum(abs(demodata1_ls_linear-seldata));
noe2_ls_spline = sum(abs(demodata1_ls_spline-seldata));
noe2_mmse = sum(abs(demodata1_mmse-seldata));
noe2_per = sum(abs(demodata1_per-seldata));
nod2 = length(seldata);
%%%%cumulative the number of error and data in noe and nod
noe2_ls_linear_temp = noe2_ls_linear_temp + noe2_ls_linear; %Number of error data of LS_linear
noe2_ls_spline_temp = noe2_ls_spline_temp + noe2_ls_spline ; %Number of error data of LS_spline
noe2_mmse_temp = noe2_mmse_temp + noe2_mmse; %Number of error data of MMSE
noe2_per_temp = noe2_per_temp + noe2_per;
nod = nod + nod2;
end
%************** output result *************
ber_ls_linear_temp = noe2_ls_linear_temp/nod;
ber_ls_spline_temp = noe2_ls_spline_temp/nod;
ber_mmse_temp = noe2_mmse_temp/nod;
ber_per_temp = noe2_per_temp/nod;
ber_fading_ls_linear(1,kkk) = ber_ls_linear_temp ;
ber_fading_ls_spline(1,kkk) = ber_ls_spline_temp;
ber_fading_mmse(1,kkk) = ber_mmse_temp;
ber_fading_per(1,kkk) = ber_per_temp;
end
%************************* 画误码率曲线进行对比 ******************%
ebn0_temp = 1:1:30;
rayleign_one_path_theory = ber_temp(ebn0_temp);
semilogy(ebn0_temp,rayleign_one_path_theory,'-*',ebn0_temp,ber_fading_ls_linear,'-^',ebn0_temp,ber_fading_ls_spline,'->',ebn0_temp,ber_fading_mmse,'-<',ebn0_temp,ber_fading_per,'-+');
xlabel('比特信噪比');
ylabel('误码率');
title('多径衰落信道下误码率仿真曲线');
legend('理论曲线','lslinear实验曲线','lsspline实验曲线','mmse实验曲线','完美均衡实验曲线');
grid on;
%*********** 多径瑞利衰落下的OFDM采用BPSK调制的误码率值 **********%
%%%%%%%%%%%%%%%%%%%%%%% 理论值 **************%
%%%%%%%%%%%%% EbN0(dB) 误码率
%%%%%%%%%%%%% 3 0.125000000000000
%%%%%%%%%%%%% 4 0.100000000000000
%%%%%%%%%%%%% 5 0.0833333333333333
%%%%%%%%%%%%% 6 0.0714285714285715
%%%%%%%%%%%%% 7 0.0625000000000000
%%%%%%%%%%%%% 8 0.0555555555555556
%%%%%%%%%%%%% 9 0.0500000000000000
%%%%%%%%%%%%% 10 0.0454545454545455
%%%%%%%%%%%%%%%%% 结论 %%%%%%%%%%%%%%%%%%%%
%%%实验记录 2020年11月14日
%含已知导频的OFDM经过多径衰落信道的误码率仿真
%OFDM中引入保护间隔,是一种冗余信息,因此相比于理论误码率曲线有10*log(160/128)=0.969dB的损失
%OFDM信道估计引入了发送和接收端都已知的导频信号,这也是冗余,所以设计SNR与Eb/N0的换算
%本次实验还缺少相应的理论分析
(1)保护间隔(GI)和循环前缀(CP)、补零(zero padding,ZP)的区别
(2)OFDM与IFFT、FFT的关系
(3)子载波(ICI)和符号间干扰(ISI)的区别
https://zhuanlan.zhihu.com/p/142925111
梳状导频是在发送信号的频域内进行内插来实现的。
ofdm_fading_sim4.m
%%%%%%%%%%%将导频进行插入
% Xp = 2*(randn(1,Np)>0)-1; % Pilot sequence generation
% Xp = 2randi([0 1],1,Np) - 1;
Xp = 2ones(Np,nd) - 1;
%%%方式一:
X = zeros(fftlen,nd);
ip = 0;
pilot_loc = [];
for k=1:fftlen
if mod(k,Nps)==1 %mod(a,b)就是求的是a除以b的余数
temp = floor(k/Nps)+1;
X(k,:) = Xp(temp,:);
% X(k) = Xp(floor(k/Nps)+1);
pilot_loc = [pilot_loc k];
ip = ip+1;
else
X(k,:) = ch1(k-ip,:);
end
end
以梳状导频为例来详细的介绍导频在信道估计中起到的作用,梳状导频是在发送信号的频域内进行内插来实现的:https://zhuanlan.zhihu.com/p/142925111
基于MATLAB实现OFDM系统基带信号在频率选择性衰落信道条件下的发送与接收
时间说按周期插入
pilot_interval=5; %导频间隔
pilot_bit_l=randi([0 1],1,M*carrier_count);%生成导频序列,长度为M*carrier_count
num_bit=carrier_count*symbol_count*M; %对应比特数据个数,即128*1000*2
% ================产生随机序列=======================
OFDM_sigbits =sourcebits(num_bit) ; % 1*256000,发送的OFDM数据
[moddata_outI,moddata_outQ]=qpsk_modulation(OFDM_sigbits); %进行映射
OFDMmoddata_in_temp=moddata_outI+1i*moddata_outQ;
OFDMmoddata_in=reshape(OFDMmoddata_in_temp,carrier_count,length(OFDMmoddata_in_temp)/carrier_count); %串并变换
% ================加导频========================
[Insertpilot_out,count,pilot_seq]=insert_pilot_f(OFDMmoddata_in,pilot_bit_l,pilot_interval); %加入导频后的矩阵为Insertpilot_out,大小为128*1200
% ===================IFFT===========================
OFDMmoddata_out=ifft(Insertpilot_out,ifft_length)*sqrt(ifft_length);
DW OFDM_benchmark.m
% 子载波数N其数值与FFT处理过的复数点数相对应
N = 64; % FFT size, Number of total subcarriers
Ncp = 16; % Length of Cyclic prefix
Ts = 1e-7; % Sampling period of channel
Fd = 0; % Max Doppler frequency shift
Np = 8; % No of pilot symbols 导频长度
Ng = 4; % No of side guard subcarriers 边保护带
.
....
% 1.3 Calculate pilot locations 插入导频
DC_sc = [N/2, N/2+1];
Effec_sc = [Ng+1:N-Ng]; %有效子载波位置
%C=setdiff(A, B, 'rows') 意思是对于行来讲,返回属于矩阵A而不属于矩阵B的行向量所组成的矩阵
Effec_sc = setdiff(Effec_sc, DC_sc);
% Pilot_sc = [5,12,19,26,34,41,48,55];
pilot_loc = [1:ceil(length(Effec_sc)/Np):length(Effec_sc)];
Pilot_sc = Effec_sc(pilot_loc);
guard_sc = [1:Ng,N-Ng+1:N]; %上、下保护带 长度为8
Np = length(pilot_loc); % Recalculate Number of pilot
pilot_sc_frame = [];
guard_sc_frame = [];
DC_sc_frame = [];
for i_sym = 0:Frame_size-1 %数据位置
%导频类型
pilot_sc_sym = Effec_sc(sort(mod((pilot_loc + i_sym*3)-1,length(Effec_sc))+1)); % scattered
% pilot_sc_sym = Pilot_sc; % comb pilot
pilot_sc_frame = [pilot_sc_frame, pilot_sc_sym+i_sym*N];
guard_sc_frame = [guard_sc_frame, guard_sc+i_sym*N];
DC_sc_frame = [DC_sc_frame, DC_sc+i_sym*N];
end
data_sc_frame = setdiff([1:Frame_size*N],guard_sc_frame);
data_sc_frame = setdiff(data_sc_frame, pilot_sc_frame);
data_sc_frame = setdiff(data_sc_frame, DC_sc_frame);
格状: pilot_sc_sym = Effec_sc(sort(mod((pilot_loc + i_sym*3)-1,length(Effec_sc))+1)); % scattered
梳状: pilot_sc_sym = Pilot_sc; % comb pilot