前言
本文继续进行 OFDM 通信连路仿真学习。
一、前置知识
1、块状导频与梳状导频
块状导频也称为训练序列
①、相似点
- 导频序列和训练序列的作用都是为了得到准确符号同步和频偏纠正;
- 导频序列和训练序列都进行信道估计;
- 二者都传输已知数据;
- 二者都可称之为基于辅助信息的信道估计方法;
②、区别
- 添加位置不同:导频序列加在频域上,作用在频域。训练序列是在时域上添加的特定的序列;
- 表现形式不同:导频序列表现为频谱上的一根线,散布在整个时频单元(在整个帧中是离散的)。训练序列表现为时域上的时间块,一个或多个连续的符号(集中在帧头并且连续)。
- 要求不同:加在时域的训练序列要求有较强自相关性和弱互相关性。加在频域的导频序列无此要求。
③、其他
- 同步信道(sync channel)的概念一般只在训练序列中涉及,对于导频来说似乎没有;
- 导频的频率应当是与载频有关的或者就是载频的频率;
- 块状导频就相当于训练序列;
- 导频序列常用于载波同步,训练序列用于帧同步;
- 二者都可进行信道估计,信道估计的目的是获得信道的一些参数,如频移、时延等。因此信道估计也称为信道参数估计。
2、其他知识
有关其他仿真细节原理知识可以参考我之前的博客:OFDM深入学习及MATLAB仿真
二、仿真任务及方案
1、仿真任务
- 使用 Matlab 语言,仿真实现 OFDM 基带信号在频率选择性信道条件下的发送与接收。输入为随机比特流,经由 OFDM 调制、仿真信道传输、OFDM 解调后输出比特流,可计算不同信噪比条件下的误码率。其中子载波间隔 15KHz,循环前缀长度及子载波数目可调,各子载波使用 QPSK 调制。
- 信道:信号经历 3GPP TS36.101 附录 B 中表 B.2.2-1 给出的ETU300 多径信道,随后叠加一个信噪比可调的 AWGN 信道。
- 要求:能够查看并解释从输入到输出沿路各点信号的时域波形和频域特性图;能够绘制误码率随信噪比变化的曲线。
- 设计梳状或块状导频并在接收端完成信道估计与补偿(即均衡)。
2、仿真方案
- 本方案在满足以上要求的前提下,选用了块状导频;除了循环前缀长度及子载波数目可调外,可以通过改变 M 的值,选用 MPSK,且导频间隔与 OFDM 符号数可任意调整,并具有信道编码,交织,脉冲成型模块。
- 仿真系统模块依次为:
- 二进制基带数据生成,卷积码编码,交织,QPSK调制,串并转换,加入虚载波(补零,数目为 fft 点数减去子载波数),插入导频,IFFT,插入循环前缀,并串转换,脉冲成型(先上采样再通过升余弦滚降滤波器),过信道。
- 解脉冲成型(通过相同的升余弦滚降滤波器,再抽样),串并转换,去循环前缀,FFT,信道估计(取出数据与导频,进行LS信道估计),去除虚载波(去零),并串转换,QPSK解调,解交织,信道译码(维比特译码),得到数据并计算误码率。
三、MATLAB仿真
1、MATLAB 源码
ofdm.m
代码语言:javascript复制%%
% 仿真系统构成:信号输入(为随机比特流)、OFDM调制、仿真信道传输、OFDM解调、信号输出
% 仿真分析内容:根据输入、输出比特流计算不同信噪比条件下的误码率,
% 并绘制曲线对调制的要求:
% OFDM调制的子载波间隔为15KHz
% 循环前缀长度,子载波数目,导频间隔及ofdm符号数可调,
% 各子载波使用QPSK调制
% 未使用扩频技术,未乘以载波进行上变频,未测试梳妆导频性能
%%
clc;
clear ;
close ;
tic;
disp("simulation start");
%% 参数设置
sta_num = 5; %仿真次数
SNR = -4:1:25;
num_carriers = 100; %子载波数
cp_length = 15; %循环前缀长度
M = 8; %QPSK时,M=4
is_pilot_k = 1; %块状导频
q = 8; %fs = q*B_jidai;
pilot_interval = 4; %导频间隔
num_ofdm_symbol = 99; %ofdm符号数
%% 以上参数为可调部分
f_delta = 15e3;
n = 1;
while(true)
% if(2^n >= num_carriers / pilot_interval * (pilot_interval 1))
if(2^n >= num_carriers )
num_fft = 2^n;
break;
end
n = n 1;
end
num_bit = num_carriers * num_ofdm_symbol * log2(M);%二进制bit数 乘以 log2(M) 是为了考虑调制方式对传输数据的影响
B_jidai = num_carriers * f_delta; %基带宽度
fs = q*B_jidai; %数字系统采样率
ts = 1/fs;
fd = 300; %多普勒频偏
pathPower = [-1.0 -1.0 -1.0 0 0 0 -3.0 -5.0 -7.0];
pathDelays = [0 50 120 200 230 500 1600 2300 5000]*1e-9;
% chan = rayleighchan(ts, fd, pathDelays, pathPower);
rchan = comm.RayleighChannel('SampleRate',fs, ...
'PathDelays',pathDelays,'AveragePathGains',pathPower, ...
'MaximumDopplerShift',fd,'FadingTechnique','Sum of sinusoids');
%% 基带数据数据产生
data_sourcebit = randi([0,1],1,num_bit);
%% 信道编码(卷积码、再交织)
L=7; %卷积码约束长度
tblen=6*L; %Viterbi译码器回溯深度
trellis = poly2trellis(7,[133 171]); %(2,1,7)卷积编码
data_conv = convenc(data_sourcebit,trellis);
data_scramble = matintrlv(data_conv, log2(M), length(data_conv) / log2(M));
%% qpsk调制
data_dec = bi2de(reshape(data_scramble,length(data_scramble)/log2(M),log2(M)));
data_moded = pskmod(data_dec,M,pi/M);
scatterplot(data_moded);
%% 串并转换
data_moded = reshape(data_moded,num_carriers,length(data_moded)/num_carriers);
%% 扩频
%%补零
data_buling = [data_moded;...
zeros(num_fft-size(data_moded,1),size(data_moded,2))];
%% 插入导频
if (is_pilot_k==1)
pilot_bit_k = randi([0,1],1,log2(M)*num_fft);
pilot_seq = pskmod(bi2de...
(reshape(pilot_bit_k,length(pilot_bit_k)/log2(M),log2(M))),M,pi/M);
data_pilot_inserted = insert_pilot_f(data_buling,pilot_seq,pilot_interval,is_pilot_k);
end
%% IFFT
data_ifft = ifft(data_pilot_inserted,num_fft)*num_fft;
�ta_ifft = ifft(data_pilot_inserted,num_fft)*sqrt(num_fft);
%% 插入保护间隔、循环前缀
data_after_cp = [data_ifft(num_fft-cp_length 1:end,:);data_ifft];
%% 并串转换
data_total = reshape(data_after_cp,[],1);
%% 脉冲成型,
sendfir = rcosdesign(0.4,4,fs/B_jidai,'sqrt');
data_upsam = upsample(data_total,fs/B_jidai);
data_send = conv(data_upsam,sendfir,'same');
%% 画图
signal = data_send;
figure(2);
subplot(311);
plot(real(signal));
subplot(312);
plot(imag(signal));
subplot(313);
fft_y=abs(fft(signal,q*num_fft));
fft_x=fs*((1:(q*num_fft))/(q*num_fft)-1/2);
plot(fft_x,20*log10(fftshift(fft_y./max(fft_y))));
%% DA
%% 上变频
%% 信道(通过多经瑞利信道、AWGN信道)
Ber=zeros(1,length(SNR));
for jj=1:length(SNR)
for ii=1:sta_num
channel_out = step(rchan,data_send);
rx_channel=awgn(channel_out,SNR(jj),'measured');
%% 下变频
%% AD
rx_data1 = conv(rx_channel, sendfir, 'same');
rx_data2 = rx_data1(1:fs/B_jidai:length(rx_data1));
%% 串并转换
rx_data3=reshape(rx_data2,num_fft cp_length,[]);
%% 去掉循环前缀
rx_data4=rx_data3(cp_length 1:end,:);
%% FFT
rx_data_fft = (1/num_fft)*fft(rx_data4,num_fft);
%% 信道估计与插值(均衡)
%% 信道校正
[rx_data_delpilot,H] = get_pilot_f(rx_data_fft,pilot_interval);
rx_data_estimation = chan_estimation_f...
(rx_data_delpilot,H,pilot_seq,pilot_interval);
%% 去零,并串转换
rx_data_quling = rx_data_estimation(1:num_carriers,:);
rx_data_psk = reshape(rx_data_quling,[],1);
% scatterplot(rx_data_psk);
%% 解扩
%% QPSK解调
demodulation_data=pskdemod(rx_data_psk,M,pi/M);
De_data1 = reshape(demodulation_data,[],1);
De_data2 = de2bi(De_data1);
De_Bit = reshape(De_data2,1,[]);
%% (解交织)
rx_data_jiejiaozi = matdeintrlv(De_Bit, log2(M), length(De_Bit) / log2(M));
%% 信道译码(维特比译码)
rx_data_deco = vitdec(rx_data_jiejiaozi,trellis,tblen,'trunc','hard'); %硬判决
%% 计算误码率
[~, ber] = biterr(rx_data_deco(1:length(data_sourcebit)),data_sourcebit);%译码后的误码率
Ber(jj)=Ber(jj) ber;
end
Ber(jj)=Ber(jj)/sta_num;
fprintf("SNR = %d dB, ber = %.5f n",SNR(jj),Ber(jj));
end
figure(3);
signal = rx_channel;
subplot(311);
plot(real(signal));
subplot(312);
plot(imag(signal));
subplot(313);
fft_y=abs(fft(signal,q*num_fft));
fft_x=fs*((1:(q*num_fft))/(q*num_fft)-1/2);
plot(fft_x,20*log10(fftshift(fft_y./max(fft_y))));
figure(4);
% semilogy(SNR,Ber2,'b-s');
% hold on;
semilogy(SNR,Ber,'r-o');
hold on;
xlabel('SNR');
ylabel('BER');
title('ETU300叠加AWGN信道下误比特率曲线');
toc;
- 第 36 行计算
num_bit
时乘以log2(M)
是为了考虑调制方式对传输数据的影响。- 在 OFDM 系统中,每个子载波上可以传输多个比特,通常使用调制方式将多个比特映射到一个符号上进行传输。调制方式可以是 QPSK、16-QAM、64-QAM等。
- 在计算
num_bit
时,乘以log2(M)
可以得到需要传输的总比特数。这是因为在 OFDM 系统中,每个 OFDM 符号的数据部分由多个子载波组成,每个子载波上都传输一定数量的比特,因此需要考虑每个符号上的比特数和调制方式的关系。
- 第 82 行使用
rcosdesign
函数设计了一个根号升余弦滤波器。该函数的输入参数为滚降系数(0.4)、滤波器的长度(4),以及滤波器的归一化截止频率(fs/B_jidai
),其中fs
为数字系统的采样率,B_jidai
为基带带宽。这个滤波器的作用是在信号传输过程中对信号进行滤波,以限制频带内的能量,并控制信号的带内和带外衰减。 - 第 83 行使用
upsample
函数对输入的信号data_total
进行上采样。上采样是将信号的采样率提高,即在信号中插入更多的零值样本,以增加信号的频带范围。上采样的倍数为fs/B_jidai
,其中fs
为数字系统的采样率,B_jidai
为基带带宽。 - 第 84 行使用
conv
函数对上采样后的信号data_upsam
和滤波器的脉冲响应 sendfir 进行卷积运算。卷积运算的结果是将信号通过滤波器,得到经过滤波的信号。'same'
参数表示输出的卷积结果与输入信号的长度相同。 - 第 94 行计算频域的横坐标,即频率。fs 是采样率,
(1:(q*num_fft))/(q*num_fft)-1/2
生成一个从 -0.5 到 0.5 的等间隔序列,并乘以采样率 fs 得到真实的频率值。 - 第 95 行在当前子图中绘制频谱图。
fftshift
函数将频域数据进行移位,使得 0 频率位于图形中心。./max(fft_y)
将FFT
结果进行归一化处理,使得最大值为 1。20*log10
将幅度转换为以分贝为单位的对数尺度。绘制出的图形将显示信号的频域特性。 - 第 107-108 行:这两行代码实现了接收端的信号处理。首先,通过卷积运算将接收到的信号与发送端的滤波器的脉冲响应进行反脉冲成型,恢复出发送信号的波形。然后,通过采样操作从反脉冲成型后的信号中提取出每个采样点的样本,以便后续的信号解调和处理。提取后的样本保存在
rx_data2
变量中。- 第 107 行使用
conv
函数将接收到的信号rx_channel
与发送端的滤波器的脉冲响应sendfir
进行卷积运算。卷积的结果是对接收信号进行反脉冲成型,即恢复出发送信号经过信道传输后的波形。'same'
参数表示输出的卷积结果与输入信号的长度相同。
- 第 107 行使用
- 第 110 行:将接收到的连续信号按照每个子载波的长度(包括循环前缀)进行分组,重新排列为一个矩阵。矩阵的每一列对应于一个子载波的信号样本,行数则表示每个子载波上进行FFT的点数加上循环前缀的长度。这样做的目的是为了后续对每个子载波进行 FFT 处理,以提取频域信息。
2、程序流程
程序流程思维导图文末资源自取。
3、仿真结果
①、打印信息
代码语言:javascript复制simulation start
SNR = -4 dB, ber = 0.45980
SNR = -3 dB, ber = 0.45087
SNR = -2 dB, ber = 0.42770
SNR = -1 dB, ber = 0.41361
SNR = 0 dB, ber = 0.38854
SNR = 1 dB, ber = 0.37098
SNR = 2 dB, ber = 0.34956
SNR = 3 dB, ber = 0.32510
SNR = 4 dB, ber = 0.30745
SNR = 5 dB, ber = 0.28106
SNR = 6 dB, ber = 0.25711
SNR = 7 dB, ber = 0.24377
SNR = 8 dB, ber = 0.22386
SNR = 9 dB, ber = 0.21781
SNR = 10 dB, ber = 0.21100
SNR = 11 dB, ber = 0.20307
SNR = 12 dB, ber = 0.18618
SNR = 13 dB, ber = 0.19459
SNR = 14 dB, ber = 0.16919
SNR = 15 dB, ber = 0.16418
SNR = 16 dB, ber = 0.16908
SNR = 17 dB, ber = 0.15683
SNR = 18 dB, ber = 0.15314
SNR = 19 dB, ber = 0.15960
SNR = 20 dB, ber = 0.14756
SNR = 21 dB, ber = 0.17572
SNR = 22 dB, ber = 0.16144
SNR = 23 dB, ber = 0.14231
SNR = 24 dB, ber = 0.15244
SNR = 25 dB, ber = 0.15856
时间已过 29.591768 秒。
③、8PSK 星座图
②、脉冲成型图
从上到下依次为脉冲成型后待发送的实部图、虚部图和频谱图
③、ETU300登加AWGN信道下误比特率曲线
四、资源自取
OFDM通信连路仿真学习
本文参考: matlab-ofdm通信链路仿真