[6] OFDM链路的误码率和OFDM符号的功率谱密度
来源:互联网 发布:数据库系统课后题答案 编辑:程序博客网 时间:2024/04/29 06:28
2016.04.26 – 05.03
个人理解笔记。(无通信基础且急躁,片面/错误概率大大的。已待纠正)
相应的word版笔记保存地址:[6] OFDM链路的误码率和OFDM符号的功率谱密度。
04.27
1 OFDM链路参数
一个OFDM信号由用PSK或QAM调制的多个子载波组成
本笔记中的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]
- [6] OFDM链路的误码率和OFDM符号的功率谱密度
- OFDM 符号的概念
- [5] OFDM符号 OFDM符号的多径Rayleigh信道链路
- OFDM中采样点和采样周期以及LTE OFDM符号包含的位数
- [4] OFDM符号的生成与解析
- OFDM基本知识的学习
- ofdm的理解
- OFDM的MATLAB仿真
- OFDM系统的仿真
- OFDM的个人笔记
- LTE:OFDM的原理
- WCDMA和OFDM的简单比较
- OFDM
- OFDM
- 【OFDM】
- OFDM
- [3] OFDM符号ofdm_signal
- OFDM符号周期计算
- 1.1进制转换:十进制转为二进制
- Android: studio 添加类似java蓝色编译文件
- 13.[LeetCode]Roman to Integer
- PS 常用工具使用汇总
- HDU 2033 人见人爱A+B
- [6] OFDM链路的误码率和OFDM符号的功率谱密度
- hdu 1260 Tickets
- ACM--DFS--nyoj 499--迷宫
- 235.[Leetcode]Lowest Common Ancestor of a Binary Search Tree
- 机器学习实践中的7种常见错误
- 关于网络编程中服务器出现故障的三种情况(TCP协议)
- 我想要的人生
- 程序员的成长阶梯和级别定义
- JDBC出现这个错误的解决办法Connections could not be acquired from the underlying database!