一文弄通STM32F103基于simulink自动代码生成CAN/USART/GPIO/TIM(stm32cubemx+stm32target+matlab2018b)

  • 写在前面
  • 1、stm32cubemx的配置
    • 1.1选择芯片型号
    • 1.2配置时钟
    • 1.3 配置时钟树
    • 1.4 配置下载模式
    • 1.5 TIM中断配置
    • 1.6 通讯配置
      • CAN配置
      • USART配置
    • 1.7 GPIO配置
    • 1.8 工程配置
  • 2、搭建simulink模型
    • 2.1目标文件系统的配置
    • 2.2搭建芯片配置
    • 2.3应用层模块的搭建
      • 2.3.1使用TIM1和GPIO实现1s闪灯
      • 2.3.2使用TIM6和CAN send实现500ms发送一条can报文
      • 2.3.3使用CAN FIFO,CAN receive和USART实现指定can报文接收及串口转发数据
        • 过滤器配置
        • can接收模型
        • 接收子系统及USART模型
  • 3、生成代码及编译
  • 4、实际测试效果
  • 写在最后

写在前面

之前用过stm32发送can数据,用stm32与simulink联合开发只搞了一个tim中断和led闪灯,也没有记录,弄完就忘了,最近又有时间来做下代码生成,不需要手写一行代码实现控制逻辑。本文用来记录下过程及遇到的一些问题。方便以后自己查看的同时,希望对后面遇到相关问题的同学有所帮助~~~
本文用到的matlab版本为2018b,stm32cubemx版本为5.3.0,stm32mat_target版本为5.6.0,编译器版本为KEIL5,后面的开发都基于上述四个版本的软件,如果版本不匹配可能会遇到各种问题(如生成的代码中不包含主逻辑函数的调用等),软件的下载在官网即可,网上也有很多下载链接,本文不再给出。安装cube还需要安装java,网上有详细教程。
本文用到的开发版为STM32F103RCT开发板,两个LED输出(PD2,PA8),USART1串口,CAN0发送与接收(PB8,PB9)。由于开发板没有带TJA1050can收发芯片,所以还需要一个TJA1050模块(我之前的一篇文章有讲过,关于stm32can发送的)
STM32F103RCT+TJA1050+USBCAN盒做can通讯
程序下载使用STLINK,同时也方便调试。(正常量产一般选择CAN bootloader来更新程序,这个我已经实现了,后面有机会再发文章)
调试串口需要一个USB转TTL的设备。如果是无线通讯,需要两个无线透传的模块。本次用的就是两个无线透传的模块。
本文用到的模块包括:
GPIO输出(用来点亮LED灯)
TIM定时中断(定周期触发)
USART(串口发送数据)
CAN(发送,接收,过滤

1、stm32cubemx的配置

1.1选择芯片型号

打开stm32cubemx,新建工程,搜索STM32F103RC,选择STM32F103RCTx(这个根据自己手里的芯片选择,我的是F103的,所以选这个)

1.2配置时钟

选择外部时钟High Speed Clock(HSE),在RCC中配置为Crystal

1.3 配置时钟树

本次使用的开发版晶振为8M,经过PLL超频后系统时钟为72M
CAN使用的时钟是APB1,我们配置为36M,后面会用到

1.4 配置下载模式

本次使用STLINK调试下载程序,选择SW模式。

1.5 TIM中断配置

这个根据应用程序来,本次使用了两个TIM中断,使用TIM1和TIM6。这里配置了后面还可以再增加或减少。
TIM1配置为输出比较模式,设置上升沿触发

激活TIM6

1.6 通讯配置

CAN配置

使能CAN,引脚选择PB8.PB9(这个看自己板子,有的可能是PA11,PA12),预分频系数Prescaler选择9,TQ1选5个tq,TQ2选2个tq,得到波特率为500K(1/2000us)
计算公式如下:
36000000(APB1的时钟)/(9(分频系数)/(5(TQ1)+2(TQ2)+1(同步段时间1tq))=500k

对于重同步来说,同步跳转宽度(SJW,reSynchronization Jump Width)设置的太小则重新同步的调整速度慢,若太大,则影响传输速率。若想了解更多can同步知识,请自行查阅。

Time Triggered Communication 选择disable
选择非时间触发通讯模式
Automatic Bus-Off Management 选择disable(可以enable)
表示Bus Off后无法自恢复
Automatic Wake-Up Mode 选择disable(可以enable)
表示不开启自动唤醒
No-Automatic Retransmission 选择disable(可以enable)
表示允许报文自动重传
Receive Fifo Locked Mode 接收FIFO锁定模式,选择disable,表示报文不锁定,新的覆盖旧的
Transmit Fifo Priority 发送FIFO优先级
选择disable,表示优先级由报文标识符决定
Operating Mode ,选择正常模式(如果调试配置参数,可以选择环回模式
Normal CAN硬件工作在正常模式
silent CAN硬件工作在静默模式
LoopBack 环回模式
Silent_LoopBack 静默环回模式

本文的can通讯暂未使用到中断模式。后面有时间再测试。

USART配置

使能USART1,选择Asynchronous(异步),波特率选择115200。

1.7 GPIO配置

配置PD2和PA8为GPIO输出,在右边的引脚图上左键可以配置。
GPIO Output level:默认输出电平为低电平。
根据开发板原理图可知,输出低电平时灯亮

1.8 工程配置

设置工程名,工程路径,选择编译器为MDK-ARM V5

以上,配置STM32cubemx的工作就完成了,Ctrl+s保存工程。(和后面建的simulink模型放在一个文件夹下)不需要在cube中生成代码,生成代码在simulink中,由simulink调用cube。

2、搭建simulink模型

新建一个simulink模型,保存在和cube工程相同的文件夹下。

2.1目标文件系统的配置

点击模型左上方的小齿轮,进入模型配置界面
选择离散型,定步长时间为0.001s,这个时间为模型运行一次的时间,最好设置为0.001实测设置为0.01会报错。

Code Generation中目标系统文件选择stm32.tlc。关于目标系统tlc文件,可以参考我的另外几个博客。
从零开始simulink自定义代码生成----自定义目标系统配置(1)


选择完后下面会多出来一个选项,勾选

点Updata install path,会自动找到安装cube的目录
配置好上述设置后,点ok保存设置,至此目标系统配置完成。

2.2搭建芯片配置

打开simulink模块库,选择stm32下的mcu config模块,拖到模型中

双击打开mcu config,选择之前配置好的cube工程

导入芯片配置后,之前在cube里配置的模块就可以在simulink中使用了,如果没有配置的模块将会是灰色,无法选择

2.3应用层模块的搭建

2.3.1使用TIM1和GPIO实现1s闪灯

从simulink模块库中,托一个TIM模块到模型中,双击点开TIM模块进行配置。
APB为之前时钟树设置的频率,无法在该模块中修改。
选择Timer通道为TIM1
分频系数选7199,(7199+1=7200),将TIM1时钟降为10000HZ(这里默认是999,这样的话,如果周期变成1s,计数ARR就会溢出
选择输出频率为1HZ(对应周期为1s),ARR值自动变为10000(表示的是计数到10000后触发中断
选择UP中断

注意: ARR值最大为65535,超过后会导致溢出,定时中断出现错误。该模块并没有考虑值大于65535的情况,如果是大于65535的数仍然是可以生成代码的。
同时输出的频率必须为整数,不能为小数。小数也可以生成代码,但生成的代码是错误的,这个STM32硬件驱动库没有考虑。
上面两点都是本人实测出来的,TIM1配置图如下:

配置好后,点ok,模块右侧会出现一个输出,该输出为function call,我们选择一个function子系统来执行回调函数

在function子系统中增加两个GPIO write模块,一个配置为PA8.一个配置为PD2


模型中增加了一个delay模块和一个取反模块,实现两个灯的来回亮灭。不是很复杂的逻辑。

2.3.2使用TIM6和CAN send实现500ms发送一条can报文

TIM6的配置和上面的TIM1差不多。只是将频率改为了2HZ(对应0.5s)

function子系统中建立模型如下,模拟一条报文的发送,选择的是simulink自带的can pack模块,第一个信号递增输出,最大值为7(位数为3),其他两个信号为常数输出。该模块输出时必须要有一个变化的值或变量输出,否则会报错,原因未知。如果是要全部输出常值,可以在function外部输入进来


关于发送can报文,本文没有使用中断。
在生成代码调试过程遇到一个非常奇怪的问题,HAL函数在添加报文(addmessage)以后,会卡在CAN_IsTxMessagePending函数中,一直没有解决,屏蔽这个while就好了,网上看其他can发送的函数里,基本没有用过这个IsTxMessagePending函数,暂时在tlc文件中将其屏蔽了,生成代码的时候也会是屏蔽的状态。如果有同学遇到了知道什么原因可以告知我一下。
关于tlc文件的作用,可以参考我的其他博客
从零开始simulink自定义代码生成----自定义硬件驱动库文件(1)

can_send模块对应的tlc文件在STM32-MAT的安装目录下,我的是在C:\MATLAB\STM32-MAT\STM32\blks\mex\tlc_c,找到Can_send.tlc文件,记事本打开,对其进行修改。在while函数前加//,注释掉这个生成的代码。

注释掉这个代码后,生成的代码可以正常发送can数据。
使用usbcan接收数据,这个之前的博客也说过的。

2.3.3使用CAN FIFO,CAN receive和USART实现指定can报文接收及串口转发数据

在模型中添加如下模块

过滤器配置

can接收时,即使不需要过滤,也需要添加一个过滤器(选择mask模式,32位,MASK ID HIGH LOW,ID HIGH LOW都填0,过滤器选择FIFO0,其他默认就好)
关于can 过滤器,有两种模式,一种mask模式(掩码模式),一种list模式(列表模式),有两种位选择,一种32位,一种16位。组合起来有四种模式

对于列表模式,很好理解,32位宽的列表模式,可以精确筛选两个ID(扩展帧和标准帧都可以),对于16位宽的列表模式,可以精确筛选4个标准帧ID,如果将IDE位置1,则可以筛选ID的高11位数据,无法精确筛选扩展帧ID。
对于掩码模式,可以这样理解,有一个屏蔽码和验证码,屏蔽码用来指定需要确定的位,验证码用来指定确定的位的值,两者一起用来过滤部分ID。关于验证码和屏蔽码,网上也有很多教程说明,此处不再说明。
32位的掩码模式,FilterIdHigh与FilterIdLow合在一起表示CAN_FxR1寄存器,用来存放验证码,而FilterMaskIdHigh与FilterMaskIdLow合在一起表示CAN_FxR2寄存器,用来存放屏蔽码
在16位宽的掩码模式下,CAN_FxR1的低16位是作为验证码,对应的16位屏蔽码为CAN_FxR1的高16位,同样的,CAN_FxR2的低16位是作为验证码,对应与CAN_FxR2的高16位为屏蔽码
本次使用的是32位宽的列表模式来指定确定的一个标准帧ID和一个扩展帧ID,其他过滤方式后面有空再测试。
can过滤器FIFO的配置如下:

注意:此处Filter Mask ID High Filter Mask ID Low Filter ID High Filter ID Low四位值填的是十进制数。在生成代码的过程中会转化为16进制。
在32位列表模式下,Filter Mask ID High Filter Mask ID Low的组合和Filter ID High Filter ID Low两者实现的功能是一样的。
定义需要过滤的标准帧ID为0x51,扩展帧ID为0x18ff31f0。定义将标准帧ID的过滤放在Filter Mask ID High 和Filter Mask ID Low中
由上图的32位列表模式排列图可知,标准帧格式占的是高位,要想过滤确定一个标准帧0x51,需要把ID左移5位,然后转化为十进制,填入Filter Mask ID High,计算值为2592,Filter Mask ID Low需要把IDE置为标准帧(值为0),数据帧RTR(值为0),所以计算值为0。
要想过滤一个扩展帧0x18ff31f0,需要把先ID左移3位,再把ID右移16位,和0xffff做与运算,再转换为十进制,得到Filter ID High的值51193 ((ExtId<<3)>>16)&0xffff;
Filter ID Low需要把先ID左移3位,和0xffff做与运算,再将IED为置为扩展帧(值为4这个地方后面会有用),数据帧RTR(值为0),再转换为十进制36740 (ExtId<<3)&0xffff|CAN_ID_EXT
对于STM32F103只有一个can,filter slave start bank没有作用,若是两路can,尽量设置为14。filter bank默认即可。

can接收模型

按官方给的demo,最好在CAN_get_state=ready(1)且read_data=ready(1)后再解析数据
read_data配置输出为can massage信号

if模块配置,两者不为0可以进入Subsystem

接收子系统及USART模型

将收到的can数据通过USART1串口发送出来,设置发送的字节为2,RcvUsartBuf转化在官方的demo中的usart模块中有。将两个不同的can中的数据进行组合,放入buf中


至此模型的搭建,也已经完成了。
注意:在can接收的模型中,又发现一个问题,标准帧可以接收到数据,正常转发,而扩展帧中的数据接收不到。通过STlink调试发现,生成的代码中unpack模块判断扩展帧是为1,而接收的ID信息在赋值时,STM32定义的扩展帧表示为4.
可能当时做这个STM32硬件驱动库的人就没考虑到用unpack解析?感觉STM32做的库确实不太给力啊
同样的解决方案,找到can_read_data.tlc,修改为下图所示

3、生成代码及编译

模型搭建完成后,ctrl+b生成代码,用KEIL5打开工程,编译后通过STLINK将程序烧写到开发板中。
编译过程中可能会遇到缺少头文件和源文件,
can_message.h,在mat-target安装目录下的\addSrc\R2018b\inc 目录下,拷贝到生成的工程头文件夹下
getBuffPtr.h,在mat-target安装目录下的\addSrc\inc目录下,拷贝到生成的工程头文件夹下
getBuffPtr.c,在mat-target安装目录下的\addSrc\src目录下,拷贝到生成的工程源文件夹下
还有一种方法,在simulink配置Model Configuration Parameters(小齿轮))中配置
选择对应文件夹下的文件即可,编译的时候会包含选择的文件

4、实际测试效果

can 500ms发送一帧数据

灯来回闪(只拍了两张图)


can接收数据及串口转发
发送0x51,串口可以转发数据


更换数据发送


发送0x52,can无法接受到数据,串口不转发(串口后面没有7的数据)


发送0x18ff31f0,串口可以转发数据(转发数据为2)


此处之前一个can转发的数据8还是在继续发送,保持了上一次的值,本文没有处理。

写在最后

后面还有can中断收发还没有试,串口接收,输入电平采集,其他can过滤方式后面有空再测试~
STM32的硬件驱动库还有很多不完善的地方,后面有空再多多研究~~

欢迎大家点赞转发分享~~有问题可以与我联系:WX/QQ:953590472
STM32cube工程及模型及生成的代码

一文弄通STM32F103基于simulink自动代码生成CAN/USART/GPIO/TIM(stm32cubemx+stm32target+matlab2018b)相关推荐

  1. Simulink自动代码生成:生成代码的基本设置

      Simulink自动代码生成也被称作基于模型开发(BMD),相比于传统的手写代码方式能够尽量减少人为错误.模型本身可以用于仿真,单元测试等,更便于提前发现逻辑错误.同时只要约定好模型接口,就可以多 ...

  2. Simulink自动代码生成

    Simulink学习笔记(二)--Simulink自动代码生成(一) Simulink学习笔记(三)--Simulink自动代码生成(二)

  3. Simulink自动代码生成:数据字典的建立及代码优化

      在上一节<Simulink自动代码生成:生成代码的基本设置>的基础上,我们来对模型进行优化,使得生成的代码更能满足实际的需求,没看过我上一篇文章的可以点开如下链接:   Simulin ...

  4. Matlab/Simulink 自动代码生成 基于模型设计学习教程(1)---- 环境配置

    在接触不断开发深入STM32的时候,我经常在直接用C语言编写一个很发杂的算法,比如PID控制,傅里叶变换,卡尔曼滤波之类的基本需要的算法,然而对于一个初学者来说,编写这样的算法,费时费劲,甚至不一定能 ...

  5. Simulink自动代码生成3——优化生成的代码(optimizing generated code)

    代码优化综述 使用simulink代码生成之后,如果需要进一步对执行效率或者内存优化,可以看下面提到的方法.具体可从以下几个方面考虑: remove initialization code remov ...

  6. STM32 Simulink 自动代码生成电机控制:基于反电动势观测器的锁相环设计

    目录 锁相环设计 参数设计 总结 锁相环设计 全阶滑模的锁相环和前面的非线性磁链观测器锁相环原理类似,同样反正切函数计算方法包含除法运算,尤其是当反电动势观测值过零时,转子位置观测误差会进一步放大,这 ...

  7. Matlab/Simulink 自动代码生成 基于模型设计学习教程(2)---- 闪烁灯实验

    首先我们来搭建我们第一个模型 将选中的模块拖到左边的模型当中 我们再来看一下原理图,可以看见PC13是我们的指示灯 我们来设置 Digital Output模块,选中PC13,并将Sample tim ...

  8. MATLAB/Simulink自动代码生成(一)

    Simulink自带了种类繁多.功能强大的模块库,在基于模型设计的开发流程下,Simulink不仅通过仿真可以进行早期设计的验证,还可以生成C/C++.PLC等代码直接应用于PC.MCU.DSP等平台 ...

  9. STM32 Simulink 自动代码生成电机控制——DTC控制仿真到代码生成

    目录 传统DTC控制仿真 1. DTC简单介绍 2. 传统DTC仿真模型 3. DTC仿真效果 改进DTC SVPWM控制仿真 1. SVPWM替换查表 2. 无传感磁链估算 改进后的DTC控制仿真 ...

最新文章

  1. 原创:检查点的三种加入方式
  2. Leetcode 147. 对链表进行插入排序 解题思路及C++实现
  3. 上的网页显示拒绝访问_DLink家庭路由器上发现6个漏洞
  4. Sending HTML content in an email using PHP
  5. MongoDB基本命令的使用
  6. oracle怎么判断地址相似,如何查看oracle数据文件的地址
  7. swfupload使用说明
  8. 【干货】神策标签生产引擎架构
  9. OOP 术语:Arguments(参量)和 Parameters(参数)的区别(转载)
  10. 如果不需要CSS隐藏滚动条
  11. 【背包问题】基于matlab多目标粒子群算法求解多背包问题【含Matlab源码 654期】
  12. iscsi 挂载教程_CentOS下如何搭建ISCSI以及Windows如何挂载ISCSI镜像
  13. 【排序】直接选择排序
  14. 使用Motion-Vector实现Real-time人体行为识别
  15. 【DataBase Notation(1/3)】Notation_Chen, Crow‘s Foot and UML
  16. 大数据的核心架构层是哪些?
  17. PDFbox-PDF解析(坐标定位,分页读取)
  18. 三个数差的平方公式推导过程_平方差公式证明推导过程及运用详解(数学简便计算方法之一)...
  19. 前端小白-HTML简介
  20. 吉林师范计算机考研真题,2021年吉林师范大学历年考研真题各专业汇总

热门文章

  1. 怎么获得本机QQ登录的密码
  2. 第24节 综合网络配置实验(含IP、RIP、VLAN、VTP、HSRP、ACL、NAT等配置完整命令)——基于PacketTracer8.0仿真实验
  3. Java输出时间为12小时制,带上PM/AM 或 上午/下午
  4. ASP.NET MVC网站使用新浪微博账号登录
  5. 网络安全之信息收集技术(全)
  6. 介绍matlab的概要和功能介绍
  7. 神经网络权值和阈值范围,神经网络的权值和阈值
  8. 识别您的英特尔® 无线适配器和 Wi-Fi 驱动程序版本号
  9. java后台解析xml格式字符串
  10. Windows加密文件夹设置