[8] OFDM的发送和接收 —— 按照框图模块化
Posted 资质平庸的程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[8] OFDM的发送和接收 —— 按照框图模块化相关的知识,希望对你有一定的参考价值。
2016.05.12 - 05.24
个人理解笔记。(无通信基础且急躁,片面/错误概率大大的。已待纠正)
05.12
到了这一步,可以在某书本上找一个OFDM的链路框图,在matlab下将每个模块实现下,完整是指基本实现OFDM链路框图的每一个模块,粗糙是指每个模块中有些细节可能还未涉及。至于像“ [7] OFDM过采样和参数选择”提到的OFDM链路参数,再留留(实际的OFDM链路参数与仿真代码还对应不过来)。
1 OFDM框图
摘《MIMO-OFDM Wireless Communications with Matlab》的《OFDM Basics》一章中的OFDM框图(如下)。
Figure 1. OFDM系统的发送和接收框图
在后续对OFDM模拟中,暂不包括“FEC coding”、“Bit interleaver/deinterleaver”、“ADC/DAC”、“RF Tx/Rx”、“Timing/frequency synchronization and channel estimation”以及“Channel equalizer”模块。其余模块将会被包含在OFDM系统中,以模块化(m文件)方式编写。
2 OFDM模块化
05.12
2.1 生成随机数据流(Bit stream)
OFDM_Bbasics.m
% OFDM_Basics.m
% @功能:仿真OFDM系统(链路)的发射端,无线信道模块以及接收端;
% 以一般书中的OFDM框图为最小模块组织该OFDM系统。
% @结果:绘制在OFDM链路接收端的误码率(BER);
% 绘制OFDM链路发射端OFDM符号的功率谱密度(PSD)。
clear
% ######## OFDM相关参数值 ########
Nbit = 6; % 表示数的位数
Ncr = 48; % 子载波个数
%Nfft = 64; % 进行ifft/fft变换时的点数
Nframe = 7; % 经过无线信道时的OFDM符号个数
% st_st_st_st_st_st_st_st OFDM发射端 st_st_st_st_st_st_st_st
N = Ncr * Nframe;
sdBitStream = generate_bit_stream(Nbit, N); % 生成发射端数据
% ed_ed_ed_ed_ed_ed_ed_ed OFDM发射端 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st 无线信道 st_st_st_st_st_st_st_st
% ed_ed_ed_ed_ed_ed_ed_ed 无线信道 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st OFDM接收端 st_st_st_st_st_st_st_st
rvBitStream = sdBitStream; % 获取发送端发送的数据
% ed_ed_ed_ed_ed_ed_ed_ed OFDM接收端 ed_ed_ed_ed_ed_ed_ed_ed
% @@@@@@@@ 绘制误码率(BER) @@@@@@@@
% @@@@@@@@ 绘制OFDM功率谱密度(PSD) @@@@@@@@
generate_bit_stream.m
function BitStream = generate_bit_stream( Nbit, N )
% @功能:生成N个Nbit位的随机正整数
% @返回:sdBitStream为生成的随机正整数序列
M = (2 ^Nbit) - 1; % Nbit位所能表示的最大整数
BitStream = randi([0, M], 1, N); % 生成1 x N的0到M的随机整数
end
05.13
2.2 生成/解调调制符号(QAM/PSK modulated symbol)
OFDM_Basics.m
% @功能:仿真OFDM系统(链路)的发射端,无线信道模块以及接收端;
% 以一般书中的OFDM框图为最小模块组织该OFDM系统。
% @结果:绘制在OFDM链路接收端的误码率(BER);
% 绘制OFDM链路发射端OFDM符号的功率谱密度(PSD)。
clear
% ######## OFDM相关参数值 ########
Nbit = 6; % 表示数的位数
Ncr = 48; % 子载波个数
%Nfft = 64; % 进行ifft/fft变换时的点数
Nframe = 7; % 经过无线信道时的OFDM符号个数
% st_st_st_st_st_st_st_st OFDM发射端 st_st_st_st_st_st_st_st
N = Ncr * Nframe;
sdBitStream = generate_bit_stream(Nbit, N); % 生成发射端数据
rLen = Ncr;
ModType = 'psk';
ParModSym = generate_modulated_symbol( ModType, Nbit, sdBitStream, Nframe, rLen ); % 生成QAM/PSK符号
% ed_ed_ed_ed_ed_ed_ed_ed OFDM发射端 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st 无线信道 st_st_st_st_st_st_st_st
% ed_ed_ed_ed_ed_ed_ed_ed 无线信道 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st OFDM接收端 st_st_st_st_st_st_st_st
rvBitStream = demodulate_symbol( ModType, Nbit, ParModSym, Nframe); % 解调QAM/PSK符号
% ed_ed_ed_ed_ed_ed_ed_ed OFDM接收端 ed_ed_ed_ed_ed_ed_ed_ed
% @@@@@@@@ 绘制误码率(BER) @@@@@@@@
% @@@@@@@@ 绘制OFDM功率谱密度(PSD) @@@@@@@@
generate_modulated_symbol.m
function ParModSym = generate_modulated_symbol( ModType, Nbit, BitStream, Nframe, rLen )
% @功能:根据ModType选择调制BitStream的方式
% @返回:ParModSym为调制(的并行)PSK/QAM符号
% @参数:Modtype —— 调制类型,其值可为'psk'或'qam'
% Nbit —— 数据流BitStream中元素的位数
% BitStream —— 数据流
% 将调制符号分为Nframe x rLen
mType = lower(ModType);
M = 2 ^Nbit;
ParModSym = zeros(Nframe, rLen);
if strcmp(mType, 'psk')
ModObj = modem.pskmod(M);
elseif strcmp(mType, 'qam')
ModObj = modem.qammod(M);
else
fprintf('generate_modulated_symbol m-fun: error %s parameter\\n', ModType);
return ;
end % 调制对象
ModSym = modulate(ModObj, BitStream); % 生成调制符号
ser2parIndex = 1 : rLen;
for i = 1 : Nframe
ParModSym(i, :) = ModSym(ser2parIndex);
ser2parIndex = ser2parIndex + rLen;
end % 调制符号串转并
end
demodulate_symbol.m
function DemodSym = demodulate_symbol( ModType, Nbit,ParModSym, Nframe)
% @功能:将PSK/QAM符号解调
% @返回:DemodSym为解调数据
% @参数:Nbit —— 调制符号对应的数的位数
% ModType —— 调制类型,其值可谓'psk'或'qam'
% ParModSym —— PSK/QAM调制符号(Nframe行)
rLen = length(ParModSym(1,:));
SerModSym = zeros(1, Nframe * rLen);
par2serIndex = 1 : rLen;
for i = 1 : Nframe
SerModSym(par2serIndex) = ParModSym(i, :);
par2serIndex = par2serIndex + rLen;
end
M = 2 ^Nbit;
mType = lower(ModType);
if strcmp(mType, 'psk')
DemodSym = pskdemod(SerModSym, M);
elseif strcmp(mType, 'qam')
DemodSym = qamdemod(SerModSym, M);
else
fprintf('generate_modulated_symbol m-fun: error %s parameter\\n', ModType);
DemodSym = zeros(1, Nframe * rLen);
return ;
end % 调制对象
end
05.16
2.3 生成OFDM符号
OFDM_Basics.m
% OFDM_Basics.m
% @功能:仿真OFDM系统(链路)的发射端,无线信道模块以及接收端;
% 以一般书中的OFDM框图为最小模块组织该OFDM系统。
% @结果:绘制在OFDM链路接收端的误码率(BER);
% 绘制OFDM链路发射端OFDM符号的功率谱密度(PSD)。
clear
% ######## OFDM相关参数值 ########
Nbit = 6; % 表示数的位数
Ncr = 48; % 子载波个数
Nframe = 7; % 经过无线信道时的OFDM符号个数
% st_st_st_st_st_st_st_st OFDM发射端 st_st_st_st_st_st_st_st
N = Ncr * Nframe;
sdBitStream = generate_bit_stream(Nbit, N); % 生成发射端数据
rLen = Ncr;
ModType = 'psk';
ParModSym = generate_modulated_symbol( ModType, Nbit, sdBitStream, Nframe, rLen ); % 生成QAM/PSK符号
Nifftop = 1024;
SerOverOfdmSym = generate_ofdm_symbol( ParModSym, Nifftop);
% ed_ed_ed_ed_ed_ed_ed_ed OFDM发射端 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st 无线信道 st_st_st_st_st_st_st_st
% ed_ed_ed_ed_ed_ed_ed_ed 无线信道 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st OFDM接收端 st_st_st_st_st_st_st_st
NofdmSym = Ncr;
Rlen = Nframe;
rvParModSym = get_modulate_symbol( SerOverOfdmSym, Nifftop, NofdmSym, Rlen );
rvBitStream = demodulate_symbol( ModType, Nbit, rvParModSym, Nframe ); % 解调QAM/PSK符号
% ed_ed_ed_ed_ed_ed_ed_ed OFDM接收端 ed_ed_ed_ed_ed_ed_ed_ed
% @@@@@@@@ 绘制误码率(BER) @@@@@@@@
% @@@@@@@@ 绘制OFDM功率谱密度(PSD) @@@@@@@@
generate_ofdm_symbol.m
function SerOverOfdmSym = generate_ofdm_symbol( ParModSym, Nifftop )
% @功能:利用ifft变换生成OFDM符号
% @返回:返回串行的OFDM符号到SerOfdmSym
% @参数:ParModSym —— 并行的调制符号
% Nifftosp —— ifft过采样变换的长度
[rLen, cLen] = size(ParModSym);
ParOverOfdmSym = zeros(rLen, Nifftop);
for i = 1 : rLen
IFFT_oversample = [ParModSym(i, 1 : cLen / 2), zeros(1, Nifftop - cLen),...
ParModSym(i, cLen / 2 + 1 : end)];
ParOverOfdmSym(i, :) = ifft(IFFT_oversample);
end % 生成ofdm符号
SerOverOfdmSym = zeros(1, rLen * cLen);
par2serIndex = 1 : Nifftop;
for i = 1 : rLen
SerOverOfdmSym(par2serIndex) = ParOverOfdmSym(i, :);
par2serIndex = par2serIndex + Nifftop;
end
end
get_modulate_symbol.m
function ParModSym = get_modulate_symbol( SerOfdmSym, Nifftop, NofdmSym, Rlen )
% @功能:根据串行的OFDM符号恢复PSK/QAM符号
% @返回:ParModSym值为并行的PSK/QAM符号
% @参数:SerOfdmSym —— 带过采样的串行OFDM符号
% Nifftop —— 进行ifft变换时的长度
% NofdmSym —— 一个OFDM符号的长度
% Rlen —— SerOfmSym中所包含的OFDM符号的个数
OverModSym = zeros(Rlen, Nifftop);
ser2parIndx = 1 : Nifftop;
for i = 1 : Rlen
OverModSym(i, :) = fft(SerOfdmSym(ser2parIndx));
ser2parIndx = ser2parIndx + Nifftop;
end % 含过采样的并行调制符号
ParModSym = zeros(Rlen, NofdmSym);
for i = 1 : Rlen
ParModSym(i, 1 : NofdmSym / 2) = OverModSym(i, 1 : NofdmSym / 2);
ParModSym(i, NofdmSym / 2 + 1 : end) = OverModSym(i, Nifftop - NofdmSym + NofdmSym / 2 + 1 : end);
end % 还原调制符号
end
05.17
2.4 保护间隔
OFDM_Basics.m
% OFDM_Basics.m
% @功能:仿真OFDM系统(链路)的发射端,无线信道模块以及接收端;
% 以一般书中的OFDM框图为最小模块组织该OFDM系统。
% @结果:绘制在OFDM链路接收端的误码率(BER);
% 绘制OFDM链路发射端OFDM符号的功率谱密度(PSD)。
clear
% ######## OFDM相关参数值 ########
Nbit = 6; % 表示数的位数
Ncr = 48; % 子载波个数
Nframe = 7; % 经过无线信道时的OFDM符号个数
% st_st_st_st_st_st_st_st OFDM发射端 st_st_st_st_st_st_st_st
N = Ncr * Nframe;
sdBitStream = generate_bit_stream( Nbit, N ); % 生成发射端数据
rLen = Ncr;
ModType = 'psk';
ParModSym = generate_modulated_symbol( ModType, Nbit, sdBitStream, Nframe, rLen ); % 生成QAM/PSK符号
Nifftop = 1024;
GiType = 'CP';
Ngi = Ncr / 4;
SerOverGIOfdmSym = generate_ofdm_symbol( ParModSym, Nifftop, GiType, Ngi );
% ed_ed_ed_ed_ed_ed_ed_ed OFDM发射端 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st 无线信道 st_st_st_st_st_st_st_st
% ed_ed_ed_ed_ed_ed_ed_ed 无线信道 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st OFDM接收端 st_st_st_st_st_st_st_st
NofdmSym = Ncr;
Rlen = Nframe;
GiType = 'CP';
Ngi = Ncr / 4;
rvParModSym = get_modulate_symbol( SerOverGIOfdmSym, Nifftop, NofdmSym, Rlen, GiType, Ngi );
rvBitStream = demodulate_symbol( ModType, Nbit, rvParModSym, Nframe ); % 解调QAM/PSK符号
% ed_ed_ed_ed_ed_ed_ed_ed OFDM接收端 ed_ed_ed_ed_ed_ed_ed_ed
% @@@@@@@@ 绘制误码率(BER) @@@@@@@@
% @@@@@@@@ 绘制OFDM功率谱密度(PSD) @@@@@@@@
generate_ofdm_symbol.m
function SerOverGIOfdmSym = generate_ofdm_symbol( ParModSym, Nifftop, GiType, Ngi )
% @功能:利用ifft变换生成OFDM符号
% @返回:返回串行的OFDM符号到SerOfdmSym
% @参数:ParModSym —— 并行的调制符号
% Nifftosp —— ifft过采样变换的长度
% GiType —— 添加保护间隔的类型
% Ngi —— OFDM保护间隔长度
[rLen, cLen] = size(ParModSym);
ParOverOfdmSym = zeros(rLen, Nifftop);
for i = 1 : rLen
IFFT_oversample = [ParModSym(i, 1 : cLen / 2), zeros(1, Nifftop - cLen),...
ParModSym(i, cLen / 2 + 1 : end)];
ParOverOfdmSym(i, :) = ifft(IFFT_oversample);
end % 生成ofdm符号
ParOverGIOfdmSym = add_gi( ParOverOfdmSym, GiType, Ngi ); % 为每个OFDM添加保护间隔
[rLen, cLen] = size(ParOverGIOfdmSym);
SerOverGIOfdmSym = zeros(1, rLen * cLen);
par2serIndex = 1 : Nifftop + Ngi;
for i = 1 : rLen
SerOverGIOfdmSym(par2serIndex) = ParOverGIOfdmSym(i, :);
par2serIndex = par2serIndex + Nifftop + Ngi;
end % 带过采样和保护间隔的OFDM符号并转串
end
get_modulate_symbol.m
function ParModSym = get_modulate_symbol( SerOverGIOfdmSym, Nifftop, NofdmSym, Rlen, GiType, Ngi )
% @功能:根据串行的OFDM符号恢复PSK/QAM符号
% @返回:ParModSym值为并行的PSK/QAM符号
% @参数:SerOfdmSym —— 带过采样的串行OFDM符号
% Nifftop —— 进行ifft变换时的长度
% NofdmSym —— 一个OFDM符号的长度
% Rlen —— SerOfmSym中所包含的OFDM符号的个数
% GiType —— OFDM符号的保护间隔类型('CP', 'ZP')
% Ngi —— OFDM保护间隔长度
OverOfdmSym = zeros(Rlen, Nifftop);
ser2parIndx = 1 : Nifftop + Ngi;
for i = 1 : Rlen
OverOfdmSym(i, :) = remove_gi( SerOverGIOfdmSym(ser2parIndx), GiType, Ngi );
ser2parIndx = ser2parIndx + Nifftop + Ngi;
end % 去掉OFDM符号的保护间隔并得到并行的带过采样的OFDM符号
OverModSym = zeros(Rlen, Nifftop);
for i = 1 : Rlen
OverModSym(i, :) = fft(OverOfdmSym(i, :));
end % 含过采样的并行调制符号
ParModSym = zeros(Rlen, NofdmSym);
for i = 1 : Rlen
ParModSym(i, 1 : NofdmSym / 2) = OverModSym(i, 1 : NofdmSym / 2);
ParModSym(i, NofdmSym / 2 + 1 : end) = OverModSym(i, Nifftop - NofdmSym + NofdmSym / 2 + 1 : end);
end % 还原调制符号
end
add_gi.m
function ParOverGIOfdmSym = add_gi( ParOverOfdmSym, GiType, Ngi )
% @功能:为每个OFDM符号添加保护间隔
% @返回:ParOverGIOfdmSym为带保护间隔的并行的OFDM符号
% @参数:ParOverOfdmSym —— (含过采样)的多个OFDM符号,
% GiType —— 保护间隔类型('CP', 'ZP')
% Ngi —— 保护间隔的长度
if Ngi <= 0
ParOverGIOfdmSym = ParOverOfdmSym;
return ;
end % 不添加保护间隔
LgiType = lower(GiType);
[rLen, cLen] = size(ParOverOfdmSym);
ParOverGIOfdmSym = zeros(rLen, cLen + Ngi);
if strcmp('cp', LgiType) % 循环前缀 —— CP
for i = 1 : rLen
ParOverGIOfdmSym(i, :) = add_cp(Ngi, ParOverOfdmSym(i, :));
end
elseif strcmp('zp',LgiType)
ParOverGIOfdmSym = ParOverOfdmSym; % ZP情况以后再补充
else
ParOverGIOfdmSym = ParOverOfdmSym;
end
end
remove_gi.m
function OverOfdmSym = remove_gi( OverGIOfdmSym, GiType, Ngi )
% @功能:去掉OFDM符号中的保护间隔
% @返回:返回去掉保护间隔后的OFDM符号
% @参数:OverGIOfdmSym —— 带保护间隔的OFDM符号
% GiType —— 保护间隔类型
% Ngi —— 保护间隔长度
if Ngi <= 0
OverOfdmSym = OverGIOfdmSym;
end
LgiType = lower(GiType);
if strcmp('cp', LgiType)
OverOfdmSym = remove_cp(Ngi, OverGIOfdmSym);
elseif strcmp('zp', LgiType)
OverOfdmSym = OverGIOfdmSym; % 留以后补充
end
end
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
05.17
2.5 无线信道
OFDM_Basics.m
% OFDM_Basics.m
% @功能:仿真OFDM系统(链路)的发射端,无线信道模块以及接收端;
% 以一般书中的OFDM框图为最小模块组织该OFDM系统。
% @结果:绘制在OFDM链路接收端的误码率(BER);
% 绘制OFDM链路发射端OFDM符号的功率谱密度(PSD)。
clear
% ######## OFDM相关参数值 ########
Nbit = 6; % 表示数的位数
Ncr = 48; % 子载波个数
Nframe = 7; % 经过无线信道时的OFDM符号个数
% st_st_st_st_st_st_st_st OFDM发射端 st_st_st_st_st_st_st_st
N = Ncr * Nframe;
sdBitStream = generate_bit_stream( Nbit, N ); % 生成发射端数据
rLen = Ncr;
ModType = 'psk';
ParModSym = generate_modulated_symbol( ModType, Nbit, sdBitStream, Nframe, rLen ); % 生成QAM/PSK符号
Nifftop = 1024;
GiType = 'CP';
Ngi = Ncr / 4;
SerOverGIOfdmSym = generate_ofdm_symbol( ParModSym, Nifftop, GiType, Ngi );
% ed_ed_ed_ed_ed_ed_ed_ed OFDM发射端 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st 无线信道 st_st_st_st_st_st_st_st
% @@@@@@@@ 多径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; % 信道长度
% @@@@@@@@ OFDM符号经过多径信道模块 @@@@@@@@
channel = (randn(1, Ntap) + 1i * randn(1, Ntap)).*sqrt(Power / 2);
h = zeros(1, Lch);
h(Delay+1) = channel; % 信道脉冲响应
y = conv(SerOverGIOfdmSym, h);
% ed_ed_ed_ed_ed_ed_ed_ed 无线信道 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st OFDM接收端 st_st_st_st_st_st_st_st
rvSerOverGIOfdmSym = y;
OfdmSymIndx = 1 : Nifftop;
H = fft([h zeros(1, Nifftop - Lch)]); % 信道频域响应
ChFrqRep = H(OfdmSymIndx);
NofdmSym = Ncr;
Rlen = Nframe;
GiType = 'CP';
Ngi = Ncr / 4;
rvParModSym = get_modulate_symbol( rvSerOverGIOfdmSym, Nifftop, NofdmSym, Rlen, GiType, Ngi, ChFrqRep );
rvBitStream = demodulate_symbol( ModType, Nbit, rvParModSym, Nframe ); % 解调QAM/PSK符号
% ed_ed_ed_ed_ed_ed_ed_ed OFDM接收端 ed_ed_ed_ed_ed_ed_ed_ed
% @@@@@@@@ 绘制误码率(BER) @@@@@@@@
% @@@@@@@@ 绘制OFDM功率谱密度(PSD) @@@@@@@@
get_modulate_symbol.m
function ParModSym = get_modulate_symbol( SerOverGIOfdmSym, Nifftop, NofdmSym, Rlen, GiType, Ngi, ChFrqRep )
% @功能:根据串行的OFDM符号恢复PSK/QAM符号
% @返回:ParModSym值为并行的PSK/QAM符号
% @参数:SerOfdmSym —— 带过采样的串行OFDM符号
% Nifftop —— 进行ifft变换时的长度
% NofdmSym —— 一个OFDM符号的长度
% Rlen —— SerOfmSym中所包含的OFDM符号的个数
% GiType —— OFDM符号的保护间隔类型('CP', 'ZP')
% Ngi —— OFDM保护间隔长度
OverOfdmSym = zeros(Rlen, Nifftop);
ser2parIndx = 1 : Nifftop + Ngi;
for i = 1 : Rlen
OverOfdmSym(i, :) = remove_gi( SerOverGIOfdmSym(ser2parIndx), GiType, Ngi );
ser2parIndx = ser2parIndx + Nifftop + Ngi;
end % 去掉OFDM符号的保护间隔并得到并行的带过采样的OFDM符号
OverModSym = zeros(Rlen, Nifftop);
for i = 1 : Rlen
temp = fft(OverOfdmSym(i, :));
OverModSym(i, :) = temp ./ ChFrqRep;
end % 含过采样的并行调制符号加信道补偿
ParModSym = zeros(Rlen, NofdmSym);
for i = 1 : Rlen
ParModSym(i, 1 : NofdmSym / 2) = OverModSym(i, 1 : NofdmSym / 2);
ParModSym(i, NofdmSym / 2 + 1 : end) = OverModSym(i, Nifftop - NofdmSym + NofdmSym / 2 + 1 : end);
end % 还原调制符号
end
05.19
2.6 AWGN
OFDM_Basics.m
% OFDM_Basics.m
% @功能:仿真OFDM系统(链路)的发射端,无线信道模块以及接收端;
% 以一般书中的OFDM框图为最小模块组织该OFDM系统。
% @结果:绘制在OFDM链路接收端的误码率(BER);
% 绘制OFDM链路发射端OFDM符号的功率谱密度(PSD)。
clear
% ######## OFDM相关参数值 ########
Nbit = 6; % 表示数的位数
Ncr = 48; % 子载波个数
Nframe = 7; % 经过无线信道时的OFDM符号个数
% AWGN相关参数
EbN0 = 0 : 5 : 20;
sigPow = 0; % 信号功率
% st_st_st_st_st_st_st_st OFDM发射端 st_st_st_st_st_st_st_st
N = Ncr * Nframe;
% if awgnIndx == 0, 计算信号功率sigPow
% else 计算误码数Neb
for awgnIndx = 0 : length(EbN0)
sdBitStream = generate_bit_stream( Nbit, N ); % 生成发射端数据
rLen = Ncr;
ModType = 'psk';
ParModSym = generate_modulated_symbol( ModType, Nbit, sdBitStream, Nframe, rLen ); % 生成QAM/PSK符号
Nifftop = 1024;
GiType = 'CP';
Ngi = Ncr / 4;
SerOverGIOfdmSym = generate_ofdm_symbol( ParModSym, Nifftop, GiType, Ngi );
% ed_ed_ed_ed_ed_ed_ed_ed OFDM发射端 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st 无线信道 st_st_st_st_st_st_st_st
Nifftop = 1024;
[y, ChFrqRep] = multi_rayleigh( SerOverGIOfdmSym, Nifftop );
% 为添加AWGN噪声测量信号能量
if awgnIndx == 0
y1 = y(1 : Nframe * (Nifftop + Ngi));
sigPow = sigPow + y1 * y1';
sigPow = sigPow / ((Ncr + Nifftop) * Nframe);
continue;
end
% 添加 AWGN 噪声
snr = EbN0(awgnIndx) + 10 * log10(Nbit * (Ncr / Nifftop)); % 4.28式
noise_mag = sqrt((10.^(-snr / 10)) * sigPow / 2);
y_AWGN = y + noise_mag * (randn(size(y)) + 1i * randn(size(y)));
% ed_ed_ed_ed_ed_ed_ed_ed 无线信道 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st OFDM接收端 st_st_st_st_st_st_st_st
rvSerOverGIOfdmSym = y_AWGN;
NofdmSym = Ncr;
Rlen = Nframe;
GiType = 'CP';
Ngi = Ncr / 4;
rvParModSym = get_modulate_symbol( rvSerOverGIOfdmSym, Nifftop, NofdmSym, Rlen, GiType, Ngi, ChFrqRep );
rvBitStream = demodulate_symbol( ModType, Nbit, rvParModSym, Nframe ); % 解调QAM/PSK符号
% ed_ed_ed_ed_ed_ed_ed_ed OFDM接收端 ed_ed_ed_ed_ed_ed_ed_ed
end
% @@@@@@@@ 绘制误码率(BER) @@@@@@@@
% @@@@@@@@ 绘制OFDM功率谱密度(PSD) @@@@@@@@
multi_rayleigh.m
function [y, ChFrqRep] = multi_rayleigh( SerOverGIOfdmSym, Nifftop )
% @功能:描述多径rayleigh信道
% @返回:经多径ralyeigh信道后的信号
% @参数:SerOverGIOfdmSym —— 带过采样、保护间隔的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; % 信道长度
% @@@@@@@@ OFDM符号经过多径信道模块 @@@@@@@@
channel = (randn(1, Ntap) + 1i * randn(1, Ntap)).*sqrt(Power / 2);
h = zeros(1, Lch);
h(Delay+1) = channel; % 信道脉冲响应
y = conv(SerOverGIOfdmSym, h);
%信道频率响应
OfdmSymIndx = 1 : Nifftop;
H = fft([h zeros(1, Nifftop - Lch)]); % 信道频域响应
ChFrqRep = H(OfdmSymIndx);
end
05.20
2.7 误码率(BER)
OFDM_Basics.m
% OFDM_Basics.m
% @功能:仿真OFDM系统(链路)的发射端,无线信道模块以及接收端;
% 以一般书中的OFDM框图为最小模块组织该OFDM系统。
% @结果:绘制在OFDM链路接收端的误码率(BER);
% 绘制OFDM链路发射端OFDM符号的功率谱密度(PSD)。
clear
% ######## OFDM相关参数值 ########
Nbit = 6; % 表示数的位数
Ncr = 48; % 子载波个数
Nframe = 7; % 经过无线信道时的OFDM符号个数
% AWGN相关参数
EbN0 = 0 : 5 : 20;
sigPow = 0; % 信号功率
% 误码率相关参数
Neb = 0; % 在OFDM链路中传输数据时,发生位(bit)错误的数量(Neb,Number of error bits)
Ntb = 0; % 在OFDM链路中传输的总位(bit)数(Ntb,Number of total bits)
NBerIter = 1e5; % OFDM发送Niter次信息统计一次误码率BER
Target_neb = 500; % Neb的最大值
% 本程序误码率相关文件
ber_file_name = 'OFDM_Rayleigh_BER.dat';
fd = fopen(ber_file_name, 'w+');
% st_st_st_st_st_st_st_st OFDM发射端 st_st_st_st_st_st_st_st
N = Ncr * Nframe;
% if awgnIndx == 0, 计算信号功率sigPow
% else 计算误码数Neb
for awgnIndx = 0 : length(EbN0)
% 误码数和码数清0
Neb = 0;
Ntb = 0;
for berIndx = 1 : NBerIter % 每 NBerIter 统计一次OFDM链路的误码率
sdBitStream = generate_bit_stream( Nbit, N ); % 生成发射端数据
rLen = Ncr;
ModType = 'psk';
ParModSym = generate_modulated_symbol( ModType, Nbit, sdBitStream, Nframe, rLen ); % 生成QAM/PSK符号
Ngi = Ncr / 4;
GiType = 'CP';
Nifftop = 1024;
SerOverGIOfdmSym = generate_ofdm_symbol( ParModSym, Nifftop, GiType, Ngi ); % 生成OFDM符号
% ed_ed_ed_ed_ed_ed_ed_ed OFDM发射端 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st 无线信道 st_st_st_st_st_st_st_st
Nifftop = 1024;
[y, ChFrqRep] = multi_rayleigh( SerOverGIOfdmSym, Nifftop );
% @@@@@@@@ 为添加AWGN噪声测量信号能量 - NBerIter次 @@@@@@@@
if awgnIndx == 0
y1 = y(1 : Nframe * (Nifftop + Ngi));
sigPow = sigPow + y1 * y1';
continue;
end
% @@@@@@@@ 添加 AWGN 噪声 @@@@@@@@
snr = EbN0(awgnIndx) + 10 * log10(Nbit * (Ncr / Nifftop)); % 4.28式
noise_mag = sqrt((10.^(-snr / 10)) * sigPow / 2);
y_AWGN = y + noise_mag * (randn(size(y)) + 1i * randn(size(y)));
% ed_ed_ed_ed_ed_ed_ed_ed 无线信道 ed_ed_ed_ed_ed_ed_ed_ed
% st_st_st_st_st_st_st_st OFDM接收端 st_st_st_st_st_st_st_st
rvSerOverGIOfdmSym = y_AWGN;
Ngi = Ncr / 4;
Rlen = Nframe;
GiType = 'CP';
NofdmSym = Ncr;
rvParModSym = get_modulate_symbol( rvSerOverGIOfdmSym, Nifftop, NofdmSym, Rlen, GiType, Ngi, ChFrqRep ); % 由串行的OFDM符号得到QAM/PSK符号
rvBitStream = demodulate_symbol( ModType, Nbit, rvParModSym, Nframe ); % 解调QAM/PSK符号
% @@@@@@@@ 误码统计 @@@@@@@@
Neb = Neb + sum(sum(de2bi(rvBitStream, Nbit) ~= de2bi(sdBitStream, Nbit)));
Ntb = Ntb + Ncr * Nframe * Nbit;
if Neb > Target_neb, break;end % 误码率迭代到这里已经足够大了
% ed_ed_ed_ed_ed_ed_ed_ed OFDM接收端 ed_ed_ed_ed_ed_ed_ed_ed
end
% @@@@@@@@ 误码率计算 @@@@@@@@
BER = Neb / Ntb;
if awgnIndx == 0
sigPow = sigPow / ((Ncr + Nifftop) * Nframe * NBerIter); % 每个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
% @@@@@@@@ 绘制误码率(BER) @@@@@@@@
figure(1); clf
plot_ber(ber_file_name); % 绘制OFDM链路接收端的误码率曲线
% @@@@@@@@ 绘制OFDM功率谱密度(PSD) @@@@@@@@
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
在matlab的命令行中运行OFDM_Basics.m文件,得到BER曲线图如下:
05.24
2.8 OFDM的功率谱密度(PSD)
OFDM_Basics.m
以上是关于[8] OFDM的发送和接收 —— 按照框图模块化的主要内容,如果未能解决你的问题,请参考以下文章
PythonPython 仿真OFDM发射机信道和接收机-实现多种调制方式