[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
顾问Alchemic Ronin
2020-3-30 22:33:19 显示全部楼层

马上注册,玩转Robomaster!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
从STM32开始的RoboMaster生活:进阶篇 VII [CAN]
项目&教程仓库-STM32-RoboMaster-


1.0 什么是CAN?

1.1 背景 + 定义
Controller Area Network 控制器局域网络 是ISO国际标准化的串行通信协议。在汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个LAN,进行大量数据的高速通信”的需要,1986 年德国电气商博世公司开发出面向汽车的CAN 通信协议。此后,CAN 通过ISO11898及ISO11519进行了标准化,在欧洲已是汽车网络的标准协议。
CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。现场总线是当今自动化领域技术发展的热点之一,被誉为自动化领域的计算机局域网。它的出现为分布式控制系统实现各节点之间实时、可靠的数据通信提供了强有力的技术支持。近年来,它具有的高可靠性和良好的错误检测能力受到重视,被广泛应用于汽车计算机控制系统和环境温度恶劣、电磁辐射强及振动大的工业环境。
1.2 意义 + 优势
  • 多主控制

    • 在总线空闲时,所有的单元都可开始发送消息(多主控制)
    • 最先访问总线的单元可获得发送权(CSMA/CA力式)
    • 多个单元同时开始发送时,发送高优先级 ID 消息的单元可获得发送权

  • 消息的发送

    • 在CAN协议中,所有的消息都以固定的格式发送。总线空闲时,所有与总线相连的单元都可开始发送新消息。两个以上的单元同时开始发送消息时,根据标识符(Identifier以下称为ID)决定优先级。ID并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息ID的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息。仲裁失利的单元则立刻停止发送而进行接收工作。

  • 系统的柔软性

    • 与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其他单元的软硬件及应用层都不需要改变。

  • 通信速度

    • 根据整个网络的规模,可设定适合的通信速度。在同一网络中,所有单元必须设定成统一的通信速度。即使有一个单元的通信速度与其它的不一样。此单元也会输出错误信号,妨碍整个网络的通信。不同网络间则可以有不同的通信速度。

  • 远程数据请求

    • 可通过发送“遥控帧”,请求其他单元发送数据。

  • 错误检测功能

    • 所有的单元都可以检测错误(错误检测功能)
    • 检测出错误的单元会立即同时通知其他所有单元(错误通知功能)
    • 正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)

  • 故障封闭

    • CAN可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。

2.0 CAN原理
2.1  Differential signal 差分信号

                               
登录/注册后可看帖子
从上图我们可以看到,与图中下部分的普通信号不同,并不是低电平表示0高电平表示1,而是当两根数据线在同一时刻,如果有电压差表示0无电压差表示1。
相对于单信号线传输的方式,使用差分信号传输具有如下优点:
  • 抗干扰能力强:当外界存在噪声干扰时,几乎会同时耦合到两条信号线上,而接收端只关心两个信号的差值,所以外界的共模噪声可以被完全抵消。
  • 有效抑制电磁干扰:同样的道理,由于两根信号的极性相反,他们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。
  • 时序定位精确:由于差分信号的开关变化是位于两个信号的交点,而不像普通单端信号依靠高低两个阈值电压判断,因而受工艺,温度的影响小,能降低时序上的误差,同时也更适合于低幅度信号的电路

由于差分信号线具有这些优点,所以在USB协议,485 协议,以太网协议,及 CAN 协议的物理层中,都使用了差分信号传输。

                               
登录/注册后可看帖子
虽然CAN是通过差分信号传输数据,但是MCU不是,所以需要CAN Transceiver来把MCU的普通信号转换成差分信号。STM32并不自己提供该功能,所以需要外接CAN Transceiver。
2.2 Time Quantum 时间量子
  • 数据的每一Bit位,都分为4段

    • 同步段 ( SS / Sync )
    • 传播时间段 ( PTS / Prop )
    • 相位缓冲段 1 ( PBS1 / Phase 1 )
    • 相位缓冲段 2 ( PBS2 / Phase 2 )



                               
登录/注册后可看帖子
  • 而这每一段又由称为Time Quantum 时间量子的最小时间单位组成

2.3 Data Frame 数据帧
在CAN标准中,分为标准格式和扩展格式,而帧也分为5种
  • 数据帧
  • 遥控帧
  • 错误帧
  • 过载帧
  • 间隔帧

