[6] OFDM链路的误码率和OFDM符号的功率谱密度
2016-05-02 20:46
477 查看
2016.04.26 – 05.03
个人理解笔记。(无通信基础且急躁,片面/错误概率大大的。已待纠正)
相应的word版笔记保存地址:[6] OFDM链路的误码率和OFDM符号的功率谱密度。
04.27
本笔记中的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
add_cp.m
remove_cp.m
04.28
这里指的是BER(Bit Error Rate,二进制误码率)。对于OFDM链路来说,是指发送N次Nframe个OFDM符号,有多少个bit错误。
运行Beasy_16QAM_64subcarrier_ofdm_link.m几次,BER都为0。
04.29
Beasy_16QAM_64subcarrier_ofdm_link.m
运行Beasy_16QAM_64subcarrier_ofdm_link.m,得到OFDM_BER_Rayleigh_CP_16.dat文件,其内容如下:
Figure 1. 每发送Niter * Nframe个OFDM符号的误码率
将误码率以曲线的形式绘制出来。
Beasy_16QAM_64subcarrier_ofdm_link.m
plot_ber.m
运行Beasy_16QAM_64subcarrier_ofdm_link.m,得到下图
Figure 2. OFDM链路误码率与EbN0关系曲线图
该部分的matlab代码保存地址为:16QAM_64subcarrier_ofdm_link_BER。
05.03
误码率是在OFDM链路的接收部分计算,而功率谱密度是在OFDM链路的发射部分计算。
在Beasy_16QAM_64subcarrier_ofdm_link.m中计算一次一个OFDM符号的功率谱密度。
Beasy_16QAM_64subcarrier_ofdm_link.m
add_cp.m
remove_cp.m
运行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]
个人理解笔记。(无通信基础且急躁,片面/错误概率大大的。已待纠正)
相应的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; end rvData = 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; end end
remove_cp.m
function y = remove_cp(Ngi, Nsym, OfdmSym) % 去掉OFDM的保护间隔 - 循环前缀 if Ngi ~= 0 y = OfdmSym(Ngi + 1 : Nsym); % 丢掉OFDM符号的循环前缀 else y = OfdmSym; end end
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次信息统计一次误码率BER Target_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 计算误码数Neb for 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 % 已经满意当前这个误码率 end end if fd ~= 0, fclose(fd);end disp('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);end plot_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 on legend('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 计算误码数Neb for 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 % 误码率 … end if fd ~= 0, fclose(fd);end % 绘制OFDM链路接收端的误码率曲线 figure(1); clf plot_ber(ber_file_name); % 绘制OFDM链路发射端的PSD曲线 figure(2); clf plot(Frc,OfdmSymPSDy,'b');grid on xlabel('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; end end
remove_cp.m
function y = remove_cp(Ngi, OfdmSym) % 去掉OFDM的保护间隔 - 循环前缀 if Ngi ~= 0 y = OfdmSym(Ngi + 1 : end); % 丢掉OFDM符号的循环前缀 else y = OfdmSym; end end
运行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]
相关文章推荐
- poj3581 Sequence (后缀数组)
- 跨语言情感分析(中/英)
- 235.[Leetcode]Lowest Common Ancestor of a Binary Search Tree
- 判定表
- atoi()函数的应用
- Python challenge
- OpenCV Error: Assertion failed (size.width>0 && size.height>0) in cv::imshow
- hdu 1719 / 哈理工 oj 2118 Friend number【递推+思维】
- 二叉树的构造(二)
- 206.[LeetCode]Reverse Linked List
- 13.[LeetCode]Roman to Integer
- 智能预判 (一:线程的开启)
- iOS UIKit:viewController之Present (3)
- CSU 1510 Happy Robot DP
- quick-lua文件加密步骤
- centos7下添加常用YUM源(EPEL/Remi/RPMforge/php/Nginx)
- python 的文件读写方法:read readline readlines wirte writelines
- 1084. Broken Keyboard (20)
- HDU 2032 杨辉三角(DP)
- 169.[LeetCode]Majority Element