基于Simulink模型的嵌入式代码生成与实际工程应用
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、工程创建
- 二、代码生成
- 1.搭建模块
- 2.设置参数
- 3.自动生成
- 三、代码整合
- 总结
前言
在嵌入式开发中,利用Simulink的相关功能模块搭建逻辑流程以后,一个非常重要的步骤就是利用代码生成功能将我们搭建的功能转化为代码,并且和嵌入式平台的芯片软件工程融合,使我们开发的功能在单片机上跑起来,从而实现产品的功能要求。
一、工程创建
这次使用Simulink搭建的工程的目标产品是车载智能保险盒,前两篇文章中的CAN模块、雨刮模块等都是其中的功能,这些功能组装起来通过一个完整的simulink project进行管理。以功能为文件夹,把相关的功能文件进行统一归类。我的理解这样创建的工程类似于代码编辑时在编译器中创建的工程。
就像KEIL或者IAR中可以进行编译,运行操作一样,simulink项目也可以进行model test、依存关系查看、运行检查等操作。版本管理也集成了SVN或git,只需要进行简单的设置也可以实现。我用的就是SVN进行版本管理,但是习惯上还是直接拷贝文件夹进行update和commit。
二、代码生成
1.搭建模块
生成代码每个模块的操作是一样的,设置参数和操作。本文采用近光灯模块进行解释,主要因为近光模块功能比较简单。信号量较少,且逻辑简单。主要信号如下:
输入信号:
1、点火开关IGN信号
2、大灯供电信号
3、近光灯开关信号
4、短路判断信号
5、开路判断信号
6、报文刷新标志
输出信号:
1、近光灯继电器的控制信号
2、CAN报文信号
3、报文发送标志位
其中报文刷新标志和报文发送标志是系统内部的判断信号,不作为对外的输出,相当于写代码时设置的标志位是一个局部变量。
工能逻辑结构如下:
一 整体结构
二 内部结构
三 stateflow
功能搭建完成以后,点击RUN图标,若未报错证明语法上结构正确是符合了生成代码的前提条件,至于控制逻辑是否正确可以通过dashboard搭建指示灯进行仿真,仿真的方法可参考前文《Simulink模型实现汽车雨刮基本功能并仿真》。
2.设置参数
点击工具栏上面model setting的齿轮图标,进入设置参数界面
以本项目生成嵌入式代码为例,主要需要调节的参数设置如下:
solver解算器下,Solever selection解算器选择,type选fixed-step(定步长),solver选discrete(离散型)
细节选项fixed-step size设置为0.01,采样步长为0.01s,这个参数关系到在嵌入式工程中多久调用一次功能循环,以本项目为例,设置为0.01s也就意味着,每10ms调用一次功能函数,要是不按照设定值进行定时中断,那么会影响模块中的计时操作。
code generation选项中主要需要注意的是两个参数,一个是System target file要选为ert.tlc,另一个就是Language要选C语言。
Report选项中选择生成代码报告,一般勾选前两项分别是生成报告和自动打开,第三个web view可选可不选。
根据所用单片机型号我们要在Hardware Implementation中选择相对应的单片机厂商和内核类型,本项目所用的是NXP,cortexM4内核S32k148芯片,选择相应选项。这里选择不像Keil这类编译器那么详细,主要作用就是确定单片机一些数据类型定义的位数,以及是否支持长整型等,点开detail可以看到详细。
3.自动生成
在完成以上步骤以后,就可以进行生成代码操作了。首选在APP选项中选择embedded coder功能卡,如下:
选择以后进入embedded coder APP
点击Build按钮,生成嵌入式C代码
代码生成以后会自动出现在右侧,方便我们查看。
因为我们勾选了生成Report选项,所以还会出现一个报告对话框,在报告里面可以查看本模块生成代码的相关内容,包括代码预览,模型信息,占用内存多少等信息。
我们在生成的代码中可以看到很多文件,但又用的主要就是功能相关的 LowBeam.c 和 LowBeam.h 这两个文件,其他的文件除了ert_main以外的可以不用管,直接拷贝放到我们自己的代码工程目录下。ert_main不用,我们用自己的main函数,不过可以参考ert_main中对功能函数的调用方法。
三、代码整合
按照上述的方法自动生成了代码以后,离成功使用还有最后一步操作,那就是将这些文件添加到工程并且与驱动代码相配合。针对这款芯片,其他同事已经进行了平台化的开发,提供了相关的接口,包括ADC、GPIO、CAN等资源都已经进行了封装,我们所需要做的就是接口对应。还是以本近光灯功能模块为例,LowBeam.c文件,几乎可以不用去管,那是Matlab软件根据我们搭建的Simulink逻辑自动生成的代码,可读性不是很强,但功能肯定是实现的。我们进行接口对应,关注LowBeam.h文件就好。
在.h文件中找到如下代码:
/* External inputs (root inport signals with default storage) */
typedef struct {IGN IG; /* '<Root>/IGN' */uint8_T Front_Power_Supply; /* '<Root>/Front_Power_Supply' */uint8_T Work_Cmd; /* '<Root>/Work_Cmd' */uint8_T IS_Opencircuit; /* '<Root>/DILAMP_Open' */uint8_T IS_Shortcircuit; /* '<Root>/DILAMP_Short' */uint8_T New_Can_Flag; /* '<Root>/New_Can_Flag' */
} ExtU_LowBeam_T;/* External outputs (root outports fed by signals with default storage) */
typedef struct {uint8_T Low_Beam_On; /* '<Root>/Low_Beam_On' */uint8_T Can_Send_Flag; /* '<Root>/Can_Send_Flag' */CAN_MESSAGE_BUS CAN_Msg_HighBeam; /* '<Root>/CAN_Msg_HighBeam' */
} ExtY_LowBeam_T;
ExtU_LowBeam_T代表输入信号的结构体;ExtY_LowBeam_T代表输出信号的结构体。都是以全局变量的形式进行赋值。
我们自己写一个赋值函数:
/*近光灯模块*/LowBeam_U.New_Can_Flag = (uint8_T)can_status_store.bit.store_Newflag_LowBeam;LowBeam_U.Front_Power_Supply = (FrontLampTogether_Y.Left_Together_ON & FrontLampTogether_Y.Right_Together_ON);LowBeam_U.Work_Cmd = CAN_Receive_Model_Y.LowBeam_WorkCmd;LowBeam_U.IG = CAN_Receive_Model_Y.IGN_Sig;LowBeam_U.IS_Opencircuit = (Output_Current_U.DILamp_FL_DRV < LOWBEAM_CURRENT_MIN) || (Output_Current_U.DILamp_FR_DRV < LOWBEAM_CURRENT_MIN) ? 1: 0;LowBeam_U.IS_Shortcircuit = (Output_Current_U.DILamp_FL_DRV > LOWBEAM_CURRENT_MAX) ||(Output_Current_U.DILamp_FR_DRV > LOWBEAM_CURRENT_MAX) ? 1: 0;
其中涉及到其他模块的一些信号,但这些都是独立的全局变量,可以直接拿来进行逻辑判断。
输出信号:
if(LowBeam_Y.Low_Beam_On == 1){HSD_SET_LEFT_LOWBEAM_ON; //打开左近光灯HSD_SET_RIGHT_LOWBEAM_ON; //打开又近光灯} else{HSD_SET_LEFT_LOWBEAM_OFF; //关闭左近光灯HSD_SET_RIGHT_LOWBEAM_OFF; //关闭右近光灯}
对输出函数进行了封装,这里直接调用即可。
针对总线信号,写一个赋值函数:
void set_can_LowBeam_output(void)
{if(LowBeam_Y.Can_Send_Flag){if(can_send_output_set(CAN_INSTANCE_SET, &LowBeam_Y.CAN_Msg_HighBeam) == CAN_EOK) //发送报文{LowBeam_Y.Can_Send_Flag = 0;}}
}
这里直接用了can_send_output_set()这个发送报文用的接口函数。
最后是在main函数中调用功能函数,我们在生成的LowBeam.h文件中可以看到三个函数申明:
/* Model entry point functions */
extern void LowBeam_initialize(void);
extern void LowBeam_step(void);
extern void LowBeam_terminate(void);
实际我们需要用到的只有LowBeam_step(void)这个函数,在main函数的主循环中每10ms调用一次该函数即可:
if(Get1MsTickInterval(modeldely) >= 10)
{ modeldely = Get1MsTickVal(); LowBeam_step(); //近光灯
}
其他的功能模块都可以按照这样的方法把_step函数添加在近光灯函数的下面。
总结
以上就是今天要讲的内容,本文简单介绍了通过Simulink搭建的逻辑框图如何生成嵌入式代码,并且将生成的代码添加到已有的单片机工程中实现近光灯模块的功能。
当然,自动代码生成在工程的调用需要多一层封装,占用了一定的资源。且对于一些业务熟练的工程师来说,一些简单的逻辑手写可以用很精简的C代码量实现同样的功能。不过,我们采用自动代码生成技术也有相应的好处,比如在功能逻辑较为复杂时可以更清楚的理清思路,而且simulink可方便的进行功能仿真,验证功能步骤可以放在生成代码之前,而手写代码则必须在编译通过以后烧录到样件中利用硬件设备进行功能测试。这样一来,自动利用simulink进行功能仿真和代码自动生成,就省去了反复的烧录过程。
当然,simulink的代码生成功能远不止本文所提到的部分,笔者还会在项目中探索,在以后的文章中和大家进一步探讨。
基于Simulink模型的嵌入式代码生成与实际工程应用相关推荐
- 感应电机转速自适应观测器基于simulink模型仿真
感应电机转速自适应观测器基于simulink模型仿真 矢量控制,电机建模等资料 ID:69160657503527528
- 基于Matlab Simulink开发的嵌入式模型,模型可自动生成ccs工程代码,生成的代码可直接运行在主控芯片中
主控芯片dsp tms320f28335,基于Matlab Simulink开发的嵌入式模型,模型可自动生成ccs工程代码,生成的代码可直接运行在主控芯片中. 该模型利用id=0的矢量控制,实现了永磁 ...
- 【Simulink专题】Simulink模型设置(三):代码生成
前言 Simulink中模型设置是关乎着整个模型的运行模式以及代码生成样式,不同的设置关乎着不同的结果,今天就给大家讲解下作者对整个模型设置的理解,有疑问的地方还需要大家多多指出,谢谢 使用版本:MA ...
- 一文弄通STM32F103基于simulink自动代码生成CAN/USART/GPIO/TIM(stm32cubemx+stm32target+matlab2018b)
一文弄通STM32F103基于simulink自动代码生成CAN/USART/GPIO/TIM(stm32cubemx+stm32target+matlab2018b) 写在前面 1.stm32cub ...
- 基于模型的嵌入式开发流程_如何使用基于模型的测试来改善工作流程
基于模型的嵌入式开发流程 Unit testing is not enough – so let's start using model-based testing to improve our wo ...
- 基于simulink的FCV燃料电池电动汽车模型。 包含3个汽车模型,双输入DCDC模型
基于simulink的FCV燃料电池电动汽车模型. 包含3个汽车模型,双输入DCDC模型,电池管理系统模型. 模型建模清晰,运行良好,部分内容如截图所示. 需要matlab2015b ID:88296 ...
- 风力发电仿真系列-基于Simulink搭建的双馈风力发电(DFIG)模型
基于Simulink搭建的双馈风力发电(DFIG)模型 1.双馈风力发电机 双馈异步风力发电机(DFIG)是一种绕线式感应发电机,是变速恒频风力发电机组的核心部分.DFIG主要由两大部分组成,分别 ...
- 基于simulink的路面附着系数估计模型, 滑转率零斜率法
出 基于simulink的路面附着系数估计模型, 滑转率零斜率法 ID:8634645145422904是命a
- 基于simulink的拓展卡尔曼滤波估计路面附着系数识别EKF,内含道夫轮胎模型
基于simulink的拓展卡尔曼滤波估计路面附着系数识别EKF,内含道夫轮胎模型,七自由度整车仿真模型,输出结果收敛,如下图,并可以在多种附着系数工况下收敛识别,验证模型合理性. ID:6914966 ...
- 【SIMULINK】全网最牛逼自制感应电机simulink模型,基于原始方程
[SIMULINK]全网最牛逼自制感应电机simulink模型,基于原始方程 可以直接使用开路实验与短路实验测得的参数,经过脚本换算得动态参数输入模型 动态模型 参数与计算部分 模型内部 电压与磁链方 ...
最新文章
- SUSE LINUX配置ORACLE命令
- Gradle -- buildScript块与allprojects块及根级别的repositories区别
- Mysql日期时间Extract函数介绍
- Image打包流程-Android10.0编译系统(四)
- 面向侧面的程序设计AOP-------《二》本质
- Protobuf序列化的原理-负数的存储
- 如何在string.Format方法中输出大括号({})
- c++学习书籍推荐《超越C++标准库:Boost库导论》下载
- 作者:潘柱廷(1969-),男,启明星辰教授级高级工程师、首席战略官。
- react-native ListView 封装 实现 下拉刷新/上拉加载更多
- 修复Winsock(转)
- Android仿IOS有弹性ScrollView
- matlab 谐振电路图,rlc串联电路谐振特性图分享
- 小功率太阳能UPS锂电池传感器供电系统套件充电宝不间断电源 5V12V户外监控
- linux poodle漏洞,Claws Mail 3.11.0发布 修复了POODLE 漏洞
- SaaS行业的六大安全问题
- ISD9160学习笔记01_大联大Nuvoton ISD9160语音识别开发板初体验
- licode的ios最新版本的接入
- ipv6联网几十分钟后显示无网络连接,v4网络正常的解决方法
- 「绝影」出没上海车展,约上30+车企一块「商量」
热门文章
- 亮点前瞻 | 首届 ServerlesssDays · China 大会议程发布
- 【C语言】通讯录管理系统
- 0527基于51单片机的防酒驾检测系统设计Proteus仿真
- 5分绩点转4分_泪目!老詹儿子凌晨5点起身训练,科比女儿4点,魔术师叹息退出群聊...
- WEB通信之 长连接、长轮询(long polling)
- web网页设计实例作业 ——中国茶文化(6页) 茶文化网页制作作业_中国化(网页设计...
- 香槟分校计算机科学排名,伊利诺伊大学厄巴纳香槟分校计算机科学computer science专业排名第29名(2020THE泰晤士高等教育世界大学排名)...
- 软件技术实训室建设方案(完整版)2022
- 我与我的专业计算机作文500字,我和学校作文500字(精选5篇)
- ML-Agents训练智能AI使用技巧