我们这里主要解析一下数据帧

                               
登录/注册后可看帖子
每个数据帧总共包含7个段
  • Start of Frame 帧起始:表示数据帧开始的段
  • Arbitration Field 仲裁段:表示该帧优先级的段
  • Control 控制段:表示数据的字节数及保留位的段
  • Data 数据段:数据的内容,一帧可发送 0~8 个字节的数据
  • CRC Field CRC段:检查帧的传输错误的段
  • ACK Field ACK段:表示确认正常接收的段
  • End of Frame 帧结束:表示数据帧结束的段

2.4 Arbitration 仲裁

                               
登录/注册后可看帖子
在CAN中,仲裁是为了解决当同一时刻有多个Node在试图发送信息的时候,让优先权最大的那个Node先发。在CAN中,1是隐性电平,0是显性电平,在ID中显性电平越靠前越多,也就是ID越小,优先权越大。在仲裁的时候,比如有上图中的3个Node同时发送数据,当他们同时发送帧ID的时候,CAN的特性之一就会起作用,隐性电平会被显性电平覆盖,也就是只要在同一时刻,CAN上既有Node发送隐性电平又有Node发送显性电平,那CAN上就只有显性电平,反过来说,只有当CAN上所有Node都只发送隐性电平的时候,CAN上才是隐性电平。这就是仲裁机制背后的物理机制。
然后接下来,我们继续谈谈仲裁的过程中到底发生了什么,继续上图的例子,在时刻5的时候,Node 2是隐性电平 ( 1 ) ,而其他Node是显性电平 ( 0 ) ,所以整个CAN上也是显性电平 ( 0 ) ,然后Node 2自己一对比自己的输入输出不同,很自觉得知道自己优先权比其他Node低,然后停止发送数据,转为监听模式,Node 1和Node 3继续仲裁。在时刻2的时候,Node 1是隐性电平 ( 1 ) ,而Node 3是显性电平 ( 0 ) ,所以Node 1也转为监听模式,最后当整个ID发送完,仲裁完成后,只有Node 3发现自己没事,就知道自己是优先权最大的那个,接下来就继续发送数据帧,而其他Node就暂停发送数据,一直监听Node 3的数据,直到Node 3发完数据,其他Node再继续仲裁下去,决定接下来的发送权。
3.0 STM32的CAN配置原理
3.1 图解CAN内部实现机构

                               
登录/注册后可看帖子
从图上我们可以看到,CAN 1与CAN 2为主从关系,CAN 1为Master ( 主 ) ,CAN 2为Slave ( 从 ) 。CAN 1和CAN 2有各自的3个发送邮箱,2个FIFO Buffer缓冲,6个接收邮箱。但是,28个Filter 过滤器却是共用的,我们可以规定,哪些Filter给那个CAN用,甚至可以在程序运行的时候调控。

                               
登录/注册后可看帖子

                               
登录/注册后可看帖子
上面俩图是发送邮箱和接收邮箱的具体的流程和机制。具体的细节就实在太多了,本文毕竟不是参考手册,想更加深入的看官,可以去ST官方的Reference Manual查阅具体细节。
3.2 Filter 过滤器
Filter 过滤器就很简单了,就是过滤接收到的每一帧的ID,如果符合特定条件,那就将该帧放入接收FIFO中。
Filter 过滤器有两种模式:
  • Identifier List Mode 标识符列表模式:它把要接收报文的 ID 列成一个表,要求报文 ID 与列表中的某一个标识符完全相同才可以接收,可以理解为白名单管理
  • Mask Mode 掩码模式:它把可接收报文 ID 的某几位作为列表,这几位被称为掩码,可以把它理解成关键字搜索,只要掩码(关键字)相同,就符合要求,报文就会被保存到接收FIFO


                               
登录/注册后可看帖子
每种模式又有对应的16 Bit位,32 Bit位模式,具体的使用方法和区别,本文不深入讨论,这部分内容再出个完整的教程都足够了,所以这部分留给客官去看Reference Manuel来理解。
3.3 如何通过Bit Rate 比特率来选择Time Quantum 时间量子

                               
登录/注册后可看帖子
该图生成于CAN Bit Time Calculation,可以看出在iRM2018的时钟树配置下,42MHz的CAN总线,最推荐的是黄色的那条,是稳定和高速的交际范围,越往上越快,但是越不稳定,越往下越稳定,但是越慢。因为C620电调和M3508电机接收的比特率是1Mbps,所以我们只能选择最上面的那个最快的那组参数。
3.4 特殊功能选项
  • Automatic Bus-Off Management 自动离线管理:可以在出错时离线后适时自动恢复,不需要软件干预
  • Automatic Retransmission 自动重传:使用本功能时,会一直发送报文直到成功为止

3.5 RoboMaster Assistant
在用串口转接器后,可以在PWM接口连接上PC的RoboMaster Assitant来调试电机,重要的是可以调整电机的CAN数据发送频率,适当调低可以降低CPU的接收压力,把计算资源留给其他更加重要的功能。
4.0 CAN的用法
  1. HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs);
复制代码
  • 参数

    • hcan:指向CAN配置结构体
    • ActiveITs:表明哪个中断会被启动,开启改中断的消息提示

  • 返回值

    • HAL_StatusTypeDef:如果开启成功,返回HAL_OK;如果失败,返回HAL_ERROR




  1. HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);
复制代码
  • 参数

    • hcan:指向CAN配置结构体

  • 返回值

    • HAL_StatusTypeDef:如果开启成功,返回HAL_OK;如果失败,返回HAL_ERROR




  1. HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig);
复制代码
  • 参数

    • hcan:指向CAN配置结构体
    • sFilterConfig:指向Filter过滤器配置结构体

  • 返回值

    • HAL_StatusTypeDef:如果开启成功,返回HAL_OK;如果失败,返回HAL_ERROR




  1. HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);
复制代码
  • 参数

    • hcan:指向CAN配置结构体
    • pHeader:指向发送数据的配置结构体
    • aData[]:指向需要发送的数据
    • pTxMailbox:该函数会返回用于储存发送数据的发送邮箱编号到该变量

  • 返回值

    • HAL_StatusTypeDef:如果添加成功,返回HAL_OK;如果失败,返回HAL_ERROR




  1. uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);
复制代码
  • 参数

    • hcan:指向CAN配置结构体
    • TxMailboxes:指向发送数据的发送邮箱

  • 返回值

    • uint32_t:如果有发送数据正在等待发送,返回1;如果没有,返回0




  [code]void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
  • 在写代码的时候,在main.c中创建HAL_CAN_RxFifo0MsgPendingCallback函数
  • 在该函数中填写在FIFO 0中已经没有正在等待接收的数据的时候开启中断,需要执行的代码



  HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
  • 参数

    • hcan:指向CAN配置结构体
    • RxFifo:指向负责接收的FIFO
    • pHeader:指向接收数据的配置结构体
    • aData[]:指向需要接收的数据

  • 返回值

    • HAL_StatusTypeDef:如果接收成功,返回HAL_OK;如果失败,返回HAL_ERROR


5.0 练习项目
5.1 项目简介
  • CAN电机控制:通过CAN控制电机,并且在按下按钮时通过CAN读取电机运行数据

5.2 项目代码
  因为论坛字数限制,详情请到 https://alchemicronin.github.io/posts/59eedfd8.html 观看
5.3 效果展示

跳转到指定楼层

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
顾问Alchemic Ronin
 楼主| 2020-5-12 08:08:52 显示全部楼层
Josh.Zhang 发表于 2020-5-10 22:05
两块板子间can通信搞过吗

一般用UART互相通讯,用CAN实在是大材小用了,通讯速度也没UART快

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
梯队队员Plaris
2022-3-24 12:22:38 显示全部楼层
博主,你的项目代码网址显示不出来!!!

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
工程Josh.Zhang
2020-5-10 22:05:43 显示全部楼层
两块板子间can通信搞过吗

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
梯队队员舟小羽
2020-4-30 18:41:52 显示全部楼层
好东西 顶一个

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
正式队员Mr.xue
2020-5-10 00:02:03 显示全部楼层
好东西没有人评论!

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
正式队员BruceLi
2020-5-10 15:41:45 显示全部楼层
围观学习~!
回复

使用道具 举报

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
正式队员没有梦想的咸鱼
2020-9-5 23:19:27 显示全部楼层
好东西,顶一个

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
梯队队员扫地僧
2020-10-5 09:51:45 显示全部楼层
这玩意不错啊

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
梯队队员lenkeble
2020-10-15 21:13:23 显示全部楼层
太好了,学习一波

[嵌入式] 【分享帖】论CAN总线对电机的控制与接收数据

[复制链接]
正式队员Artisans
2020-10-16 20:05:13 显示全部楼层
好东西 宝宝
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

触屏版 | 电脑版

Copyright © 2024 RoboMasters 版权所有 备案号 粤ICP备2022092332号

快速回复 返回顶部 返回列表