关于OFDM系统的MATLAB仿真实现的第二篇随笔,在第一篇中,我们讨论的是信号经过AWGN信道的情况,只用添加固定噪声功率的高斯白噪声就好了。但在实际无线信道中,信道干扰常常是加性噪声、多径衰落的结合。今天我们准备再进一步,让信号经过多径瑞利衰落信道。在这种信道条件下,信号具体是怎么怎么变化的呢?下面将讲解系统仿真的各个部分以及实现多径衰落的方法。

)。这些技术的数学理论推导确实很难,但是在MATLAB仿真中往往用几个自带的函数就能解决问题,所以要实现一个简单的OFDM系统还是很容易的,不要被天花乱坠般恐怖的数学公式吓跑了(所以我最喜欢的就是直接看代码的运行过程,然后有时间再去研究数学推导23333)。



步骤1>

这个仿真好像暂时没有时间的概念,单位是按照采样点来的。假设一帧有三个OFDM符号,每个符号长度为64(刚好在步骤3做IFFT时长度也为64,满足2的幂次方)。我们首先生成数字基带信号,信号长度为192个采样点,由于要进行16QAM调制,我们直接随机生成192个16进制的数作为基带信号X(K),然后再将X(K)经过16QAM星座图映射便完成了调制。打工仔,怎么能不进行误码率分析呢?于是当前步骤我们研究一下怎么分析误码率。其实也很简单,计算一下Yr和X有几比特不相同,再计算一下总共有几比特,把它们相除就得到了我们的比特误码率(BER)。

需要注意的一点是,既然是误比特率,就要把16进制的信号转换成2进制,以比特为单位计算错误数

代码:

Neb = sum(sum(de2bi(Yr,K) ~= de2bi(X,K))); % 转为2进制,计算具体有几bit错误
Ntb = NFFT * NFRAME * K;  % 仿真的总比特数
BER = Neb / Ntb;


完整代码:

最后贴一个完整代码,代码是参考的《MIMO-OFDM无线通信技术及MATLAB实现》这本书。我是一行一行自己重新实现了一遍并且加上了详细的中文注释,希望能对像我这样的刚入门的萌新有所启发。对了,后面有个与理论值相比较的作图函数有点占位置,我就暂时不放到这篇文章中了XD。注意在包含多径衰落信道的仿真的时候,如果想要仿真不同信噪比时的误码率,务必要生成一个状态种子,保持衰落信道参数在每一次仿真中都不变。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Version 3.1
%%% 16QAM调制(官方函数)
%%% IFFT(官方函数)
%%% 添加循环前缀
%%% 经过多径瑞利衰减信道
%%% 添加AWGN
%%% 去除循环前缀
%%% FFT(官方函数)
%%% 16QAM解调(官方函数)
%%% BER分析
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;close all;clc;
%% 基带数字信号及一些初始化
NFRAME = 3;      % 每一帧的OFDM符号数
NFFT = 64;         % 每帧FFT长度
NCP = 16;          % 循环前缀长度
NSYM = NFFT + NCP; % OFDM符号长度
M = 16; K = 4;     % M:调制阶数,K:log2(M)

P_hdB = [0 -8 -17 -21 -25];     % 各信道功率特性(dB)
D_h = [0 3 5 6 8];              % 各信道延迟(采样点)
P_h = 10 .^ (P_hdB / 10);       % 各信道功率特性
NH = length(P_hdB);             % 多径信道个数
LH = D_h(end)+1;                % 信道长度(延迟过后)

EbN0 = 0:1:20;              % 设出比特信噪比(dB)
snr = EbN0 + 10 * log10(K); % 由比特信噪比计算出snr(dB)
BER(1 : length(EbN0)) = 0;  % 初始化误码率

file_name=['OFDM_BER_NCP' num2str(NCP) '.dat'];
fid=fopen(file_name, 'w+');

X = randi([0,15],1,NFFT * NFRAME); % 生成基带数字信号
%%
for i = 1 : length(EbN0) % 对于每一种比特信噪比,计算该通信环境下的误码率

    randn('state',0); % 很重要!!保持信道参数在每一次仿真中都不变
    rand('state',0);

    %% 16QAM调制(官方函数)
    X_mod = qammod(X,M,'gray') / (sqrt(10)); % 16QAM调制,格雷码星座图,并归一化
    %% IFFT与循环前缀添加
    x(1 : NFFT * NFRAME) = 0; % 预分配x数组
    xt(1 : (NFFT + NCP) * NFRAME) = 0; % 预分配xt数组

    len_a = 1 : NFFT; % 处理的X位置
    len_b = 1 : (NFFT + NCP); % 处理的X位置(加上CP的长度)
    len_c = 1 : NCP;
    len_left = 1 : (NFFT / 2); len_right = (NFFT / 2 + 1) : NFFT; % 每一符号分为左右两边??

    for frame = 1 : NFRAME % 对于每个OFDM符号都要翻转和IFFT
        x(len_a) = ifft([X_mod(len_right), X_mod(len_left)]); % 左右翻转再ifft
        xt(len_b) = [x(len_c + NFFT - NCP), x(len_a)]; % 添加CP后的信号数组

        len_a = len_a + NFFT; % 更新找到下一个符号起点位置
        len_b = len_b + NFFT + NCP; % 更新找到下一个符号起点位置(CP开头)
        len_c = len_c + NFFT;
        len_left = len_left + NFFT; len_right = len_right + NFFT;
    end
    %% 经过多径瑞利衰减信道
    A_h = (randn(1,NH) + 1i * randn(1,NH)) .* sqrt(P_h / 2); % 生成瑞利随机变量
    h = zeros(1,LH); % 初始化信道冲激响应模型
    h(D_h + 1) = A_h; % 信道冲激响应(同时体现出衰减系数和信道时延)
    xt1 = conv(xt,h); % 卷积,输出通过该信道的信号
    %% 由snr计算噪声幅度并加噪
    xt2 = xt1(1 : NSYM * NFRAME); % 只取卷积过后属于OFDM符号的部分
    P_s = xt2 * xt2' ./ NSYM ./ NFRAME; % 计算信号功率

    A_n = sqrt(10 .^ (-snr(i) / 10) * P_s / 2); % 计算噪声标准差
    yr = xt1 + A_n * (randn(size(xt1)) + 1i * randn(size(xt1))); % 根据噪声标准差添加噪声
    %% 去除循环前缀并且FFT
    y(1 : NFFT * NFRAME) = 0; % 预分配y数组
    Y(1 : NFFT * NFRAME) = 0; % 预分配Y数组

    len_a = 1 : NFFT; % 处理的y位置
    len_b = 1 : NFFT; % 处理的y位置
    len_left = 1 : (NFFT / 2); len_right = (NFFT / 2 + 1) : NFFT; % 每一符号分为左右两边

     H= fft([h zeros(1,NFFT-LH)]); % 信道频率响应
     H_shift(len_a)= [H(len_right) H(len_left)];

    for frame = 1 : NFRAME % 对于每个OFDM符号先去CP,再FFT再翻转
        y(len_a) = yr(len_b + NCP); % 去掉CP

        Y(len_a) = fft(y(len_a)); % 先fft再翻转
        Y(len_a) = [Y(len_right), Y(len_left)] ./ H_shift; % //

        len_a = len_a + NFFT;
        len_b = len_b + NFFT + NCP;
        len_left = len_left + NFFT; len_right = len_right + NFFT;
    end
    %% 16QAM解调(官方函数)
    Yr = qamdemod(Y * sqrt(10),M,'gray');
    %% BER计算(多次迭代算均值会更准确)
    Neb = sum(sum(de2bi(Yr,K) ~= de2bi(X,K))); % 转为2进制,计算具体有几bit错误
    Ntb = NFFT * NFRAME * K;  %[Ber,Neb,Ntb]=ber(bit_Rx,bit,Nbps);
    BER(i) = Neb / Ntb;
    fprintf('EbN0 = %3d[dB], BER = %4d / %8d = %11.3e\n', EbN0(i),Neb,Ntb,BER(i))
    fprintf(fid, '%d %11.3e\n', EbN0(i),BER(i));
end
%% BER作图分析
fclose(fid);
disp('Simulation is finished');
plot_ber(file_name,K);


参考文献:

[1] Tse D, Viswanath P. Fundamentals of wireless communication[M]. Cambridge university press, 2005.

[2] Cho Y S, Kim J, Yang W Y, et al. MIMO-OFDM wireless communications with MATLAB[M]. John Wiley & Sons, 2010.

[3] Goldsmith A. Wireless communications[M]. Cambridge university press, 2005.

07-23 12:15