虽然Simulink中包含了很多已有的Blocks,但并不是时刻符合我们的使用需求,况且有时还不清楚Simulink某些模块的封装,以及内部的运行机制。所以自定义创建simulink模块不失为一个好方法。

MATLAB提供了几种自定义封装Simulink模块的方式。本文简单使用s-function进行封装,仿真16QAM调制解调

QAM调制解调原理

仿真前先回顾下QAM的调制解调原理,本文只针对16QAM进行分析和仿真

1、基本原理

QAM(正交幅度调制,Quadrature Amplitude Modulation)利用两路独立的数字基带信号,对两个相互正交的同频载波进行抑制载波的双边带调制。QAM本质上是一种 IQ 调制,利用这种已调信号在同一带宽内频谱正交的性质来实现两路并行的数字信号传输。

从数学表达式的角度来看:

QAM调制信号一般表达式:
QAM调制信号一般表达式

式中,An是基带信号的幅度,g(t-nTs)是宽度为Ts的单个基带波形

利用三角函数变换公式可以对上述表达式变换成 正交 的表示形式:
正交表示形式

从上式可以看到,QAM调制信号可以“分解”为两路基带数字信号
Σ A g ( t − n T s ) c o s ϕ \Sigma Ag(t-nTs)cos\phi ΣAg(tnTs)cosϕ Σ A g ( t − n T s ) s i n ϕ \Sigma Ag(t-nTs)sin\phi ΣAg(tnTs)sinϕ
分别去调制两个 同频相互正交 的载波信号 cos ω \omega ωct 和 sin ω \omega ωct

  • 因此我们在做QAM调制的时候需要将基带信号分成I和Q两路信号分别对载波进行调制
  • 对于基带信号中的An ϕ \phi ϕn即幅度和相位,我们可以分别调整他们的取值,组合起来就可以得到不同的基带信号,对应星座图上不同的点,这样就可以实现MQAM(M可以取4,16,64等等)

2、16QAM星座图

16QAM基带信息与平面点的对应方式有 方型星型两种(本文仅对方型进行仿真)

方型16QAM星座图如下图所示,平面上的点采用 格雷码 进行映射
方型16QAM星座图

由于平面上总共有16个符号,所以需要4个bit表示一个符号

3、16QAM调制解调原理

QAM调制流程
QAM解调流程

自建Simulink模块

采用一种简易方法:利用MATLAB提供的 s-function.m 文件封装成Simulink模块

  1. 在MATLAB命令行中:edit sfuntmpl 打开s-function模板。对sfuntmpl.m进行更改,编写所需要的封装block程序

sfuntmpl.m参数介绍

  1. 函数形式:
    function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)
  2. 输入参数
    t:当前的时间
    x:状态向量
    u:输入向量
    flag:(整数)指示s-function应该执行的任务
  3. 输出参数
    sys:通用的返回参数,其值取决于flag的值
    x0:初始状态
    str:保留
    ts:一个1x2的矩阵,第一列指示block的采样时间,第二列指示偏移量
  4. flag的取值对应的s-function程序:
    0:mdlInitializeSizes
    1:mdlDerivatives
    2:mdlUpdate
    3:mdlOutputs
    4:mdlGetTimeOfNextVarHit
    9:mdlTerminate
  1. 在本次仿真中,只需要用到flag=0和flag=3的情况,即只需要修改s-function模板的初始化和输出过程
  2. 更改s-function函数名称,并保证文件命名和其一致
  3. 在simulink中使用s-function模块
    s-function
    模块参数
    在使用时,需要将s-function name修改为函数的名称。同时还可以在这里设置s-function传入的参数

Simulink仿真16QAM调制解调

1. 仿真参数

信源速率:4kbps
载波频率:8kHz
采样频率:80kHz

2. 整体框图

整体框图

3. 设计思路

根据QAM调制解调原理图自建simulink模块,搭建仿真框图

3.1 信源产生

利用Simulink中Random Integer Generator block产生随机二进制序列
设置
set size:2
Sample time:1/4e3
Samples per frame:1(即在每个时刻输出的信号为1x1的帧)
random integer generator

3.2 幅度/相位映射

根据16QAM调制流程,需要对信源产生的二进制随机序列进行串/并转换成IQ两路,再分别对这两路进行幅度/相位映射。

由于星座图上每个点代表一个符号,其坐标可以用复数表示。这里Simulink仿真时,将信源产生的 每4个比特 对应 1个符号,分别取出坐标的 实部虚部 即可将数据流分成IQ两路。

幅度/相位映射
Buffer模块参数设置:
buffer1
Buffer模块降低信息的速率,在每个时刻输出一个[4x1]的帧
sim_REgraymodsim_IMgraymod 为s-function模块,分别取出映射后的实部和虚部。以sim_REgraymod为例。
命令行输入:

edit sfuntmpl

打开s-function模板,将函数名更改为sim_REgraymod,并和.slx文件保存在同一目录下。

function [sys,x0,str,ts,simStateCompliance] = sim_REgraymod(t,x,u,flag)

改动初始化函数 mdlInitializeSizes

sizes.NumContStates  = 0;	%此仿真不涉及连续和离散状态,都设置为0
sizes.NumDiscStates  = 0;	
sizes.NumOutputs     = 1;	%每个时刻输出为1维向量
sizes.NumInputs      = 4;	%每个时刻输入为4维向量(4x1的帧)
sizes.DirFeedthrough = 1;	%直馈
sizes.NumSampleTimes = 1; 
%.............
%.............
ts  = [1/1e3 0];	%信源速率为4kbps,经过buffer后变成1kbps,初始时间设置为0

