Simulink代码生成: 基本数据类型

1 引言

正如C语言中为变量区分了不同的数据类型一样,Simulink中也有不同的数据类型,并且与C语言数据类型关系紧密。本文研究Simulink中的基本数据类型的用法和一些相关的配置。

2 Simulink中的基本数据类型

在Simulink中,基本数据类型分为浮点类型、整数类型和布尔类型,具体有以下几种。

数据类型名称含义存储大小范围
double双精度浮点型4字节-1.7E-308~1.7E+308
single单精度浮点型8字节1.2E-38 ~ 3.4E+38
int8有符号 8 位整数1字节-128 ~ 127
uint8无符号 8 位整数1字节0 ~ 255
int16有符号 16 位整数2字节-32,768 ~ 32,767
uint16无符号 16 位整数2字节0 ~ 65,535
int32有符号 32 位整数4字节-2,147,483,648 ~ 2,147,483,647
uint32无符号 32 位整数4字节0 ~ 4,294,967,295
boolean布尔类型1字节0~1

后文会举例说明不同类型的使用方法及一些注意点。

3 数据类型实例

3.1 浮点类型

浮点类型就是具有浮动小数点的数据类型,用于表示小数。
首先,通过下面的Simulink建模示例,可以清楚地了解浮点类型的用法。

1)新建一个Simulink模型<Data_Type_Basics.slx>,在模型中搭建以下简单模块;
在这里插入图片描述
2)分别双击Inport1和Inport2,打开配置界面,将Data type分别配置为single和double;

在这里插入图片描述

3)分别双击Gain模块,并对应配置DataType为single和double;

在这里插入图片描述
4)在Debug工具栏中点击Base Data Types,可以在信号线上显示数据类型;

在这里插入图片描述

完成后Ctrl + D更新模型,就可以看到信号线上的数据类型分别是single和double。

在这里插入图片描述
在模型中配置浮点数的方法如上文所示。接着,通过将模型生成代码,可以在C语言的层面上进一步理解Simulink中的浮点类型,以及和C语言中浮点类型的关系。

1)生成代码前,先配置好Embedded Coder,并且Ctrl + B生成代码;

在这里插入图片描述
在<Data_Type_Basics.h>头文件中可以看到Inport1和Inport2的类型是real32_T和real_T。

2)接着打开<rtw_types.h>头文件;

在这里插入图片描述
在该文件中通过typedef关键字将real32_T和real_T分别定义为C语言的基础类型float和double,也就是单精度和双精度浮点型数。这种做法在C语言中很常见,是为了不直接使用C语言中的基础类型,而是在新的名称中可以直观地看出该类型所占的字节数。

这些被定义好的新的类型名称,也是在Simulink中可以配置的,具体参照下图。

在这里插入图片描述

3.2 整数类型

整数类型用于表示整数,和浮点类型在代码生成方面类似,都是通过typedef定义一个新的类型名称,再以此去定义变量名。

类似浮点类型的建模,建模时将Inport中的Data type 选中成整型。在生成代码的形式方面,整数类型和浮点类型除类型定义外,没有差别,这里不再赘述。

3.3 布尔类型

布尔类型用于表示“真”或“假”,常用于条件判断或者逻辑运算中。首先,通过下面的Simulink建模示例,可以清楚地了解布尔类型的用法。

1)将Inport1和Inport2配置成single类型,并且通过一个关系运算符(小于等于)来输出判断结果,如果Inport1 < Inport2,则输出True,否则输出False;

在这里插入图片描述

2)配置好显示端口数据类型,然后Ctrl + D更新模型,就可以看到关系运算符输出的信号为boolean,即布尔类型;

在这里插入图片描述

同理,逻辑运算符的输入输出都是boolean类型,进行与、或、非等逻辑运算。

3)生成代码前,先配置好Embedded Coder,并且Ctrl + B生成代码;

在这里插入图片描述
在这里插入图片描述

在生成的<Data_Type_Basics_Bool.h>文件中,Outport的类型为boolean_T。在 rtwtypes.h文件中可以看到通过typedef关键字将unsigned char类型定义为boolean_T,也就是说boolean_T的背后是无符号 8 位整数,和uint8_T是一样的。

3 数据类型使用的注意点

3.1 浮点数等于比较

两个浮点数可以通过比较运算模块,输出true或者false的布尔值。但是在建模的过程中,不可以使用 == 比较运算符来比较两个浮点数相等。即如下情况。
在这里插入图片描述
因为计算机在进行浮点数运算的时候会产生精度损失,所以两个浮点类型变量在小数点后的很多位就可能看不一样的,从现实物理意义上来说,基本可以等同一致,但是 == 运算符会判定为不一样,就产生了相反的效果。

在Model Advisor中的Check comparison of floating point types in Simulink项可以检查出模型中进行浮点数等于比较的错误。

在这里插入图片描述
建模中判断浮点数相等的正确做法应该是,两个浮点数的差值的绝对值,小于一个定义好的误差量,例如0.00001.

在这里插入图片描述

3.2 整形数溢出

由于浮点类型可表示的范围很大,所以一般不需要考虑数值溢出的问题。但是整数类型必须很清楚该类型所对应的范围是否满足信号的需要。例如int8类型可以表示-128~127的整数,但是超出该范围就会溢出,造成了数值的错误。

