前言
之前做轮腿机器人的时候,一直想把控制板换成STM32H7系列(之前用的DJI RoboMasterC型开发板,STM32F4,两路CAN), 因为关节电机+轮毂电机+云台电机就有7个独立的CAN发送包,感觉两路CAN的带宽不是很够用,后面在赛场上云台电机时常疯转也证明了我在CAN通信的软件和硬件上存在问题。后续也未排查出具体问题。达妙科技的DM_MC02开发板(STM32H723VGT6)具有三路FDCAN,可兼容经典CAN模式。而网上关于如何将FDCAN配置成经典CAN的教程并不多且讲的十分晦涩难懂,在学习安富莱的https://img.anfulai.cn/bbs/86980/%E5%AE%89%E5%AF%8C%E8%8E%B1_STM32-V7%E5%BC%80%E5%8F%91%E6%9D%BF_%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8C%EF%BC%8C%E5%90%ABBSP%E9%A9%B1%E5%8A%A8%E5%8C%85%E8%AE%BE%E8%AE%A1%EF%BC%88V3.5%EF%BC%89.pdf 嵌入式文档的90、91、92章节关于FDCAN的知识后,结合自己这几天的摸索,总结了以下如何使用达妙科技的DM_MC02开发板(STM32H723VGT6),将FDCAN配置成经典CAN驱动四个达妙4310电机的经验教程和注意事项。
软件和硬件
软件
MDK5.40、最新版STM32CubeMX、ZCANPRO波特率计算器
硬件
达妙科技STM32开发板H723 DM-MC02
达妙科技DM-J4310-2EC V1.1电机
XT30 2+2双端线*4 GH1.25-2 pin *1
正点原子高速无线调试器
STM32CubeMX基本配置
打开STM32H723VGTx芯片的配置界面
选择System Core -> CORTEX-M7 -> Speculation default mode 从Enabled改成Disabled 为减少不必要的麻烦 先关闭MPU和Cache
选择RCC -> High Speed Clock (HSE ) 改成 Crystal/Ceramic Resonator
如果使用FreeRTOS的话 选择SYS -> Timebase Source 从systick改为TIM2 不用就保持默认systick
选择Connectivity -> FDCAN1->Activated打勾 先激活FDCAN1 方便我们后续的时钟配置
配置时钟 点击Clock Configuration 依次将input frequency 改为24(开发板使用的外部晶振24MHz)时钟源选择HSE PLLCLK锁相环产生的时钟信号 最高频率STM32H723VGT6可达550MHz,这里为了计算方便 我把最大频率设置为了480MHz 等待STM32CubeMX自动配置好
将该界面拉到最下面我们可查看到FDCAN的时钟频率为系统默认生成的120MHz
这里我们也可以根据计算方便修改PLL2的时钟频率 让FDCAN使用PLL2的时钟频率 比如我想让FDCAN的时钟频率修改成100MHz
下面FDCAN的频率我们还是使用系统默认配置的120MHz
波特率的计算
波特率的计算公式 (这里只是了解一下波特率是怎么计算的 后续我们可以使用波特率计算器)
FDCANFrequency(FDCAN频率):即为上述我们配置的FDCAN时钟频率,为120MHz
Prescaler(预分频器):FDCAN频率还需要除预分频系数得到一个更小的频率 方便我们后续计算 假设TimeSeg1和TimeSeg2的值范围在1-32和1-16 如果FDCAN频率过大算出来可能达不到我们想要的波特率。
比如说我们需要配置1Mdps波特率 如果没有Prescaler(预分频器) BaudRate = 120MHz / (1+32+16) = 2.449Mdps 达不到我们的期望值 而TimeSeg1和TimeSeg2的值已达到最大值。
TimeSeg1和TimeSeg2即我们需要配置的参数。具体原理可参考下图。
我们回到STM32CubeMX 中的FDCAN1配置界面 我们会发现怎么有两个不同的Prescaler、TimeSeg1、TimeSeg2组合,一个是Data,一个是Nominal 即数据和仲裁 即对应的CAN通信的数据域和仲裁域。两者还有一个参数一样 Sync Jump Width(同步跳转段的宽度)缩写SJW 后续是我们配置选择TimeSeg1和TimeSeg2的重要参考
这是因为FDCAN支持可变波特率 即CAN的仲裁域和数据域的波特率可以不同 但是我们将其配置成经典的CAN模式,仲裁域和数据域的波特率必须是一样的 所以我们这里先配置仲裁域的波特率 因为下面可以实时显示配置波特率的多少 配置好后将数据域的参数改成和仲裁域一样的就好 。
这里就要使用我们的波特率计算器了,可以去官网下载 也可以直接底下网盘链接
链接:https://pan.baidu.com/s/1I9mTRRVyH48QXiS9vNWD4A?pwd=kxff
下载好后选择baudcal
打开后 设备类型 选择任意带有CANFD并且TCP和UDP结尾的都可以 计算方式是一样的 我们选择CANFDNET_TCP
我们看到底下有一个CAN(FD)波特率推荐设置 在看了网上很多资料和别人配置的代码 发现很多配置都符合这些规则,应该是一种根据CAN通信原理最优化配置的规范,那我们配置波特率也按这个设置来 总结一下就是
1.BRP尽量小:即Prescaler(预分频器)的值尽量要小。
2.不用管,因为经典CAN仲裁域和数据域BRP是一样的。
3.SJW尽量大且尽量保持与TSEG2一致 :即Sync Jump Width和TimeSeg2两个参数尽量保证一致且较大。
4.我们配置的波特率一般为经典CAN模式支持的最大值即1Mbps 1000kbps>800kbps 所以我们选择采样率(SMP)为 75%左右的参数
5.不用管
6.不用管
所以我们选择参数的要求是 采样率(SMP)为75%左右的同时 BRP(Prescaler(预分频器))的值尽量要小,且Sync Jump Width和TimeSeg2两个参数尽量保证一致且较大。
接下来我们用计算器算一下我们理想的参数
首先将时钟改为我们CubeMX配置的FDCAN时钟频率120MHz 波特率改为我们期望的1Mbps点击设备类型旁边的计算得到一组参数,点击SMP 参数会根据采样率大小进行排序
我们找到采样率(SMP)为75%左右的参数
根据 BRP(Prescaler(预分频器)尽量较小 我们应该选择BRP为2的那套参数,但实际上并不行,因为我们回到CubeMX,点击Data Time Seg1 可以看到 该参数的最大值为32 如果选择44,15,1,2那套参数 Data Time Seg1 最大值会超出 ,所以我们选择BRP为3的那套。
最后我们将SJW(同步跳转宽度)改为10 即满足TimeSeg2两个参数尽量保证一致且较大 验证一下。发现该组参数满足上述所有条件。所以最后
Prescaler = 3 Data Time Seg1 = 29 Data Time Seg2 = 10 Sync Jump Width = 10.
CubeMX FDCAN配置(重要!!!!!)
回到CubeMX我们来看看FDCAN的各个参数如何配置
基础配置:
Frame Format (帧格式):因为我们配置的是经典CAN模式,选择Classic mode,经典模式
Mode (模式):选择Normal mode,正常即可
Auto Retransmission 与 Transmit Pause :这两个都是FDCAN的特性 全部Disable就行
Protocol Exception (协议异常处理):这个打不打开都一样,打开可能有一点点好处,我这里选择了 Enable,关闭也无所谓
Nominal Sync Jump Width (仲裁域的同步跳转宽度) 根据我们上面计算器得到的Sync Jump Width = 10
Data Prescaler、Data Sync Jump Width、Data Time Seg1、Data Time Seg2,这四个参数根据我们计算器得到的依次填入3、10、29、10
Message Ram Offset (RAM消息地址偏移):范围0-2560,使用几个FDCAN就将2560平均分给几个,比如使用一个FDCAN1就填0,范围就是将RAM地消息0-2560分给FDCAN1。使用FDCAN1和FDCAN2,FDCAN1就填0,FDCAN2就填1280,FDCAN1范围就是0-1280,FDCAN2范围则是1281-2560。三个就以此类推。
Std Filters Nbr(标准ID过滤数量) :这个参数的配置非常容易踩坑,它的参数作用是规定你需要过滤掉标准CANID的数量,通常我们我们不需要过滤任何ID,但这里绝对不能设置为0,如果设置为0则进入不了CAN的中断,必须设置为1即以上,设置为1也不代表我们需要在代码初始化过滤器时过滤掉一个ID,可将一个参数设置为0x00000000,即可不过滤掉任何ID。
Ext Filters Nbr (扩展ID过滤数量):经典CAN没有扩展ID,写0。
接下来我们要明确一个概念:即你的一路CAN中 在不加延时的情况下,一次最多能发送或接收的最大帧数据包的数量。我把它叫做CAN收发最大带宽数。这么说可能有点云里雾里,举两个例子。以达妙系列电机为例,在不加延时的情况下,一次只能给两个电机发送指令,如果连续给三个达妙电机发送控制包,第三个电机将收不到控制指令也不会返回电机数据(达妙电机控制方式就是发一帧回一帧,发不出去肯定就收不到)所以这路CAN的最大发送带宽数和最大接受带宽数都是2
再拿大疆的电机(3508、6020等)举例,官方手册上说一次两帧数据包最多可以控制8个电机且收到电机反馈数据(实际测试大概只能控制6个),那大疆的电机CAN的最大发送带宽数为2,最大接收带宽数为8(实际上4-6)这个概念关乎我们配置接下来的接收区和发送区的FIFO数量和字节数。
接收区配置:
接收区分为Fifo接收和Buffers接收,其中Fifo区有两个,Fifo0和Fifo1,选择哪个Fifo不仅要在CubeMX配置,在程序中的CAN过滤器初始化中也要配置 。Nbr结尾代表对应接收区的的数量,Size就是一个接收区开辟的最大字节数。
首先我们不使用Buffers接收,RxBuffers Nbr直接填0。那我们Fifo0和Fifo1数量如何选择,就关乎到上面说的CAN收发最大带宽数,开辟的数量不能小于CAN的接收最大带宽数,(发送也是一样),比如我这路CAN的最大接收带宽数为2,如果只开辟一个Fifo区的话,那第二个电机的数据就会收不到,所以我们配置的数量要大于等于2。那有人可能要问了,我要控制四个电机发送四帧数据包不是要开辟四个吗,上面说了,是不加延时的情况下最大的接收数量,通过每两电机延时200us-1ms可以控制两个以上,Fifo数量也只需要2个,当然多开一点也无所谓。Rx Fifo Elmt Size我们选择8bytes就行,经典CAN一帧数据包最大就8bytes,当然选择多的也可以。具体使用哪个Fifo在Cube里配置完后,程序中CAN过滤器初始化也要选择!!(后面会说)
我们使用一路CAN控制达妙电机,并用Fifo0来接收电机数据的最低配置为
Rx Fifo0 Elmts Nbr :2
Rx Fifo0 Elmt Size :8 bytes data filed
Rx Fifo1 Elmts Nbr :0
Rx Buffers Nbr :0
发送区配置:
发送区和接收区差不多,不过多赘述了,我们不使用Events和Buffers发送,直接写0,我们采用FIFO发送不用Queue(队列),选择FIFO mode,Nbr数量根据CAN收发最大带宽数配置,大于等于这个数,Size选择8字节就行,大一点也可以。
我们使用一路CAN控制达妙电机,并用FIFO模式来发送控制电机的最低配置为:
Tx Events Nbr :0
Tx Buffers Nbr :0
Tx Fifo Queue Elmts Nbr:2
Tx Fifo Queue Mode :FIFO mode
Tx Elmt Size 8 bytes data filed;
仲裁域的波特率配置:
根据我们计算器得到的 Prescaler = 3 Data Time Seg1 = 29 Data Time Seg2 = 10 就可,最后算的波特率可以看到为1000000bit/s 即1Mbps。
其他
中断记得打开,方便我们接收数据处理
注意CAN的引脚跟开发板的对不对应
然后就可以生成代码了。
Keil程序代码
CAN过滤器初始化:
虽然我们不需要过滤任何ID,但是过滤器关乎到开启中断、使能CAN等功能,所以是必要的
过滤器的配置我也研究的不是很深,也是看着别人来的,经典CAN的配置这样就行,各个配置的详情可以见官方文档或者安富莱的教程。
发送相关代码
CAN发送的头结构体配置
我这里是将CAN的句柄、头结构体、还有8字节数组封装在了一起:
头结构体的具体配置
CAN发送代码举例
以给达妙电机发送使能为例
Identifier就是F4系列的StdId即发送的标识符,因为我们使用的FIFO模式发送,最后的发送函数为HAL_FDCAN_AddMessageToTxFifoQ
接收相关代码
接收结构体:
还是一样,我这里对接收的相关结构体也进行了二次封装
接收的不需要配置什么,函数获取就行了
CAN接收的中断回调函数
分别是FIFO0和FIFO1的中断回调,根据Cube和过滤器配置的FIFO区,收到数据时就会进入对应的中断,然后通过HAL_FDCAN_GetRxMessage获取接收的各种数据,再根据通信协议进行数据处理,FDCAN1_RxFifo0RxHandler是我自己定义的数据处理函数。
代码开源:
代码 · kit/AGV - 码云 - 开源中国 (gitee.com)
主要内容在其BSP层的bsp_can.c、h里
声明(叠甲)
本文章或者教程不具有特别严谨性,有些地方是根据实际工程多次试错得到的经验,作者鼓励读者寻找官方文档或者更为专业的教程进行配置,该教程只是方便工程上的开发,作者使用上述内容数十天内暂时没有发现问题,上述教程如有不严谨、不合理、错误的地方或对教程有不理解的地方请及时与作者联系。欢迎指正。
QQ:1985483641
Blibili:王草凡