📄 liuguifen.m
字号:
1 模块Simatar.m
set_sim_consts;
%设定输入数据长度
plen=2;
%生成输入数据
inf_bits = randn(1, plen*8) > 0;
%根据输入选择映射方式
MOD=“16QAM”
start_time=clock;
%填充位
rdy_to_mod_bits = make_int_num_ofdm_syms(inf_bits, MOD);
%调制映射
mod_syms=modulate(rdy_to_mod_bits,MOD);
%加导频
mod_ofdm_syms =add_pilot_syms(mod_syms);
% IFFT频域到时域变换 (OFDM调制)
time_syms = freqd_to_timed(mod_ofdm_syms);
% 加循环前缀(CP)
time_signal = add_cyclic_prefix(time_syms);
stop_time = clock;
elapsed_time = etime(stop_time,start_time);
fprintf('仿真用时: %g 秒\n',elapsed_time);
%图表显示
stem(inf_bits);title('输入序列');
figure
scatterplot(abs(mod_syms));title('调制映射后序列(星座图)');ylabel('实部');xlabel('虚部')
figure
compass(mod_syms);title('调制映射后序列(相位图)');
figure
stem(abs(mod_syms));title('调制映射后序列');ylabel('实部');xlabel('虚部')
figure
stem(abs(mod_ofdm_syms));title('调制映射后序列加导频');ylabel('实部');xlabel('虚部')
figure
stem(abs(time_syms));title('OFDM调制后输出');ylabel('幅度');xlabel('序列')
figure
stem(abs(time_signal));title('OFDM调制后加CP时域输出');ylabel('幅度');xlabel('序列')
2 模块sim_const.m
function sim_consts = set_sim_consts
global sim_consts;
%抽样频率
sim_consts = struct('SampFreq' , 20e6, ...
'ConvCodeGenPoly', [1 0 1 1 0 1 1;1 1 1 1 0 0 1 ], ...
'NumSubc', 52, ... %子载波数
'UsedSubcIdx', [7:32 34:59]', ...%子载波位置
'ShortTrainingSymbols', sqrt(13/6)*[0 0 1+j 0 0 0 -1-j 0 0 0 1+j 0 0 0 -1-j 0 0 0 -1-j 0 0 0 1+j 0 0 0 0 0 0 -1-j 0 0 0 -1-j 0 0 0 ...
1+j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0], ...
'LongTrainingSymbols', [1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 ...
1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1], ...
'ExtraNoiseSamples', 500, ...
%导频极性序列
'PilotScramble', [1 1 1 1 -1 -1 -1 1 -1 -1 -1 -1 1 1 -1 1 -1 -1 1 1 -1 1 1 -1 1 1 1 1 ...
1 1 -1 1 1 1 -1 1 1 -1 -1 1 1 1 -1 1 -1 -1 -1 1 -1 1 -1 -1 1 -1 -1 1 1 1 1 1 -1 -1 1 ...
1 -1 -1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 -1 -1 -1 1 -1 -1 1 -1 1 1 1 1 -1 1 -1 1 -1 1 -1 ...
-1 -1 -1 -1 1 -1 1 1 -1 1 -1 1 1 1 -1 -1 1 -1 -1 -1 1 1 1 -1 -1 -1 -1 -1 -1 -1], ...
'NumDataSubc', 48, ...%数据载波数
'NumPilotSubc' , 4, ...% 导频数
'DataSubcIdx', [7:11 13:25 27:32 34:39 41:53 55:59]', ... %数据载波位置
'PilotSubcIdx', [12 26 40 54]', ...% 导频位置
'PilotSubcPatt', [6 20 33 47]', ...%导频插入方式
'DataSubcPatt', [1:5 7:19 21:26 27:32 34:46 48:52]', ...%数据载波规格
'PilotSubcSymbols' , [1;1;1;-1]);%插入的导频数据
3 模块Modulate.m:
function mod_symbols = tx_modulate(bits_in, modulation)
full_len = length(bits_in);
if ~isempty(findstr(modulation, '16QAM'))
% 生成 16QAM 符号
m=1;
for k=-3:2:3
for l=-3:2:3
table(m) = (k+j*l)/sqrt(10); % 功率归一化
m=m+1;
end;
end;
table=table([0 1 3 2 4 5 7 6 12 13 15 14 8 9 11 10]+1); % 按照格雷编码星座图顺序定义16-QAM映射矩阵
inp=reshape(bits_in,4,full_len/4);%以4个比特为一列调整输入序列
mod_symbols=table([8 4 2 1]*inp+1); % 将输入序列进行16QAM映射
else
error('未定义的调制方式');
end
4 模块make_int_num_ofdm_syms.m:
function out_bits = make_int_num_ofdm_syms(tx_bits, MOD)
global sim_consts;
n_tx_bits = length(tx_bits);
n_syms = sim_consts.NumDataSubc;
%根据映射方式计算一个OFDM符号需要的比特数
n_bits_per_sym = get_bits_per_symbol(MOD);
%计算OFDM符号数 总比特数/(定义子载波数*每个符号所需比特数)
n_ofdm_syms = ceil(n_tx_bits/(n_syms*n_bits_per_sym));
%根据OFDM符号中的比特数进行填充(填充随机0 1)
%802.11a中填充比特均为0 最后再与数据加扰 此仿真中使用随机生成数据代替加扰
%符号数*一个符号的载波数*一个载波的比特数-输入比特数=需要填充的比特数
pad_bits = randn(1, n_ofdm_syms*n_syms*n_bits_per_sym - n_tx_bits) > 0;
%根据OFDM符号中的比特数进行全0填充
%pad_bits = zeros(1, n_ofdm_syms*n_syms*n_bits_per_sym - n_tx_bits)
%输出
out_bits = [tx_bits pad_bits];
4 模块get_bits_per_symbol:
function num_bits = get_bits_per_symbol(mod_order)
%根据调制方式定义一个符号的比特数
if ~isempty(strmatch(mod_order, '16QAM','exact'))
num_bits=4;
else
error('未定义的调制方式');
end
5 模块freqd_to_timed.m:
function time_syms = freqd_to_timed(mod_ofdm_syms)
global sim_consts;
% OFDM符号数统计
num_symbols = size(mod_ofdm_syms, 2)/sim_consts.NumSubc;
%IFFT抽样形式
resample_patt=[33:64 1:32];
%生成时域信号0矩阵
time_syms = zeros(1, num_symbols*64);
% 将信号转为时域 64点IFFT
syms_into_ifft = zeros(64, num_symbols);
%将一个OFDM符号中的子载波以列的形式按照 UsedSubcIdx [7:32 34:59]放置到IFFT调制矩阵中 (52行 OFDM符号数列)
syms_into_ifft(sim_consts.UsedSubcIdx,:) = reshape(mod_ofdm_syms, ...
sim_consts.NumSubc, num_symbols);
%按resample_patt=[33:64 1:32]抽取syms_into_ifft中子载波以列的方式进行IFFT变换
syms_into_ifft(resample_patt,:) = syms_into_ifft;
%IFFT
ifft_out = ifft(syms_into_ifft);
%转换为行的形式
time_syms = ifft_out(:).';
6 模块add_pilot_syms:
function mod_ofdm_syms = add_pilot_syms(mod_syms, sim_options)
global sim_consts;
%获取信号数
n_mod_syms = size(mod_syms,2);
%获取OFDM符号数
n_ofdm_syms = n_mod_syms/sim_consts.NumDataSubc;
%估计数据长度是否大于P序列,若大于则重复P序列
scramble_patt = repmat(sim_consts.PilotScramble,1,ceil(n_ofdm_syms/length(sim_consts.PilotScramble)));
%每个OFDM符号与一个P序列元素对应 列出需要用到的P序列元素
scramble_patt = scramble_patt(1:n_ofdm_syms);
%生成一个列为一个OFDM符号 行为48个数据载波的0矩阵
mod_ofdm_syms = zeros(sim_consts.NumSubc, n_ofdm_syms);
% 一列为一个OFDM符号 行为48个数据载波 将数据以DataSubcPatt[1:5 7:19 21:26 27:32 34:46 48:52]的形式填入
mod_ofdm_syms(sim_consts.DataSubcPatt,:) = reshape(mod_syms, sim_consts.NumDataSubc, n_ofdm_syms);
%将导频载波形式PilotSubcSymbols填入 并与极性序列相乘 PilotSubcPatt为填入位置
mod_ofdm_syms(sim_consts.PilotSubcPatt,:) = repmat(scramble_patt, sim_consts.NumPilotSubc,1).* ...
repmat(sim_consts.PilotSubcSymbols, 1, n_ofdm_syms);
%将矩阵转为序列
mod_ofdm_syms = mod_ofdm_syms(:).';
7 模块add_cyclic_prefix.m:
function time_signal = add_cyclic_prefix(time_syms)
%OFDM信号数统计
num_symbols = size(time_syms, 2)/64;
%生成时域信号0矩阵 80为加CP后的总长 取决于CP长(CP长为16)
%协议规定GI长度为0.8μs IFFT周期为3.2μs
%即GI长为1/4的64点IFFT长 为16
time_signal = zeros(1, num_symbols*80);
%添加循环前缀CP
symbols = reshape(time_syms, 64, num_symbols);
%设定提取冗余数据长度 49:64(16)
tmp_syms = [symbols(49:64,:); symbols];
time_signal = tmp_syms(:).';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -