Simulink仿真入门到精通(十九) 总结回顾&自我练习

摘要:
从2019年12月27日到2020年2月12日,从初学者到熟练掌握Simulink模拟和代码生成技术需要17天。

从2019年12月27到2020年2月12日,学习了Simulink仿真及代码生成技术入门到精通,历时17天。

学习的比较粗糙,有一些地方还没理解透彻,全书梳理总结:

  • Simulink的基础模块已基本掌握,对不熟悉的模块可以借助帮助文档了解其功能;
  • Simulink信号基本掌握,了解了各种信号的外观及意义的不同;
  • 对Simulink子系统的认识有待深入,对原子子系统需要进一步熟悉;
  • 对仿真过程及参数配置有所了解,对Debugger的应用不太熟悉;
  • 对回调函数有所认识,能够简单应用到参数预加载等场合;
  • 关于M语言对Simulink的操作有待进一步熟悉;
  • Simulink流控制有待进一步熟悉;
  • S函数掌握得不好;
  • 对模块的封装有所认识,能够应用到子系统外观绘制等场合;
  • 自定义库、自定义环境估计暂且用不到;
  • 对代码生成前的配置有了一定的认识,对各种优化代码生成的技巧需要进一步练习;
  • 对TLC语言有初步的入门。

在学习过程中一直采用打字记录的方法,其间一周由QQ拼音统计的结果如下,好处在于在仔细地输入过程中对书中内容有了更多的思考时间,对参数配置都过了一遍,而不是走马观花,以后用到之时即使记不起具体内容,应该也会记得我在哪里曾经输入过,方便回来查找。坏处在于花费了较多时间,且博客照搬书中文字,缺少自己的思考和创新,在以后的学习中,应该简要记录重点内容,加之自己的思考和描述。

Simulink仿真入门到精通(十九) 总结回顾&自我练习第1张

全书共19章,最后一章由于没有下载到相应的库和工具,暂且放过。其他1~18章链接如下。在打字过程中难免疏漏,存在一些错误,希望日后查阅时能够逐步改正,如果这些博客有幸为其他小伙伴所浏览,也欢迎评论指出错误之处。

Simulink仿真入门到精通(一) Simulink界面介绍

Simulink仿真入门到精通(二) Simulink模块

Simulink仿真入门到精通(三) Simulink信号

Simulink仿真入门到精通(四) Simulink子系统

Simulink仿真入门到精通(五) Simulink模型的仿真

Simulink仿真入门到精通(六) Simulink模型保存为图片

Simulink仿真入门到精通(七) Simulink的回调函数

Simulink仿真入门到精通(八) M语言对Simulink模型的自动化操作及配置

Simulink仿真入门到精通(九) Simulink的流控制

Simulink仿真入门到精通(十) S函数

Simulink仿真入门到精通(十一) 模块的封装

Simulink仿真入门到精通(十二) Publish发布M文件

Simulink仿真入门到精通(十三) Simulink创建自定义库

Simulink仿真入门到精通(十四) Simulink自定义环境

Simulink仿真入门到精通(十五) Simulink在流程工业中的仿真应用

Simulink仿真入门到精通(十六) Simulink基于模型设计的工业应用概述

Simulink仿真入门到精通(十七) Simulink代码生成技术详解

Simulink仿真入门到精通(十八) TLC语言

学完本书,决定完成一个代码生成的练习,以低通滤波器为例,以C51做载体,原因在于C51比较简单,资源较少,我比较熟悉,另外C51可以借助Keil、Proteus等工具方便地进行仿真,验证其正确性。

下面将介绍我的练习过程。

注:MATLAB版本2018a,Keil V5.24,Proteus8.6。

1. Simulink模型

1.1 模型外观

Simulink仿真入门到精通(十九) 总结回顾&自我练习第2张

Simulink仿真入门到精通(十九) 总结回顾&自我练习第3张

说明:

  • 为了配合C51的数据类型,输入输出均设置为uint16,故需要进行数据类型转换;
  • LPF(Low Pass Filter)内部结构及输出表达式如图所示;
  • 增益参数设为g,并在Model Properties→Callbacks→PreLoadFcn中设置回调函数为g=0.05;以便与在生成的代码中对增益进行修改;
  • 在Mask Editor的Icon drawing commands中添加一下绘图命令,绘制低通滤波器的大致形状,使模块美观。
num=1;
den=[1,1];
ts=tf(num,den);
P=bodeoptions;
[mag,~,w]=bode(ts,P);
w=reshape(w,1,length(w));
mag=reshape(mag,1,length(w));
dB=20*log10(mag);
w=log10(w);
plot(w,dB);

传递函数G(s)=1/(s+1),使用bode获取幅频特性并绘图。

补:本想选用DSP System Toolbox→Filtering→Filter Implementations中的Analog Filter Design作为低通滤波器。但此模块阶数(Order)较高时,计算比较复杂,可能导致C51的RAM空间不足,此处只是为了验证代码生成的过程,故选用比较简单的模型。

Simulink仿真入门到精通(十九) 总结回顾&自我练习第4张

1.2 模型配置

Solver Type:Fixed-step

Solver:discrete(no continuous states)

生成嵌入式代码必须采用固定步长,由于没有连续环节,故可选用离散解算器。

Device:Intel

Device type:8051 Compatible

注:MATLAB2018a中没有此选项,但可以在低版本MATLAB中建立模型,选择此项,再将模型在2018a中打开即可。

System target file:ert.tlc

Language:C

Generate code only:√

Default parameter behavior:Tunable

Create code generation report:√

Open report automatically:√

生成报告并自动打开。

Generate an example main program:

自己编写main主函数,不需生成示例。

其他参数保持默认。

1.3 模型仿真

在Simulink中建立如下模型。

Simulink仿真入门到精通(十九) 总结回顾&自我练习第5张

Simulink仿真入门到精通(十九) 总结回顾&自我练习第6张

输入信号由正弦信号和正态随机数叠加构成。

仿真时长30s,步长0.01s,得到仿真结果如下图所示。

Simulink仿真入门到精通(十九) 总结回顾&自我练习第7张

可以看到,模型具有较好的滤波效果。

1.4 代码生成

配置好模型参数后,选定好工作目录,按下Ctrl+B,启动代码生成。

得到Report如下图。

Simulink仿真入门到精通(十九) 总结回顾&自我练习第8张

在LPF_data中可以看到g的定义,在此处可进行修改。

Simulink仿真入门到精通(十九) 总结回顾&自我练习第9张

LPF_step函数为核心函数。

void LPF_step(void)
{
  real_T rtb_Add1;
  real_T tmp;

  /* Sum: '<S1>/Add1' incorporates:
   *  DataTypeConversion: '<Root>/Data Type Conversion'
   *  Gain: '<S1>/Gain'
   *  Inport: '<Root>/In1'
   *  Sum: '<S1>/Add'
   *  UnitDelay: '<S1>/Unit Delay'
   */
  rtb_Add1 = ((real_T)LPF_U.In1 - LPF_DW.UnitDelay_DSTATE) * LPF_P.g +
    LPF_DW.UnitDelay_DSTATE;

  /* DataTypeConversion: '<Root>/Data Type Conversion1' */
  tmp = floor(rtb_Add1);
  if (rtIsNaN(tmp) || rtIsInf(tmp)) {
    tmp = 0.0;
  } else {
    tmp = fmod(tmp, 65536.0);
  }

  /* Outport: '<Root>/Out1' incorporates:
   *  DataTypeConversion: '<Root>/Data Type Conversion1'
   */
  LPF_Y.Out1 = tmp < 0.0 ? (uint16_T)-(int16_T)(uint16_T)-tmp : (uint16_T)tmp;

  /* Update for UnitDelay: '<S1>/Unit Delay' */
  LPF_DW.UnitDelay_DSTATE = rtb_Add1;
}
2. Proteus硬件连接

2.1 带噪声的正弦信号发生器

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第10张

由于Proteus中没有直接产生白噪声的元件,在这里采用基于EPROM的波形发生方式。首先采用外部函数将白噪声数据写入txt文件,在转换为二进制数据加载到27256中,得到噪声信号。

比如我采用R语言生成这些数据,R代码如下。

#生成波形数据部分
noise<-rnorm(500,mean=36*3.5,sd=36)
noise<-round(noise)
noise_H<-as.character(as.hexmode(noise))
#写入文件部分
write.table(noise_H,file='C:/Users/lenovo/Desktop/noise_H.txt', row.names =FALSE,col.names =FALSE, quote =FALSE)

由于正态分布在3倍标准差范围内的概率已经达到99.74%,因此此处选3.5足够。得到数据文件如下:

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第11张

利用从网上下载的转换工具进行转换:(感谢这位博主)

https://download.csdn.net/download/mouseleoz/10905646

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第12张

即得到可加载的bin文件。

555定时器产生周期性信号,74LS161构成16进制计数器,噪声数据即在27256的D0到D7端口输出。

2.2 A/D转换

将上面的输入信号封装为子电路图,总电路图如下。

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第13张

利用11通道12位串行A/D转换芯片TLC2543进行A/D转换,TLC2543引脚说明如下。

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第14张

AIN0~AIN10为模拟输入通道。
CS为片选端,低电平有效。
DATA INPUT为串行数据输入端。
DATA OUT为A/D转换结果的三态串行输出端。
EOC为转换结束端。
I/O CLK为I/O时钟端。
REF+为正基准电压端。
REF-为负基准电压端。
VCC为电源端。
GND为地。

2.3 D/A转换

利用DAC0832进行D/A转化,由于0832是8位D/A转换器,因此损失了部分精度。

DAC0832引脚功能说明:
Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第15张
DI0~DI7:数据输入线,TTL电平。
ILE:数据锁存允许控制信号输入线,高电平有效。
CS:片选信号输入线,低电平有效。
WR1:为输入寄存器的写选通信号。
XFER:数据传送控制信号输入线,低电平有效。
WR2:为DAC寄存器写选通输入线。
Iout1:电流输出线。当输入全为1时Iout1最大。
Iout2: 电流输出线。其值与Iout1之和为一常数。
Rfb:反馈信号输入线,芯片内部有反馈电阻。
Vcc:电源输入线 (+5v~+15v)。
Vref:基准电压输入线 (-10v~+10v)。
AGND:模拟地,摸拟信号和基准电源的参考地。
DGND:数字地,两种地线在基准电源处共地比较好。
3. Keil工程

3.1 main函数

#include<reg52.h>
#include "LPF.h"
#include "LPF_private.h"
#define uint unsigned int
#define uchar unsigned char
#define y P2
uint volt; 
uchar addr;
sbit CLK=P1^7;//定义时钟信号口
sbit DIN=P1^6;//定义2543数据写入口
sbit DOUT=P1^5;//定义2543数据读取口
sbit CS=P1^4;//定义2543片选信号口
sbit P2_5=P2^5;

void read2543(uchar addr)
{
    uint ad=0;
    uchar i;
    CLK=0;
    CS=0;//片选段,启动2543
    addr<<=4;//对地址位预处理
    for(i=0;i<12;i++) //12个时钟走完,完成一次读取测量
    {
        if(DOUT==1)
            ad=ad|0x01;//单片机读取ad数据
        DIN=addr&0x80;//2543读取测量地址位
        CLK=1;
        ;;;//很短的延时
        CLK=0;//产生下降沿,产生时钟信号
        ;;;
        addr<<=1;
        ad<<=1;//将数据移位准备下一位的读写
    }
    CS=1;//关2543
    ad>>=1;
    volt=ad;//取走转换结果
    }

void main()
{
    addr=0;
    LPF_initialize();
    TMOD=0x01;
    TH0=0xD8;
    TL0=0xF0;
    TR0=1;
    EA=1;
    ET0=1;
    while(1)
    {
        read2543(addr);
    }
}
void Timer0_ISR(void) interrupt 1
{
    TH0=0xD8;
    TL0=0xF0;
    LPF_U.In1=volt;
    LPF_step();
    y=LPF_Y.Out1/16;
    
}

在while(1)中不断读取A/D转换结果,在定时器中固定步长执行LPF_step函数。定时器初值D8F0=55536=2^12-10000,故步长为0.01s。

由于读取的转换结果是12位数据,因此除以16转换为8位,同时损失了精度。

3.2 编译方法

将Simulink生成的.c和.h文件加入到工程下,启动编译。

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第16张

编译无误即可得到hex文件,将其加载到单片机中,启动仿真,得到示波器结果如下所示。

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第17张

可以看到,该电路完成了滤波任务。

4. 模型评价总结

该实例仅是为了练习Simulink生成代码的过程,实际效果并不理想,主要缺点有:

  • 中间经过A/D和D/A转换,损失了精度,得到的结果是离散的;
  • 算法导致输出比输入有一定的相位滞后。

Simulink仿真入门到精通(十九) 总结回顾&amp;自我练习第18张

如图,放大后即可看到其离散性,实际效果甚至不如一阶RC滤波器(有源或无源)。

在这个过程中对Proteus的总线创建、标号添加及子电路图绘制方法进行了回顾。

对C51的端口赋值方法进行了复习,#define y P2。

在建模过程中参考了以下网页,对这些博主表示感谢。

Simulink生成代码在C51中的用法:https://blog.csdn.net/weixin_41911709/article/details/90648818

TLC2543的用法:https://blog.csdn.net/nanfeibuyi/article/details/80564741

通过此练习,起码简单验证了Simulink生成C代码的可行性,其他学习有待以后深入。

总之,本书由浅入深,还是非常值得一读,错误也比较少,即使偶尔有拼写错误也不影响阅读。

我的模型文件打包如下:

链接:https://pan.baidu.com/s/1iedYzuQbcezU4_-fW2s6tw
提取码:k3fj

免责声明:文章转载自《Simulink仿真入门到精通(十九) 总结回顾&amp;amp;自我练习》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇delphiDeepin/UOS/debian/Ubuntu/Linux下搭建pyqt5开发环境—基于Pycharm下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Vue(一)

一、es6语法:let和const es6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。 上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效 for循环...

利用Javascript获取当前日期的农历日期

来源:http://www.ido321.com/926.html JavaScript代码 1: /*设置农历日期*/ 2: var CalendarData=new Array(100); 3: var madd=new Array(12); 4: var numString="一二三四五六七八九十"; 5: var...

Simulink仿真入门到精通(五) Simulink模型的仿真

5.1 模型的配置仿真 由各种模块所构建的可视化逻辑连接,只是模型的外在表现,模型仿真的核心驱动器是被称作解算器(Solver)的组件,相当于Simulink仿真过程的心脏,驱动着模型仿真,它在每一个采样时间点更新模型中所有的状态和信号变量,并计算下一步的步长。除此之外,模型还具有一个参数配置集合(Configuration Parameter Set),...

模拟器上安装 Frida (Frida +FRIDA-DEXDump联动)

1.模拟器安装drozer和相关adb 。看上文。 https://www.cnblogs.com/pangya/p/10062860.html 把adb添加到环境变量。 2.模拟器上安卓Firda-server 1.确定模拟器版本,使用adb adb shell getprop ro.product.cpu.abi --查看版本 2.下载frid...

tar命令结合find搜索将指定条件的文件进行打包压缩

今天处理 /tmp 临时目录下 session 文件过多的问题,顺便找到了这个 tar 结合 find 打包压缩的方法,记录下来,很实用的哈! 搜索 /tmp 目录下 创建超过 24 分钟的文件 find /tmp -cmin +24 分两步: 1、将按照自己条件搜索出来的文件名写入到一个文件 tmp.list 中 find /tmp -cmin +24...

Centos7基本命令

shell基本命令 linux命令行的组成结构 linux系统命令操作语法格式 命令 空格 参数 空格 文件路径或者需要处理的内容 rm -rf /tmp/* ls -la /home 1.一般情况下,【参数】是可选的,一些情况下【文件路径】也是可选的 2.参数》同一个命令,跟上不同的参数执行不同的功能...