您当前的位置: 首页 >  ar

Better Bench

暂无认证

  • 0浏览

    0关注

    695博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

OFDM中的帧(frame)、符号(symbol)、子载波(subcarriers)、导频(Pilot)、保护间隔(guard)的关系图解以及代码详解--MATLAB

Better Bench 发布时间:2020-08-16 19:35:49 ,浏览量:0

目录
  • 一、OFDM经典框架图
  • 二、基础理论
    • (一)导频(Pilot)
    • (二)保护间隔(Guard)
    • (三)帧、符号、子载波、导频、保护间隔的关系
  • 三、代码流程图
  • 四、代码
  • 五、代码和原图下载

一、OFDM经典框架图

在这里插入图片描述

二、基础理论 (一)导频(Pilot)
  • 本质:导频不携带信息,导频是双方已知的数据,因为所有子载波会产生一定的相位偏移,在信号中插入导频是提供相位参考,来做接收信号时候的信道估计。

  • 原理:将训练信号(导频)插入帧中,以便接收器可以根据导频和数据类似地失真的假设来估计信道响应。 设计了一种适当的导频模式来满足这种假设。 OFDM系统中的典型导频模式为:块,梳状和分散式。如下图所示。 在这里插入图片描述

(二)保护间隔(Guard)
  • 也叫保护频带

  • 作用:多径信道会对OFDM符号造成ISI影响,破坏了子载波间的正交性。故需要采取一些方法来消除多径信道带来的符号间干扰(ISI)影响,即插入保护间隔。

  • 方法:

  1. 补零(zp),即在保护间隔中填充0
  2. 另一种是插入循环前缀(cp)或循环后缀(cs)实现OFDM的循环扩展(为了某种连续性),cp是将OFDM后部的采样复制到前面,长度为Tcp,故每个符号的长度为Tsym=Tsub+Tcp,Tsub为数据部分子载波数。Tcp大于或等于多径时延,符号间的ISI影响将被限制在保护间隔中,因此不会影响下一个OFDM的FFT变换。
(三)帧、符号、子载波、导频、保护间隔的关系
  • 该图中是一帧数据,64× 8 的矩阵,64行表示64个子载波,8列表示8个OFDM符号。这个图对应以下代码的各个参数设置。结合该该图和代码理解,几者的关系。 在这里插入图片描述
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的帧关系图、代码流程图下载

关注
打赏
1665674626
查看更多评论
立即登录/注册

微信扫码登录

0.0394s