之前用过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(发送,接收,
过滤
)
打开stm32cubemx,新建工程,搜索STM32F103RC,选择STM32F103RCTx(这个根据自己手里的芯片选择,我的是F103的,所以选这个)
选择外部时钟High Speed Clock(HSE),在RCC中配置为Crystal
本次使用的开发版晶振为8M,经过PLL超频后系统时钟为72M
CAN使用的时钟是APB1,我们配置为
36M
,后面会用到
本次使用STLINK调试下载程序,选择SW模式。
这个根据应用程序来,本次使用了两个TIM中断,使用TIM1和TIM6。这里配置了后面还可以再增加或减少。
TIM1配置为输出比较模式,设置上升沿触发
激活TIM6
使能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通讯暂未使用到中断模式。后面有时间再测试。
使能USART1,选择Asynchronous(异步),波特率选择115200。
配置PD2和PA8为GPIO输出,在右边的引脚图上左键可以配置。
GPIO Output level:默认输出电平为低电平。
根据开发板原理图可知,输出低电平时灯亮
设置工程名,工程路径,选择编译器为MDK-ARM V5
以上,配置STM32cubemx的工作就完成了,Ctrl+s保存工程。(
和后面建的simulink模型放在一个文件夹下
)不需要在cube中生成代码,生成代码在simulink中,由simulink调用cube。
新建一个simulink模型,保存在和cube工程相同的文件夹下。
点击模型左上方的小齿轮,进入模型配置界面
选择离散型,定步长时间为0.001s,这个时间为模型运行一次的时间,最好设置为
0.001
,
实测设置为0.01会报错。
Code Generation中目标系统文件选择stm32.tlc。关于目标系统tlc文件,可以参考我的另外几个博客。
从零开始simulink自定义代码生成----自定义目标系统配置(1)
选择完后下面会多出来一个选项,勾选
点Updata install path,会自动找到安装cube的目录
配置好上述设置后,点ok保存设置,至此目标系统配置完成。
打开simulink模块库,选择stm32下的mcu config模块,拖到模型中
双击打开mcu config,选择之前配置好的cube工程
导入芯片配置后,之前在cube里配置的模块就可以在simulink中使用了,
如果没有配置的模块将会是灰色,无法选择
从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模块和一个取反模块,实现两个灯的来回亮灭。不是很复杂的逻辑。
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接收数据,这个之前的博客也说过的。
在模型中添加如下模块
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默认即可。
按官方给的demo,最好在CAN_get_state=ready(1)且read_data=ready(1)后再解析数据
read_data配置输出为can massage信号
if模块配置,两者不为0可以进入Subsystem
将收到的can数据通过USART1串口发送出来,设置发送的字节为2,RcvUsartBuf转化在官方的demo中的usart模块中有。将两个不同的can中的数据进行组合,放入buf中
至此模型的搭建,也已经完成了。
注意:在can接收的模型中,又发现一个问题,标准帧可以接收到数据,正常转发,而扩展帧中的数据接收不到。通过STlink调试发现,生成的代码中unpack模块判断扩展帧是为1,而接收的ID信息在赋值时,STM32定义的扩展帧表示为4.
可能当时做这个STM32硬件驱动库的人就没考虑到用unpack解析?感觉STM32做的库确实不太给力啊
同样的解决方案,找到can_read_data.tlc,修改为下图所示
模型搭建完成后,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(小齿轮))中配置
选择对应文件夹下的文件即可,编译的时候会包含选择的文件
can 500ms发送一帧数据
灯来回闪(只拍了两张图)
can接收数据及串口转发
发送0x51,串口可以转发数据
更换数据发送
发送0x52,can无法接受到数据,串口不转发(串口后面没有7的数据)
发送0x18ff31f0,串口可以转发数据(转发数据为2)
此处之前一个can转发的数据8还是在继续发送,保持了上一次的值,本文没有处理。
后面还有can中断收发还没有试,串口接收,输入电平采集,其他can过滤方式后面有空再测试~
STM32的硬件驱动库还有很多不完善的地方,后面有空再多多研究~~
欢迎大家点赞转发分享~~有问题可以与我联系:WX/QQ:953590472
STM32cube工程及模型及生成的代码
①创建新工程后,要选择手上开发板实际对应的芯片型号。我这里是野火的骄阳开发板,也是
STM32
F407IGT6。备注:过程基本参考上文,接下来我将突出说明差异部分。一、
STM32
Cube
MX
设置。
磁场定向控制包含电流环和速度环,电流环是通过转矩电流分量闭环控制实现动态调节,速度环是以目标转速和测量转速为闭环控制量。对于无传感器(无编码器/霍尔传感器)的电机需要对转子速度和位置进行观测,本案例中采用了滑模观测器(SMO)或磁通观测器。滑模观测器使用定子电压和电流作为输入来估计电机模型的反电动势(EMF),进而估计转子位置和速度,而磁通观测器使用定子电压和电流估计定子磁通、产生的扭矩和转子位置。
最近换了工作,电脑也换了,
STM32
的
自动
代码生成
工具在官网已经下不到了,估计也是做的太差了,也不想干了~~花了一些时间把环境配置好了,目前用的是
Matlab
2020b,
stm32
cube
版本5.6.0,
stm32
target
版本5.6.0(这个是最新的了,再没有更新了)
断更很多天了,感觉很颓废。
进入正题,本文记录
stm32
CAN过滤模式的四种配置及
simulink
代码生成
与测试。之前的文章中只用了32位列表模式(不清楚的可以看
STM32
基于
simulink
自动
代码生成
),下面分别介绍其他三种模式。
环境:
STM32
Cube
Mx
+Clion+
Matlab
+PCAN利用
STM32
Cube
Mx
配置
STM32
的CAN通信:默认这两项终端是Enabled的,这里去掉,否则CAN无法同时收发,会卡在接收中断服务里:通过
STM32
Cube
Mx
配置的CAN后,还需要在生成的代码中声明CAN类型和对应ID、长度的信息,如下:/* Private variables -----------------...