目录
一、OFDM经典框架图
- 一、OFDM经典框架图
- 二、基础理论
- (一)导频(Pilot)
- (二)保护间隔(Guard)
- (三)帧、符号、子载波、导频、保护间隔的关系
- 三、代码流程图
- 四、代码
- 五、代码和原图下载
-
本质:导频不携带信息,导频是双方已知的数据,因为所有子载波会产生一定的相位偏移,在信号中插入导频是提供相位参考,来做接收信号时候的信道估计。
-
原理:将训练信号(导频)插入帧中,以便接收器可以根据导频和数据类似地失真的假设来估计信道响应。 设计了一种适当的导频模式来满足这种假设。 OFDM系统中的典型导频模式为:块,梳状和分散式。如下图所示。
-
也叫保护频带
-
作用:多径信道会对OFDM符号造成ISI影响,破坏了子载波间的正交性。故需要采取一些方法来消除多径信道带来的符号间干扰(ISI)影响,即插入保护间隔。
-
方法:
- 补零(zp),即在保护间隔中填充0
- 另一种是插入循环前缀(cp)或循环后缀(cs)实现OFDM的循环扩展(为了某种连续性),cp是将OFDM后部的采样复制到前面,长度为Tcp,故每个符号的长度为Tsym=Tsub+Tcp,Tsub为数据部分子载波数。Tcp大于或等于多径时延,符号间的ISI影响将被限制在保护间隔中,因此不会影响下一个OFDM的FFT变换。
- 该图中是一帧数据,64× 8 的矩阵,64行表示64个子载波,8列表示8个OFDM符号。这个图对应以下代码的各个参数设置。结合该该图和代码理解,几者的关系。
% Benchmark code for OFDM communication system in AWGN channel
% AWGN信道下OFDM通信系统的基准码
%% Step 1: Configurations
clc;
%clear all;
close all;
save_tx_data = 1;
if save_tx_data
mkdir('mat');
end
% 1.1 OFDM parameters
N = 64; % FFT size, Number of total subcarriers FFT大小,子载波总数
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 保护频带数
Ndc = 2; % No of DC guard subcarriers 直流保护频带数
Ndata = N - Np - 2.*Ng - Ndc; % No of Data subcarriers per symbol 每个符号的数据子载波数46
Frame_size = 8; % OFDM symbols per frame 每帧的OFDM符号数
Nframes = 1000; % Size of tested OFDM frames: set as 10^4 for smooth curve传送的数据帧数量
M_set = [2, 4, 8, 16]; % Modulation orders 调制方式序列
SNRs = 0:1:8; % Test SNR points 测试的信噪比取值区间
% 1.2 Vehicles for results 存结果
berofdm_all = zeros(5,length(SNRs));
berofdm_all(1,:) = SNRs;
serofdm_all = zeros(5,length(SNRs));
serofdm_all(1,:) = SNRs;
% 1.3 Calculate pilot locations 计算导频位置 ,以上图片中黄色圆圈的位置
DC_sc = [N/2, N/2+1]; % 32 33 第一个符号中直流保护频带的位置下标;以上图片中中间两行白色圆圈部分
Effec_sc = [Ng+1:N-Ng]; %5~60
Effec_sc = setdiff(Effec_sc, DC_sc);% 5:1:6 % 第一个符号中数据+导频的位置下标
pilot_loc = [1:ceil(length(Effec_sc)/Np):length(Effec_sc)];% 产生第一个符号中导频的位置下标
Pilot_sc = Effec_sc(pilot_loc); % 存储第一个符号中导频的位置下标
% guard_sc = [1,2,3,4,61,62,63,64]
guard_sc = [1:Ng,N-Ng+1:N]; % 保护频带的位置下标,以上图片上四行和尾四行的白色圆圈部分
Np = length(pilot_loc); % Recalculate Number of pilot 8
pilot_sc_frame = []; % 存储一帧8个符号所有的导频下标位置
guard_sc_frame = []; % 存储一帧8个符号所有的保护频带下标位置
DC_sc_frame = [];; % 存储一帧8个符号所有的直流保护频带下标位
for i_sym = 0:Frame_size-1 %0~7 % 在一帧中8个符号一次计算导频+保护频带+直流保护频带位置
pilot_sc_sym = Effec_sc(sort(mod((pilot_loc + i_sym*3)-1,length(Effec_sc))+1));
pilot_sc_frame = [pilot_sc_frame, pilot_sc_sym+i_sym*N];% 5:7:504 ;1* 64 % 采用Comb的导频方式
guard_sc_frame = [guard_sc_frame, guard_sc+i_sym*N];%1:1:502
DC_sc_frame = [DC_sc_frame, DC_sc+i_sym*N];
end
% C=setdiff(A,B)函数返回在向量A中却不在向量B中的元素,并且C中不包含重复元素,并且从小到大排序。
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); %% 存储一帧8个符号所有的数据下标位置 % 存储一帧8个符号所有的保护频带下标位
%% Step 2: Test Loops
mod_names = {'BPSK','QPSK','8QAM','16QAM'}; % 该代码只是测试了BPSK的调制方式
channel = 'AWGN';
mat_name = sprintf('BER_OFDM_%s_Gray.mat',channel);
csv_name = sprintf('BER_OFDM_%s_Gray.csv',channel);
snr = SNRs;
for m_ary = 1:1
M = M_set(m_ary); %BPSK调制方式 % 选择BPSK的调制方式
berofdm = zeros(1,length(snr)); % 为存储误码率做准备
serofdm = zeros(1,length(snr)); % 为信号错误率做准备
for i = 1:length(snr) % 9 % 在9个不同信噪比下做调制解调
% Step 2.1 Transmitter
% 2.1.1 Random bits generation
D = round((M-1)*rand(Ndata*Frame_size,Nframes)); % 随机产生要传送的数据域
D_test = reshape(D, Ndata, Frame_size*Nframes); % 第一次矩阵变换 46× 8000(8× 1000)
D_gray = D_test; % gray2bin(D_test,'qam',M); 46* 16000的矩阵
txbits = de2bi(D_gray(:)); % de2bi 把十进制数转换成二进制向量,为计算误码率做准备
% 2.1.2 Modulation
Dmod = qammod(D,M,'gray');
% 2.1.3 Framing 组装成帧,构造帧
Data = zeros(N*Frame_size,Nframes); % 初始化一个存储所有帧的矩阵
Data(data_sc_frame,:) = Dmod; % 把数据域插入到矩阵中
txamp = max(abs(Dmod(:)));
pilot_signal = txamp.*sqrt(1/2).*(1+1i); % Norm pilot power to peak constellation power 初始化一个导频的数值
Data(pilot_sc_frame,:)= pilot_signal; % 把导频插入到矩阵中
Data = reshape(Data, N, Frame_size*Nframes); % 第二次矩阵变换 64× 8000
% 2.1.4 To Time-domain OFDM symbol
IFFT_Data = (N/sqrt(N-2*Np))*ifft(Data,N); % 频域转时域,及时傅里叶变换
TxCy = [IFFT_Data((N-Ncp+1):N,:); IFFT_Data]; % Add Cyclic prefix添加16位的循环前缀
[r, c] = size(TxCy);
Tx_Data = TxCy;
% 2.1.5 Clip PAPR to 8 (9dB)削减PAPR?????????
%由于OFDM 符号是由多个独立经过调制的子载波信号叠加而成的,
%当各个子载波相位相同或者相近时,叠加信号便会受到相同初始相位信号的调制,
%从而产生较大的瞬时功率峰值,由此进一步带来较高的峰值平均功率比
%
Tx_Amp = abs(Tx_Data); %对复数取模
Tx_Power = Tx_Amp.^2;
Power_PAPR8 = 8.*mean(Tx_Power,1);
Clip_loc = Tx_Power > Power_PAPR8;
Clip_Data = Tx_Data./Tx_Amp;
Clip_Data = sqrt(Power_PAPR8).*Clip_Data;
Tx_Data(Clip_loc) = Clip_Data(Clip_loc);
% Step 2.2 Wireless Channel % 模拟信道的串并转换
Tx_Data = reshape(Tx_Data, r*Frame_size,[]); % 第三次矩阵变换640× 1000
% 2.2.2 Add AWGN noise
y1 = awgn(Tx_Data,snr(i),'measured'); % 模拟信道,添加高斯白噪声
y = reshape(y1,r,[]); %80* 8000 % 出信道,80× 8000第四次矩阵变换
% Step 2.3: OFDM Receiver
% 2.3.1 Remove cyclic prefix 去循环前缀
Rx = y(Ncp+1:r,:);
% 2.3.2 Transform to Frequency-Domain 转换时域到频域
Rx_Freq = (sqrt(N-2*Np)/N)*fft(Rx,N,1);
% 2.3.3 Reshape to Frame size
FFT_Data = reshape(Rx_Freq,N*Frame_size,[]); % 512× 1000 第五次矩阵变换,为提取每一帧的数据单元
% 2.3.4 Extract Data Cells 提取数据单元格,从每一帧中提取数据
FFT_Data = reshape(FFT_Data(data_sc_frame,:), [], Nframes*Frame_size);%46× 8000 第六次矩阵变换,为解调
% 2.3.5 Demodulation
Rx_Data = qamdemod(FFT_Data,M,'gray');
Rx_gray = Rx_Data
rxbits = de2bi(Rx_gray(:)); %为了计算误码率而要转换成二进制的
% Step 2.4 Collect BER and SER
[bitErrors,ber] = biterr(txbits,rxbits);
%[number,ratio] = symerr(x,y)
%输出number是一个标量或向量,表示不同元素的数量。 输出ratio等于number除以较小输入中的元素总数。
[symErrors,ser] = symerr(Rx_Data(:),D(:)); %计算符号错误数和符号错误率
serofdm(i) = ser;
berofdm(i) = ber;
Y(1,1,:,(i-1)*Nframes+1:i*Nframes) = D; %存储原始信号数据
IX = real(y1); %提取IQ信号的实部
QX = imag(y1); %提取IQ信号的虚部
for j =1:size(IX,2)
tempX(:,:,1,j) = [IX(:,j) QX(:,j)];
end
X(:,:,1,(i-1)*Nframes+1:i*Nframes) = tempX; %存IQ信号
end
berofdm_all(m_ary+1,:) = berofdm; %存误码率
serofdm_all(m_ary+1,:) = serofdm; %存符号错误率
end
%% Step 3: Result Presentation: Plot BER
save(mat_name, 'berofdm_all','serofdm_all');
csvwrite(csv_name, berofdm_all);
figure;
semilogy(SNRs,berofdm_all(2:5,:),'--x','LineWidth',2);
grid on;
title('OFDM BER vs SNR in AWGN channel');
xlabel('SNR (dB)');
ylabel('BER');
legend(mod_names);
save('Data_BPSK.mat','X','Y');
五、代码和原图下载
OFDM存储IQ信号代码、OFDM的帧关系图、代码流程图下载