CAN协议
协议概述
教程:
- https://www.bilibili.com/video/BV1HY411D7Ar/ 视频有点长,倍速挑着看就好
- https://www.bilibili.com/video/BV1vu4m1F7Gt/ 协议部分简单了解即可,重点看外设结构部分
特征:
- 两根差分数据线(CAN_H、CAN_L),抗干扰,无需时钟线
- 总线上挂载多设备,异步通信,冲突时通过报文ID进行仲裁
- 报文长度1~8字节
- 广播式通信、请求-响应式通信
- 应答机制、CRC校验机制
- 分为低速和高速两种,电路连接和电平有所不同
差分信号
https://en.wikipedia.org/wiki/Differential_signalling
用两条平行的、等长的走线,传递互补的信号,利用两根线之间的电平差表示数值。
例如:RS485, USB, CAN差分信号抗干扰能力强,因为两根差分走线之间的耦合很好,当外界存在噪声干扰时,几乎是同时被耦合到两条线上,而接收端关心的只是两信号的差值,所以外界的共模噪声可以被完全抵消。
电路连接
高速/低速CAN的总线连接
显性电平/隐性电平:
- 和生物学到的显性基因/隐性基因类似
- 显性电平和隐性电平同时发送时,信号线上读取到的为显性电平
- 在CAN通信中,0为显性电平,1为隐性电平
- 两个设备分别同时发送0和1,信号线上读取到0
高速/低速CAN的电平标准
CAN收发器
帧格式
帧类型
- 数据帧:主动发送帧,发送数据,根据ID长度分为标准的和扩展的两种
- 遥控帧:主动发送帧,请求数据,根据ID长度分为标准的和扩展的两种
- 错误帧:硬件自动发送,出错时会发送
- 过载帧:硬件自动发送,忙碌时会发送
- 帧间隔:硬件自动发送,分割主动发送帧,以空出时间插入自动发送帧
数据帧格式
- 起始段(SOF):1bit,标志帧起始,显性电平0
- 仲裁段
- (ID):11bit,表示CANID,同时用于仲裁
- (RTR):1bit,数据帧为0,遥控帧为1
- 控制段:
- (IDE):1bit,标准帧为0,扩展帧为1
- (R0):1bit,保留位,0
- (DLC):4bit,数据长度
- 数据段:0~8bytes
- 校验段
- (CRC):15bit,CRC校验码
- (CRC delimiter):1bit,隐性电平1
- 回复段
- (ACK):1bit,接收设备控制,正确为0,错误为1
- (ACK delimiter):1bit,隐性电平1
- 结束段(EOF):7bit,隐性电平1
ID仲裁
概念:在同一个通信系统中,有时有多个设备想要同时发送信息。但是通信资源有限,当多个设备均想要占用同一个通信资源时,协议必须制定一种规则,旨在协调冲突,判断谁先应该占用资源,同时规定未占用资源的设备的行为。这就是仲裁。对于CAN这样的总线协议,数个设备直接连接到同一对线缆上,对线缆这个公用通信资源的仲裁尤其重要。
我们先理解只要有节点发送显性位,不论总线上其他节点如何发送,总线的整体状态一定是显性(逻辑0)。所有节点同步发送自己的ID的每一位时,查看总线状况。由于显性位会覆盖隐形位,于是对于节点来说,发送时只会有三种情况:自己发送隐性并且总线状态隐性、自己发送显性并且总线状态显性、自己发送隐性并且总线状态显性。
| 节点发送\总线上其它设备 | 显性(0) | 隐性(1) |
|---|---|---|
| 显性(0) | 继续发送 | 总线状态被自己覆盖为显性,相当于(显性,显性) |
| 隐性(1) | 终止发送(失去仲裁) | 继续发送 |
节点一边发送,一边接收。
- 如果节点发送的位与总线上的位相同,那么节点继续发送。
- 如果节点发送时,总线状态与自己发送的不一样,那么意味着这个节点的ID一定比某个同时发送的节点的大。那么根据CAN协议规定,这个节点失去仲裁。
这样一来,每个节点在发送自己ID的时候同步的进行了仲裁,任何接收端只需要一直接受就可以,总线是否有冲突与接收端无关,使得CAN系统不需要额外的时间来仲裁,非常高效。
举例:两节点ID分别为9和10
9(1001)
10(1010)
假设两节点同时发送数据。第一个时间段,两者同步发送1,总线为1,均继续发送。第二个时间段,两者同步发送0,总线为0,均继续发送。第二个时间段9发送0,10发送1,总线状态0。9继续发送,10看到总线状态与自己发送的不一致,于是中断之后所有发送。仲裁完成。9之后继续正常发送
位时序
概述
- CAN协议为异步协议,无时钟线。设定固定的波特率进行采样
- 由于晶振会随着温度变化而产生漂移,为了避免细微的时钟不一致,使得采样更加精确,设计以下的机制
- 将传输一个Bit的时间细分为多个阶段,每一段时长为若干Tq(最小的时间单位)
分段
- SS 同步段 1Tq 边沿跳变应该发生在这一段时间里
- PTS 传播时间段 1~8Tq 实际上电平跳变时可能会有震荡,为了等待数据线上的电压稳定下来而设置
- PBS1 相位缓冲段1 1~8Tq
- PBS2 相位缓冲段2 2~8Tq 通过调整PBS1和PBS2的时间长短,控制采样点的前后

