为了方便大家阅读,从这章开始在章节名中添加该章节要讲的主要的东西。
本章给大家讲一个最简单的Simulink模型:
在处理应用逻辑时常常会判断车速信号来得到车是否静止,如果车已经跑起来了,很多功能都会被禁用,比如诊断,开关门等。
![725e07db30855a1725f1d6aa95ca704b.png](https://i-blog.csdnimg.cn/blog_migrate/0cb0b74aee5c0c71deaa1445e9493377.png)
以上模型就是一个最简单的车速判断逻辑,int16型数据VehicleSpeed(单位km/h)先得到其绝对值然后再和Constant数3做比较,如果绝对车速大于等于3km/h那么车是Driving状态。如果小于3km/h那么车即可认定为静止状态。
我们来生成以下代码,看看代码是怎么样的:
点击APP下的Embedded Coder,
![ddeda6cb913ef7b170602c13ba4f2095.png](https://i-blog.csdnimg.cn/blog_migrate/815bee63dab0b48bb17e71f7a9b5be4a.png)
点击Quick Start,
![928b06c8704a55c32d215129e28d621d.png](https://i-blog.csdnimg.cn/blog_migrate/71c2d1b00984aaf81a9ff2363a8a83f7.jpeg)
点击next,
![268902b62f1b9200a861bc7359052cbe.png](https://i-blog.csdnimg.cn/blog_migrate/10ba5b2e4843909486397290c470deec.jpeg)
这里可以选择整个Model或者选择Model下的某一个子系统,这里直接选择整个Model,点击next,
![5b90a431bbcf05b7abe0712f8ed2f9a2.png](https://i-blog.csdnimg.cn/blog_migrate/b5f5e722dd6689eacd596faeb3c84260.jpeg)
当前只是看下基本代码,直接选择C Code 和 单Instance(Instance及autosar相关的选项都是AUTOSAR下相关的属性及配置,后续会有基于AUTOSAR下模型开发的文章)。点击next,
![0a7e0c1f58ce22ab7ee76daacadd1957.png](https://i-blog.csdnimg.cn/blog_migrate/b449c4701a36216d7b0e90bc113f1d70.jpeg)
点击next,
![3e3085850e88cedbfba2682a40c987a5.png](https://i-blog.csdnimg.cn/blog_migrate/ba8f6a8b3d0b1dbc0390d4717d80f546.jpeg)
这里选择一些基本类型的内存长度,直接选择默认的,点击next,
![35250d3734812b0c95798c1dc628749b.png](https://i-blog.csdnimg.cn/blog_migrate/29877877752188d3da1f04d4f2249baf.jpeg)
这里是选择执行最快或者RAM最少,为了让逻辑看起来更明了,选择执行最快,点击next,
![f86929d4f0b2fe0a2d3912916aea9a1c.png](https://i-blog.csdnimg.cn/blog_migrate/9a31ac2ea3851c7da54140eaaefa08c9.jpeg)
直接点击next,
![230a16aa32d1a98b63d04fa163578d33.png](https://i-blog.csdnimg.cn/blog_migrate/e3bb7bf4e2cf3e14cfd1aeeebd2de2bc.jpeg)
点击finish,
回到Simulink,
![9f5c201e1d1201cdef9b0fe659af379d.png](https://i-blog.csdnimg.cn/blog_migrate/da6df534b7887278e9bef769ddc3c888.jpeg)
点击build,
代码就生成了,
![bccebdadb73e23d2b6549ca891f51b9d.png](https://i-blog.csdnimg.cn/blog_migrate/801cd5759f75a5a2677854d7528e7b72.png)
生成了上图的四个.c,.h文件
进入Demo.h
typedef struct {
int16_T VehicleSpeed; /* '<Root>/VehicleSpeed' */
} ExtU;
/* External outputs (root outports fed by signals with default storage) */
typedef struct {
boolean_T VehicleIsDriving; /* '<Root>/VehicleIsDriving' */
} ExtY;
/* External inputs (root inport signals with default storage) */
extern ExtU rtU;
/* External outputs (root outports fed by signals with default storage) */
extern ExtY rtY;
/* Model entry point functions */
extern void Demo_initialize(void);
extern void Demo_step(void);
可以看到,Embedded Coder将模型的输入做了一个结构体,对输出也做了一个结构体,这样出来的代码结构比较清晰,在代码debug的过程中会很方便地跟踪这些变量。同时生成了Demo_initialize(void)和Demo_step(void)两个函数,这两个函数在嵌入式RTOS系统用中是很重要的函数,每个SWC(Software component)都必须有这两个函数,Demo_initialize(void)一般用在系统startup时,Demo_step(void)会被assign到一个固定的task中周期执行。
再看下Demo.c
#include "Demo.h"
/* External inputs (root inport signals with default storage) */
ExtU rtU;
/* External outputs (root outports fed by signals with default storage) */
ExtY rtY;
/* Model step function */
void Demo_step(void)
{
int16_T tmp;
/* Abs: '<Root>/Abs' incorporates:
* Inport: '<Root>/VehicleSpeed'
*/
if (rtU.VehicleSpeed < 0) {
tmp = (int16_T)-rtU.VehicleSpeed;
} else {
tmp = rtU.VehicleSpeed;
}
/* End of Abs: '<Root>/Abs' */
/* Outport: '<Root>/VehicleIsDriving' incorporates:
* RelationalOperator: '<Root>/Relational Operator'
*/
rtY.VehicleIsDriving = (tmp >= 3);
}
/* Model initialize function */
void Demo_initialize(void)
{
/* (no initialization code required) */
}
代码中可以清楚地看出,其先用了一个temp得到VehicleSpeed的绝对值,然后在和3做比较并输出给VehicleIsDriving
打开rtwtype.h
/*=======================================================================*
* Fixed width word size data types: *
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
*=======================================================================*/
typedef signed char int8_T;
typedef unsigned char uint8_T;
typedef short int16_T;
typedef unsigned short uint16_T;
typedef int int32_T;
typedef unsigned int uint32_T;
typedef long long int64_T;
typedef unsigned long long uint64_T;
/*===========================================================================*
* Generic type definitions: boolean_T, char_T, byte_T, int_T, uint_T, *
* ulong_T, ulonglong_T. *
*===========================================================================*/
typedef unsigned char boolean_T;
typedef int int_T;
typedef unsigned int uint_T;
typedef unsigned long ulong_T;
typedef unsigned long long ulonglong_T;
typedef char char_T;
typedef unsigned char uchar_T;
typedef char_T byte_T;
rtwtype.h是simulink的Realtime Workshop的type定义,提供给各个SWC.h做基本类型引用。在嵌入式系统中,每个SWC在代码生成是都会生成一个rtwtype.h,最终只包含一个大家通用就行了。
最后ert_main.c(Embedded realtime target)没什么用,其只为生成一个示例去调用Demo_initialize(void)和Demostep(void)两个函数,在实际的实时嵌入式系统中,我们会将swc.c, swc.h加入工程中,用系统中提供的task_init(), task_xxms()来调用这两个函数。当然大家也可以将ert_mian.c及swc.c swc.h rtwtype.h加入visual studio工程中进行验证(不过用处不是很大,仅限学习使用)。
以上便是simulink基本模块的搭建以及Embedded coder的基本使用相关的内容,需要提的是不同的simulink版本在simulink的搭建方面是一样的,但是其Embedded coder变化较大,本文在是基于R2020a版本的Embedded coder讲解的,大家在生成代码过程中有什么问题可以自行百度。