[6] OFDM链路的误码率和OFDM符号的功率谱密度

来源:互联网 发布:数据库系统课后题答案 编辑:程序博客网 时间:2024/04/29 06:28

2016.04.26 – 05.03
个人理解笔记。(无通信基础且急躁,片面/错误概率大大的。已待纠正)
相应的word版笔记保存地址:[6] OFDM链路的误码率和OFDM符号的功率谱密度。

04.27

1 OFDM链路参数

一个OFDM信号由用PSK或QAM调制的多个子载波组成[2]
本笔记中的OFDM由16QAM调制的64个子载波(64点IFFT/FFT变换)组成;每次会有3个OFDM信号经过多径Rayleigh衰减信道(最大延迟为15);每个OFDM符号的保护间隔类型为循环前缀(长度为16)。见Beasy_16QAM_64subcarrier_ofdm_link.m中的描述(同[5] OFDM符号 OFDM符号的多径Rayleigh信道链路中的Nframe_ofdm_multi_channel_link.m文件)。

Beasy_16QAM_64subcarrier_ofdm_link.m

% Beasy_16QAM_64subcarrier_ofdm_link.m% 生成ofdm信号:64个子载波,由16QAM调制;% 为ofdm添加循环前缀保护间隔,ofdm在多径信道中传输;% 解析经多径信道后的ofdm信号,得到最初的数据。clear% --------OFDM链路参数描述模块---------------------------------------------% @@@@@@@@ OFDM符号相关参数 @@@@@@@@Nbps    = 4;            % 对应16QAM调制M       = 2 ^ Nbps;     % 16QAM调制只能调制16进制数Nfft    = 64;           % Nfft点ifft/fft变换 - 子载波的个数Ncp     = Nfft / 4;     % 循环前缀保护间隔长度 (Ncp=0时表示OFDM无保护间隔)Nsym    = Nfft + Ncp;   % OFDM符号的长度Ndata   = Nfft;         % OFDM符号中的携带数据部分的长度Nframe  = 3;            % 每次发送Nframe个OFDM符号% @@@@@@@@ 多径Rayleigh衰减信道相关参数 @@@@@@@@PowerdB     = [0 -8 -17 -21 -25];   % 信道抽头功率分布(dB)Delay       = [0 3 5 6 8];          % 信道延迟样本Power       = 10.^(PowerdB / 10);   % 信道抽头功率分布(线性Ntap        = length(PowerdB);      % 信道抽头数Lch         = Delay(end) + 1;       % 信道长度channel     = (randn(1, Ntap) + 1i * randn(1, Ntap)).*sqrt(Power / 2);h           = zeros(1, Lch); h(Delay+1)  = channel;              % 信道脉冲响应% --------OFDM符号生成模块-------------------------------------------------% @@@@@@@@ 生成Ndata * Nframe个M进制数据 @@@@@@@@DataSource   =  randi([0, M - 1], 1, Ndata * Nframe);% @@@@@@@@ 将数据映射为QAM符号(时-->频) @@@@@@@@MapObj  = modem.qammod(M);ModSym  = modulate(MapObj, DataSource);% @@@@@@@@ QAM符号串转并 @@@@@@@@ModSymSrl2PrlIndx = 1 : Ndata;ModPrlSym = zeros(Nframe, Ndata);for i = 1 : Nframe    ModPrlSym(i, :)     = ModSym(ModSymSrl2PrlIndx);    ModSymSrl2PrlIndx   = ModSymSrl2PrlIndx + Ndata;end% @@@@@@@@ 利用ifft变换生成OFDM符号 @@@@@@@@OfdmSym = zeros(Nframe, Ndata);for i = 1 : Nframe    OfdmSym(i, :)   = ifft(ModPrlSym(i, :));end% @@@@@@@@ 为每个OFDM符号添加循环前缀保护间隔 @@@@@@@@GIOfdmSymIndx   = 1 : Nsym;OfdmSym_GI      = zeros(Nframe, Nsym);for i = 1 : Nframe    OfdmSym_GI(i, :)   = add_cp(Ncp, Ndata, OfdmSym(i,:));end% @@@@@@@@ 带循环前缀的OFDM符号并转串 @@@@@@@@GIOfdmSrlSymIndx    = 1 : Nsym;OfdmSrlSym_GI       = zeros(1, Nframe * Nsym);for i = 1 : Nframe    OfdmSrlSym_GI(GIOfdmSrlSymIndx) =  OfdmSym_GI(i, :);    GIOfdmSrlSymIndx                = GIOfdmSrlSymIndx + Nsym;end% --------OFDM符号经过多径信道模块-----------------------------------------y           = conv(OfdmSrlSym_GI,h);% --------OFDM符号解析模块---------------------------------------------rvOfdmSrlSym_GI = y;OfdmSymIndx     = 1 : Ndata;H               = fft([h zeros(1, Nfft - Lch)]); % 信道频域响应ChFrqRep        = H(OfdmSymIndx);%  @@@@@@@@ 带循环前缀的OFDM符号串转并 @@@@@@@@rvOfdmSym_GI = zeros(Nframe, Nsym);GIOfdmSrlSymIndx = 1 : Nsym;for i = 1 : Nframe    rvOfdmSym_GI(i, :)  = rvOfdmSrlSym_GI(GIOfdmSrlSymIndx);    GIOfdmSrlSymIndx    = GIOfdmSrlSymIndx + Nsym;end%  @@@@@@@@ 去掉OFDM符号的循环前缀 @@@@@@@@rvOfdmSym = zeros(Nframe, Ndata);for i = 1 : Nframe    rvOfdmSym(i, :)  = remove_cp(Ncp, Nsym, rvOfdmSym_GI(i, :));end%  @@@@@@@@ 用fft变换将OFDM符号变为QAM符号(时-->频),并进行信道补偿 @@@@@@@@rvModPrlSym = zeros(Nframe, Ndata);for i = 1 : Nframe      temp = fft(rvOfdmSym(i, :));      rvModPrlSym(i, :) = temp./ChFrqRep;end%  @@@@@@@@ QAM符号并转串 @@@@@@@@rvModSym = zeros(1, Nframe * Ndata);ModSymPrl2SrlIndx = 1 : Ndata;for i = 1 : Nframe    rvModSym(ModSymPrl2SrlIndx)     = rvModPrlSym(i, :);    ModSymPrl2SrlIndx               = ModSymPrl2SrlIndx + Ndata;endrvData  = qamdemod(rvModSym, M);

add_cp.m

function y = add_cp(Ngi, Ndata, OfdmSym)% 为OFDM添加保护间隔 - 循环前缀if Ngi ~= 0    y   = [OfdmSym(Ndata - Ngi + 1 : Ndata) OfdmSym(1 : Ndata)];else    y   = OfdmSym;endend

remove_cp.m

function y  = remove_cp(Ngi, Nsym, OfdmSym)% 去掉OFDM的保护间隔 - 循环前缀if Ngi ~= 0    y   = OfdmSym(Ngi + 1 : Nsym); % 丢掉OFDM符号的循环前缀else    y   = OfdmSym;endend

04.28

2 OFDM链路的误码率

误码率。
这里指的是BER(Bit Error Rate,二进制误码率)。对于OFDM链路来说,是指发送N次Nframe个OFDM符号,有多少个bit错误。

2.1 Beasy_16QAM_64subcarrier_ofdm_link下的误码率

Beasy_16QAM_64subcarrier_ofdm_link.m

% Beasy_16QAM_64subcarrier_ofdm_link.m% 生成ofdm信号:64个子载波,由16QAM调制;% 为ofdm添加循环前缀保护间隔,ofdm在多径信道中传输;% 解析经多径信道后的ofdm信号,得到最初的数据并计算误码率。clear% --------OFDM链路参数描述模块---------------------------------------------% @@@@@@@@ OFDM符号相关参数 @@@@@@@@…Nframe  = 3;            % 每次发送Nframe个OFDM符号Neb     = 0;            % 在OFDM链路中传输数据时,发生位(bit)错误的数量(Neb,Number of error bits)Ntb     = 0;            % 在OFDM链路中传输的总位(bit)数(Ntb,Number of total bits)Niter   = 1e5;          % OFDM发送Niter次信息统计一次误码率BER% @@@@@@@@ 多径Rayleigh衰减信道相关参数 @@@@@@@@for berIndx = 1 : Niter         % 每Niter统计一次OFDM链路的误码率    % --------OFDM符号生成模块-------------------------------------------------% --------OFDM符号经过多径信道模块-----------------------------------------    channel     = (randn(1, Ntap) + 1i * randn(1, Ntap)).*sqrt(Power / 2);    h           = zeros(1, Lch);     h(Delay+1)  = channel;              % 信道脉冲响应    y           = conv(OfdmSrlSym_GI,h);    % --------OFDM符号解析模块---------------------------------------------   …    rvData  = qamdemod(rvModSym, M);    % -------- 误码 --------------------------------------------------    Neb     = Neb + sum(sum(de2bi(rvData,Nbps) ~= de2bi(DataSource, Nbps)));    Ntb     = Ntb + Ndata * Nframe * Nbps;end% 误码率BER     = Neb / Ntb;

运行Beasy_16QAM_64subcarrier_ofdm_link.m几次,BER都为0。

04.29

2.2 添加AWGN后的误码率

在信道模型非常准确的情况下,以上的OFDM链路几乎可以做到0误码。但在实际的OFDM链路下,还存在一些其它干扰。现往OFDM链路中加入AWGN模型,再来看误码率。
Beasy_16QAM_64subcarrier_ofdm_link.m

% Beasy_16QAM_64subcarrier_ofdm_link.m% 生成ofdm信号:64个子载波,由16QAM调制;% 为ofdm添加循环前缀保护间隔,ofdm在多径信道中传输;% 解析经多径信道和AWGN后的ofdm信号,得到最初的数据并计算误码率。clear% --------OFDM链路参数描述模块---------------------------------------------% @@@@@@@@ OFDM符号相关参数 @@@@@@@@…Niter       = 1e5;      % OFDM发送Niter次信息统计一次误码率BERTarget_neb  = 500;      % Neb的最大值   % AWGN相关参数EbN0    = 0 : 5 : 20;sigPow  = 0;            % 信号功率% @@@@@@@@ 多径Rayleigh衰减信道相关参数 @@@@@@@@% 本程序误码率相关文件ber_file_name   = 'OFDM_BER_Rayleigh_CP_16.dat';fd             = fopen(ber_file_name, 'w+');% if awgnIndx == 0, 计算信号功率sigPow% else 计算误码数Nebfor awgnIndx = 0 : length(EbN0)     % 跟AWGN相关的循环    % 误码数和码数清0    Neb = 0;     Ntb = 0;    for berIndx = 1 : Niter         % 每Niter统计一次OFDM链路的误码率        % --------OFDM符号生成模块-------------------------------------------------        % @@@@@@@@ 生成Ndata * Nframe个M进制数据 @@@@@@@@        ….        % --------OFDM符号经过多径信道模块---------------------------------        channel     = (randn(1, Ntap) + 1i * randn(1, Ntap)).*sqrt(Power / 2);        h           = zeros(1, Lch);         h(Delay+1)  = channel;              % 信道脉冲响应        y           = conv(OfdmSrlSym_GI,h);        % 为添加AWGN噪声测量信号能量        if awgnIndx == 0            y1      = y(1 : Nframe * Nsym);             sigPow  = sigPow + y1 * y1';            continue;        end        % 添加 AWGN 噪声---------------------------------------------------        snr         = EbN0(awgnIndx) + 10 * log10(Nbps * (Ndata / Nfft)); % 4.28式        noise_mag   = sqrt((10.^(-snr / 10)) * sigPow / 2);        y_AWGN      = y + noise_mag * (randn(size(y)) + 1i * randn(size(y)));        % --------OFDM符号解析模块-----------------------------------------        …        rvData  = qamdemod(rvModSym, M);        % -------- 误码计算 --------------------------------------------------        Neb     = Neb + sum(sum(de2bi(rvData,Nbps) ~= de2bi(DataSource, Nbps)));        Ntb     = Ntb + Ndata * Nframe * Nbps;        if Neb > Target_neb, break;end  % 误码率迭代到这里已经足够大了    end    % 误码率    BER     = Neb / Ntb;    if awgnIndx == 0        sigPow  = sigPow / (Nsym * Nframe * Niter); % 每个OFDM信号的能量 - 平均值    else        fprintf(fd, '%d\t%11.3e\n', EbN0(awgnIndx), BER);        if BER < 1e-6, break; end   % 已经满意当前这个误码率    endendif fd ~= 0, fclose(fd);enddisp('Simulation is finished');

运行Beasy_16QAM_64subcarrier_ofdm_link.m,得到OFDM_BER_Rayleigh_CP_16.dat文件,其内容如下:
这里写图片描述
Figure 1. 每发送Niter * Nframe个OFDM符号的误码率

将误码率以曲线的形式绘制出来。
Beasy_16QAM_64subcarrier_ofdm_link.m

if fd ~= 0, fclose(fd);endplot_ber(ber_file_name);disp('Simulation is finished');

plot_ber.m

function plot_ber( file_name )% 绘制OFDM链路的误码率曲线% file_name中保存的是EbN0和误码率值对EbN0_BER    = load(file_name);semilogy(EbN0_BER(:,1),EbN0_BER(:,2),'b-o');grid onlegend('OFDM模拟链路的误码率曲线');xlabel('EbN0[dB]'), ylabel('BER');axis([EbN0_BER(1,1) EbN0_BER(end,1) 1e-5 1]);end

运行Beasy_16QAM_64subcarrier_ofdm_link.m,得到下图
这里写图片描述
Figure 2. OFDM链路误码率与EbN0关系曲线图

该部分的matlab代码保存地址为:16QAM_64subcarrier_ofdm_link_BER。

05.03

3 OFDM符号的功率谱密度

完全根据书本附带的代码搬迁/验证过来的,甚至不懂什么是功率谱密度,更别说计算OFDM符号的功率谱密度了。

误码率是在OFDM链路的接收部分计算,而功率谱密度是在OFDM链路的发射部分计算。

在Beasy_16QAM_64subcarrier_ofdm_link.m中计算一次一个OFDM符号的功率谱密度。

Beasy_16QAM_64subcarrier_ofdm_link.m

% Beasy_16QAM_64subcarrier_ofdm_link.m% 在OFDM链路的接收端计算误码率(BER);在OFDM链路的发送端计算一个OFDM符号的功率谱密度(PSD)。clear% --------OFDM链路参数描述模块---------------------------------------------% OFDM功率谱密度相关参数NXpsd       = 2048; Frc         = (1 : NXpsd) - NXpsd / 2;  % OFDM符号功率谱密度横坐标个数NIFFTOvspl  = NXpsd / 2;                % ifft变换的QAM符号长度    NpsdCp      = 2 * Nfft;                 % 求功率谱密度时循环前缀的长度Nprxz       = round((NXpsd - NIFFTOvspl - NpsdCp) / 3);    % 在ofdm符号前面补0的个数Nsuxz       = (NXpsd - NIFFTOvspl - NpsdCp) - Nprxz;        % 在ofdm符号后面补0的个数% if awgnIndx == 0, 计算信号功率sigPow% else 计算误码数Nebfor awgnIndx = 0 : length(EbN0)     % 跟AWGN相关的循环    % 误码数和码数清0    Neb = 0;     Ntb = 0;    for berIndx = 1 : Niter         % 每Niter统计一次OFDM链路的误码率        % --------OFDM符号生成模块-------------------------------------------------% ++++++++ 计算一次一个OFDM符号的PSD - 过采样++++++++        if awgnIndx == 0            IFFT_Oversample     = [ModPrlSym(i, 1 : end / 2) zeros(1, NIFFTOvspl - Ndata) ModPrlSym(i, end / 2 + 1 : end)];            PsdOfdmSym          = ifft(IFFT_Oversample);            PsdOfdmSymCP        = add_cp(NpsdCp, PsdOfdmSym);            PsdOfdmSymCPAddZros = [zeros(1, Nprxz) PsdOfdmSymCP zeros(1, Nsuxz)];   % 过采样            OfdmSymComput       = 20 * log10(abs(fft(PsdOfdmSymCPAddZros)));            OfdmSymPSDy         = fftshift(OfdmSymComput) - max(OfdmSymComput);        end        % @@@@@@@@ 利用ifft变换生成OFDM符号 @@@@@@@@end    % 误码率endif fd ~= 0, fclose(fd);end% 绘制OFDM链路接收端的误码率曲线figure(1); clfplot_ber(ber_file_name);% 绘制OFDM链路发射端的PSD曲线figure(2); clfplot(Frc,OfdmSymPSDy,'b');grid onxlabel('frequency[Hz]'); ylabel('PSD[dB]'); axis([Frc([1 end]) -100 0]);disp('Simulation is finished');

add_cp.m

function y = add_cp(Ngi, OfdmSym)% 为OFDM添加保护间隔 - 循环前缀if Ngi ~= 0    y   = [OfdmSym(end - Ngi + 1 : end) OfdmSym];else    y   = OfdmSym;endend

remove_cp.m

function y  = remove_cp(Ngi, OfdmSym)% 去掉OFDM的保护间隔 - 循环前缀if Ngi ~= 0    y   = OfdmSym(Ngi + 1 : end); % 丢掉OFDM符号的循环前缀else    y   = OfdmSym;endend

运行Beasy_16QAM_64subcarrier_ofdm_link,得到在发射端的一个OFDM符号的功率谱密度:
这里写图片描述
Figure 3. OFDM链路发射端一个OFDM符号的功率谱密度(PSD)图

上图的横坐标值并不代表OFDM符号的频率值,它只是为了绘制纵坐标而出现的 ¬—— 它的个数跟纵坐标值的个数相同。

含OFDM链路接收端误码率(BER)和发送端一个OFDM符号功率谱密度(PSD)的matlab源码笔记地址为:16QAM_64subcarrier_ofdm_link_BER&PSD。

[2016.05.02 - 20:47]

0 0