改动输出函数 mdlOutputs

function sys=mdlOutputs(t,x,u)
switch [num2str(u(1)) num2str(u(2)) num2str(u(3)) num2str(u(4))]
        case '0010'
            graytrans=-3+3i;
        case '0110'
            graytrans=-1+3i;
        case '1110'
            graytrans=1+3i;
        case '1010'
            graytrans=3+3i;
        case '0011'
            graytrans=-3+1i;
        case '0111'
            graytrans=-1+1i;
        case '1111'
            graytrans=1+1i;
        case '1011'
            graytrans=3+1i;
        case '0001'
            graytrans=-3-1i;
        case '0101'
            graytrans=-1-1i;
        case '1101'
            graytrans=1-1i;
        case '1001'
            graytrans=3-1i;
        case '0000'
            graytrans=-3-3i;
        case '0100'
            graytrans=-1-3i;
        case '1100'
            graytrans=1-3i;
        case '1000'
            graytrans=3-3i;
end
sys = real(graytrans);	%此模块输出实部
3.3 脉冲成型

基带信号发射前需要经过脉冲成型,可以利用MATLAB自带的 fdatool设计合适的根升余弦滤波器。
脉冲成型
设计滤波器参数
Response Type:Raise - Cosine
Design Method:FIR
Window:Kaiser
Beta:0.5
Fs:80000
Fc:8000
Rolloff:0.25
Square root

File —> Export to Simulink Model将设计好的滤波器导出成模块

经过脉冲成型滤波器之前需要对信号进行升采样
利用zero-order hold模块,设置模块的Sample time为采样间隔:1/80kHz

3.4 调制

Sine Wave模块可以生成载波
c o s ω t cos\omega t cosωt
cos
cosine
s i n ω t sin\omega t sinωt
sin
sine
分别与I Q两路信号相乘后相加得到16QAM已调信号

3.5 AWGN信道

已调信号经过AWGN信号,信噪比设置为15dB

3.6 解调

解调
已调信号与载波相乘,经过低通滤波器,再进行抽样判决可恢复出原始信号(此时恢复出的信号为幅度/相位映射后的IQ路信号)

低通滤波器与前面的脉冲成型滤波器相同(既起到低通滤波的作用,同时两个根升余弦滤波器相乘后就是一个升余弦滤波器,通信原理书上都会讲到,在此不赘述)

Gain:gain=2,信号幅度乘2

抽样:还是利用zero-order Hold模块,但是因为抽样的频率和IQ路信息速率一致,所以模块的Sample time设置为1/1e3

sim_SampleDecision 为s-function模块,对抽样后的信号进行判决
代码如下:

function [sys,x0,str,ts,simStateCompliance] = sim_SampleDecision(t,x,u,flag)%更改函数名
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes	%编辑初始化函数
%......
sizes.NumOutputs     = 1;	%输出为1维向量
sizes.NumInputs      = 1;	%输入为1维向量
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
%......
ts  = [1/1e3 0];	%采样间隔和前面模块一致
function sys=mdlOutputs(t,x,u)	%编辑输出函数
sample_point = u;
sys = round((sample_point+1)/2)*2-1;   %判决电平为-2,0,2
% end mdlOutputs
3.7 逆映射与并/串转换

逆映射
MUX模块可以将两路信号复用到一路,每个时刻输出一个2x1的帧。sim_graydemod 是s-function模块,将星座图上的一个符号逆映射成4位比特序列。
代码如下:

function [sys,x0,str,ts,simStateCompliance] = sim_graydemod(t,x,u,flag)	%更改函数名
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
%.....
sizes.NumOutputs     = 4;	%输出4位比特
sizes.NumInputs      = 2;	%输入为二维向量
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;
%.....
ts  = [1/1e3 0];
function sys=mdlOutputs(t,x,u)
switch [num2str(u(1)) num2str(u(2))]
        case '11'
            sys=[1 1 1 1];
        case '13'
            sys=[1 1 1 0];
        case '33'
            sys=[1 0 1 0];
        case '31'
            sys=[1 0 1 1];
        case '-11'
            sys=[0 1 1 1];
        case '-31'
            sys=[0 0 1 1];
        case '-13'
            sys=[0 1 1 0];
        case '-33'
            sys=[0 0 1 0];
        case '-1-1'
            sys=[0 1 0 1];
        case '-3-1'
            sys=[0 0 0 1];
        case '-1-3'
            sys=[0 1 0 0];
        case '-3-3'
            sys=[0 0 0 0];
        case '1-1'
            sys=[1 1 0 1];
        case '3-1'
            sys=[1 0 0 1];
        case '1-3'
            sys=[1 1 0 0];
        case '3-3'
            sys=[1 0 0 0];
    otherwise
            sys=[0 0 0 0];
end

Unbuffer 模块
Initial Conditions:0

Convert a frame to scalar samples output at a higher rate.
恢复出信源输出的原始序列

3.8 计算误码率

计算误码率
Error rate calculation模块可以计算误码率。通过对比信源产生的原始序列和恢复出的序列时域波形可以看到,这两者之间延迟差了8个码元,计算误码率的时候需要考虑
参数设置如下:
参数设置

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