新建一个模型<Data_Type_Basics_IntOverflow.slx>,如图所示,输入的数值是80,乘以二之后超出了int8类型可以表示的范围。如果将Diagnostics中的Wrap on overflow选配置为error,那么Ctrl + T运行模型仿真时就会检测到溢出而报错。
在这里插入图片描述
如果将Wrap on overflow选配置为warning再Ctrl + T运行模型仿真,就会输出-96的错误值。

在这里插入图片描述
这里需要注意,仅通过Ctrl + D更新模型是不会报错的,或者输入输出为Inport或者Outport模块时也不会报错。必须首先配置好模型诊断项,以及使用导致溢出的数值输入后,通过Ctrl + T进行仿真后,Simulink才会报错。因此,测试用例需要能够覆盖这种情况。

3.3 布尔类型的位域

布尔类型只需要一个比特就可以存储0和1两种状态,但是C语言最小的整数数据类型是char,也就是一个字节,占据8个比特,这样造成了控制器内存资源的浪费。一种解决方法是把布尔量打包成位域。

通过下面的Simulink示例,可以清楚地了解布尔类型打包成位域的方法。

1)首先,建立一个Matlab脚本<Bitfield_Parameter.m>,输入如下脚本并运行,用于创建Bool_Param_1和Bool_Param_2两个参数;

Bool_Param_1 = Simulink.Parameter;
Bool_Param_1.Value = 0;
Bool_Param_1.CoderInfo.StorageClass = 'Custom';
Bool_Param_1.CoderInfo.Alias = '';
Bool_Param_1.CoderInfo.Alignment = -1;
Bool_Param_1.CoderInfo.CustomStorageClass = 'BitField';
Bool_Param_1.CoderInfo.CustomAttributes.StructName = '';
Bool_Param_1.Description = '';
Bool_Param_1.DataType = 'boolean';
Bool_Param_1.Min = [];
Bool_Param_1.Max = [];
Bool_Param_1.DocUnits = '';

Bool_Param_2 = Simulink.Parameter;
Bool_Param_2.Value = 1;
Bool_Param_2.CoderInfo.StorageClass = 'Custom';
Bool_Param_2.CoderInfo.Alias = '';
Bool_Param_2.CoderInfo.Alignment = -1;
Bool_Param_2.CoderInfo.CustomStorageClass = 'BitField';
Bool_Param_2.CoderInfo.CustomAttributes.StructName = '';
Bool_Param_2.Description = '';
Bool_Param_2.DataType = 'boolean';
Bool_Param_2.Min = [];
Bool_Param_2.Max = [];
Bool_Param_2.DocUnits = '';

这里注意,CustomStorageClass配置成了BitField。

2)运行脚本<Bitfield_Parameter.m>,在Matlab工作空间中生成两个Parameter参数;

在这里插入图片描述

3)接着在Simulink中建模如下,包含两个Const模块和两个Outport模块,Const模块中的值引用工作空间中的两个参数,直接输出给Outport模块;

在这里插入图片描述
4)在Simulink的配置界面中,勾选上Pack Boolean data into bitfields,并将
Bitfield declarator type specifier选择位uchar_T;

在这里插入图片描述
这里的选择表示将Boolean类型的数据打包到位域中,并且共享一个uint_T的类型。

5)保存模型后,先配置好Embedded Coder,Ctrl + B生成代码;

在这里插入图片描述

在<Data_Type_Basics_Bitfield.h>头文件中,将两个参数定义到一个结构体内,并且后面带了个冒号和数字1。这代表这两个参数共用一个类型uint_T,并且分别只占了这个类型的1个比特。位域就是通过这种共享类型的方式,节省了控制器的内存资源。

4 关于定点数的说明

在早期的模型开发中,常用定点数表示浮点数。定点数的类型配置如下图所示。

在这里插入图片描述
定点数就是把小数点固定下来,来表示浮点数。这样做的目的时牺牲一定的小数精度,来换取内存资源空间的节省。

简单举个例子,通过1个字节,也就是8个比特的内存空间表示小数,假如小数点固定在从右往左第三位,如图所示。

在这里插入图片描述
整数部分分配到5个比特,也就是整数最大能表示2^5 - 1,即十进制的31。小数部分分配到3个比特,也就是可以把数字1等分成8份,每份是0.125。这样的话小数可以表示的精度就是0.125。也就是说,小数只能是0.0,0.125,0.25,0.375,0.5,0.625,0.75,0.875这几种。0.125和0.25之间的小数值无法表示,因为精度不够。想要表达更精准的小数,就要把小数点往左移,但是这样的话整数的最大值又减小了。因此定点数需要按照需求去一个平衡。

由于集成电路的发展,现在的嵌入式芯片已经有了充足的资源和空间,以及浮点运算单元。不再需要旧时代的定点化的操作,笔者在工作的时候已经没有再见过定点化相关的技术了。

5 总结

本文研究了Simulink中的浮点型(double、single)、整型(int8、uint8等)和布尔型数据类型。建模时需注意浮点数比较的精度、整数溢出问题以及布尔类型的位域优化,以提升模型效率和可靠性。

返回个人博客总目录

  • 23
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值