硬同步(帧开始时同步)
- 开始发送,发送方开始计时,在SS时间段中将数据线驱动为逻辑低电平
- 在检测到SOF (Start Of Frame)下降沿时,接收方同步开始从SS段计时
再同步(逻辑电平跳变边沿不在SS段时再同步)
- 除了帧开始时的第一个下降沿,后续每个数据位都可以进行再同步
- 如果逻辑跳变发生在SS段前或后,则对应增加PBS1或者减少PBS2
- SJW:最大补偿的Tq数,用于防止单次补偿过度

STM32 CAN外设

发送
- 三个发送缓存(邮箱)
- CAN外设自动在总线空闲时从三个邮箱中选择一个进行发送
- 可以配置优先级
TXFP(TX Fifo Priority)- 1: 先请求先发送
- 0: 按报文ID优先级发送
- 如果发送失败,可以配置
NART(Not Allow ReTransmit)=1禁止自动重传
一个邮箱的状态图如下:

-
RQCP:发送请求已经完成
-
TXOK:发送成功
-
TME:发送邮箱空
-
ABRQ:终止发送
接收
- 两个三级接收FIFO缓存(邮箱)
- CAN外设接收到报文,进入过滤器匹配
- 如果报文符合过滤条件,则会被放入过滤器指定的一个FIFO
- 如果FIFO已满,有新的报文到达,可以配置
RFLM(Recieve Fifo Lock Mode)- 1: FIFO上锁,新到来的报文被丢弃
- 0: FIFO未上锁,丢弃队列中末尾(最晚到达)的报文,再放入新的报文
一个三级接收FIFO的状态图如下

过滤器

