一文弄通STM32F103基于simulink自动代码生成CAN/USART/GPIO/TIM(stm32cubemx+stm32target+matlab2018b)
写在前面
之前用过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、实际测试效果
can 500ms发送一帧数据 灯来回闪(只拍了两张图) can接收数据及串口转发 发送0x51,串口可以转发数据 更换数据发送 发送0x52,can无法接受到数据,串口不转发(串口后面没有7的数据) 发送0x18ff31f0,串口可以转发数据(转发数据为2) 此处之前一个can转发的数据8还是在继续发送,保持了上一次的值,本文没有处理。
写在最后
后面还有can中断收发还没有试,串口接收,输入电平采集,其他can过滤方式后面有空再测试~ STM32的硬件驱动库还有很多不完善的地方,后面有空再多多研究~~
欢迎大家点赞转发分享~~有问题可以与我联系:WX/QQ:953590472 STM32cube工程及模型及生成的代码
|