每一个过滤器有两个32位的寄存器,和以下几个过滤器配置位
-
FSCx(Filter Bank Scale):- 0: 每个过滤器使用4个16位寄存器,仅支持标准CAN地址长度 (将32位的寄存器拆成两个16位的使用,能更好的利用资源)
- 1: 每个过滤器使用2个32位寄存器,支持标准和扩展CAN地址长度
-
FBMx(Filter Bank Mode):- 0: 掩码模式 将新收到的报文ID和过滤器中的ID进行比较,但是仅比较Mask中为1的位(类似IP地址掩码)
- 1: 列表模式 将新收到的报文ID和过滤器中的ID进行比较,一个过滤器允许两个特定的报文ID
-
FACT(Filter ACTive): 过滤器使能开关 -
FFA(Filter Fifo Assignment): 通过过滤器的报文进入哪一个FIFO
掩码机制
配置为掩码模式时,过滤器将输入的报文ID和寄存器中的ID进行比较,但是仅比较二进制下,Mask中为1的位,其它位无论是什么都可以。
用公式来描述,满足以下公式的数据包,可以通过过滤器
CAN_ID & MASK == FILTER_ID & MASK
例子
- 屏蔽所有单数ID
Filter = 0
Mask = 1 - 接收 ID 范围在 0x100 ~ 0x1FF 的报文
Filter = 000100000000
Mask = 101100000000 - 接收 ID 为偶数且最高 4 位固定的报文
Filter = 10100000
Mask = 11110001
表示最高 4 位必须匹配(必须是0x1010),中间 3 位可以忽略,最低位必须为 0(偶数)
DJI电机
分类
| 电机型号 | 电调型号 | 减速比 | 驱动方式 | 链接 |
|---|---|---|---|---|
| snail | C615 | 电机直驱 | PWM | https://www.dji.com/cn/snail |
| 2006 | C610 | 36:1 | CAN+PWM | https://www.robomaster.com/zh-CN/products/components/general/M2006 |
| 3508 | C620 | 3591:187 | CAN+PWM | https://www.robomaster.com/zh-CN/products/components/general/M3508 |
| 6020 | 内置电调 | 电机直驱 | CAN+PWM | https://www.robomaster.com/zh-CN/products/components/general/gm6020/ |
编码器和减速箱
编码器:可以读取某个旋转轴的角度/速度信息。
对于没有减速箱的电机(6020),编码器可以直接读出输出轴角度
对于包含减速箱的电机(2006/3508),编码器安装在动力未经过减速箱之前的位置上(电机屁股上)。此时会出现问题:编码器同一个位置对应着电机总体动力输出轴的不同位置。
CAN通信与报文
电机ID
为了能在一根总线上挂载多个电机,每个电机有一个唯一的电机ID,范围1~8共8个可用ID。
可以观察电调绿灯闪烁次数,得知当前设置的电机ID。设置电机ID的方式请参考对应电调的说明书。
[!NOTE]
注意区分电机ID和CAN报文ID
通信报文
电调说明书里详细描述了大疆电机的通信报文。
根据电机ID的不同,电调会接收某个CAN ID上的控制报文,并且将自己的实时状态用另一个CAN ID发送到总线上。控制报文(8字节)包括16bit的字段“转矩电流”,它正比于电机的输出力矩。反馈报文(8字节)包括角度、转速、实际转矩电流、温度多个字段。
GM6020电机比较特殊,旧固件只能控制“转矩电压”,新固件可以在RoboMaster Assistant软件中开启“转矩电流”控制。
为了节省CAN带宽,控制报文设计为一个报文可以控制四个电机。一个控制报文有8字节,包括4个16bit的转矩电流字段,对应电机ID为1~4或5~8的电机。也就是说,多个电调侦听同一个CAN ID上的控制报文,并且将自己的数据用独立的CAN ID反馈。
| 电机ID | C610与C620 | 6020 电压|电流模式 |
|---|---|---|
| 1 | 0x200[0:1] / 0x201 |
0x1FF|0x1FE[0:1] / 0x205 |
| 2 | 0x200[2:3] / 0x202 |
0x1FF|0x1FE[2:3] / 0x206 |
| 3 | 0x200[4:5] / 0x203 |
0x1FF|0x1FE[4:5] / 0x207 |
| 4 | 0x200[6:7] / 0x204 |
0x1FF|0x1FE[6:7] / 0x208 |
| 5 | 0x1FF[0:1] / 0x205 |
0x2FF|0x1FE[0:1] / 0x209 |
| 6 | 0x1FF[2:3] / 0x206 |
0x2FF|0x1FE[2:3] / 0x20A |
| 7 | 0x1FF[4:5] / 0x207 |
0x2FF|0x1FE[4:5] / 0x20B |
| 8 | 0x1FF[6:7] / 0x208 |
不支持 |