CAN 协议层
协议帧格式概览
协议层定义了数据在总线上的封装格式。CAN 协议主要包含以下几种帧格式:
帧类型 |
主要用途 |
发送时机/约束 |
关键特点 |
|---|---|---|---|
数据帧 |
传输实际数据 |
|
|
远程帧 |
请求特定 ID 的数据 |
|
|
错误帧 |
通知全局总线错误 |
|
|
过载帧 |
延迟下一帧接收 |
|
|
帧间隔 |
物理分隔连续的帧 |
|
|
数据帧
数据帧(Data Frame)是 CAN 总线进行数据传输的常用类型,用于节点间的数据传输。
标准数据帧采用 11-bit 标识,格式如下:
标准数据帧
扩展数据帧采用 29-bit 标识符 (11-bit Base ID + 18-bit Extension ID),用于大型网络,格式如下:
扩展数据帧
关键字段解析
帧结构由显性位(逻辑 0)起始,以连续的隐性位(逻辑 1)结束。完整的数据帧由七个功能段组成,依序为:帧起始、仲裁段、控制段、数据段、CRC 段、ACK 段及帧结束。
功能段 (Field) |
组成/位定义 |
技术说明 |
|---|---|---|
帧起始 (SOF) |
Start Of Frame,1 位 (显性) |
标识帧开始,用于硬同步。 |
仲裁段 |
ID, RTR, IDE, SRR |
|
控制段 |
DLC (4 位), r0/r1 |
DLC: Data Length Code,指示数据字节数 (0-8)。r0/r1 为保留位。 |
数据段 |
0-8 字节 |
有效载荷,MSB 先行。 |
CRC 段 |
CRC 序列(15 位) + 界定符 |
硬件计算校验码,界定符为隐性位。 |
ACK 段 |
ACK 槽 + 界定符 |
发送方发隐性,接收方拉低为显性以应答。 |
帧结束 (EOF) |
7 位 (隐性) |
标识帧结束,无位填充。 |
远程帧
用于接收节点向发送节点请求数据。与数据帧的主要区别在于: RTR 位为隐性 (1) 且 无数据段。格式如 标准远程帧 和 扩展远程帧 所示。
标准远程帧
扩展远程帧
错误帧
当节点检测到总线错误时发送,由错误标志 (6 bits) 和错误界定符 (8 bits) 组成。图 主动错误帧 和 被动错误帧 展示了两种帧格式。 由于不同节点可能在不同时间点检测到错误并发送错误帧,导致总线上的错误标志位叠加,最终的错误标志位间可能在 6 到 12 个位之间,可参考 错误检测和管理 获取详细信息。
主动错误帧
被动错误帧
过载帧
当接收节点未准备好接收下一帧数据时发送,用于在两帧之间插入额外延时。过载帧格式如下:
过载帧的发送时机可参考 发送过载帧。
帧间隔
帧间隔用于分隔数据帧和远程帧的帧。帧间隔格式如下:
数据帧和远程帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、远程帧、错误帧、过载帧)分开。
过载帧和错误帧前不能插入帧间隔。
其中:
Intermission:在前一帧报文(EOF 或 错误界定符)结束后,总线必须保持 3 个位的隐性电平(1)
Suspension:当发生错误时,
如果一个节点处于 主动错误 状态,节点发完一帧,休息完 3 bit 的 Intermission 后,可以立刻争抢总线发送下一帧
如果一个节点频繁出错,变成了 被动错误 状态,协议规定它在发完一帧后,必须额外多等 8 个隐性位(suspension)。
Bus idle:如果上面两个阶段都过完了,总线上依然没有数据,那就进入“空闲状态”。此时总线一直维持隐性(1)。任何节点只要想发数据,随时可以把电平拉低(0)来启动发送(即发送 SOF 位)。
位时序与同步机制
CAN 采用异步串行通信,收发双方需约定波特率。为解决时钟漂移和传输延迟问题,ISO 11898 定义了基于 时间量子 (Time Quantum, Tq) 的位时序分解与同步机制。
Bit 分解
根据 ISO 11898-1 标准,总线上的一个 Bit 时序分为四个段:
单个 Bit 分解后的最小单位是 Time quantum(Tq),单位大小为 prescaler/core clk,其中 core clk 是 CAN 的时钟源输入。一个完整的 Bit 位一般由 8-25 个 Tq 组成。
同步段 (Sync_Seg) :用于判断 总线上信号的跳变是否恰好在 Sync_Seg 段内,如果是,则表明通信节点和总线同步
传播段 (Prop_Seg) :用于补偿信号在物理线路上的传输延迟及收发器内部延迟。电信号在总线上传播需要时间,例如在总线仲裁阶段,如果未预留这时间,节点 A 发送的信号还未到达对面节点 B,节点 A 就开始采样,此时采样错误
相位缓冲段 1 (Phase_Seg1) :该段是采样前的弹性缓冲, 紧挨着采样点 。如果当前 Bit 的 Sync_Seg 发现信号跳变晚了(在 Sync_Seg 后面),说明当前 Bit 来得迟,为了不让采样点来得太早,因此需要延长此段
相位缓冲段 2 (Phase_Seg2) :该段是采样后的弹性缓冲。如果当前 Bit 的 Sync_Seg 发现信号跳变早了(快了),说明当前 Bit 的结束的太早,需要缩短 Phase_Seg2 来使得下一 Bit 可以被正确采样
采样点 (Sample Point) 位于 Phase_Seg1 的结束时刻。通过控制各段的长度,可以对采样点的位置进行偏移,以便准确采样。
下表给出了各个段的参考范围。
参数 |
取值范围 |
描述 |
|---|---|---|
位时间预分频器 (Prescaler) |
1 ~ 32 |
Tq = prescaler / core_clk |
Sync_Seg |
1 个 Tq (固定) |
同步总线上的各个 CAN 节点 |
Prop_Seg |
1 ~ 8 个 Tq |
补偿网络内的物理延迟时间 |
Phase_Seg1 |
1 ~ 8 个 Tq |
补偿边缘相位误差,在同步过程中可能会暂时延长 |
Phase_Seg2 |
2 ~ 8 个 Tq |
补偿边缘相位误差,在同步过程中可能会暂时缩短 |
SJW |
1 ~ 4 个 Tq |
不能长于任意一个相位缓冲段 (Phase_Seg1/2) |
通信波特率
CAN 节点的通信速率是传输单个 Bit 的 Tq 总数的倒数,例如时钟源是 40MHz,分频系数是 2,则单个 Tq 的时间是 0.05us。假设单个 Bit 占用 20 个 Tq,则波特率结果为:
Baud Rate = core_clk / (BRP × Total Tq) = 1000000 baud/s
同步过程
前面约定的每个数据 bit 的段划分,并未涉及到相位细节。根据 ISO 11898 标准,同步分为:
硬同步 :仅在当存在“帧起始信号(SOF)”时起作用
重新同步 :在 SOF 后续信号时起作用
两者都使用 Sync_Seg 段来进行检测,同步的目的都是使节点内的 Sync_Seg 段把跳变沿包含起来
硬同步
当 总线空闲结束 时,第一个帧起始信号 SOF 到来。接收节点检测到总线的 SOF 不在节点内部时序的 SS 段范围,所以判断自己内部时序与总线不同步。此时接收节点会强行将 Bit Time 计数器清零,强行将 Sync_Seg 段对齐到 SOF 信号的下降沿。同步后采样便可正确进行。
硬同步
以图 硬同步 为例,
发送节点 Node_A 在发送 SOF 位时,SOF 位的下降沿在 SS 段
这个时候接收节点 Node_B 发现自己当前位的 SS 段和发送节点 SOF 位的 SS 段不同步。也就是说当 Node_A 产生 SOF 位 SS 段时,Node_B 的当前位的 SS 段已经在 5 个 Tq 之前产生了;
于是接收节点 Node_B 强行将自己当前位的 SS 段拉到与 SOF 位的 SS 段同步
重新同步
在帧传输过程中(除 SOF 跳变外),每次检测到 隐性到显性(高电平至低电平)的跳变沿 时进行重新同步。以总线跳变沿与 Sync_Seg 段的相对位置进行区分,重新同步可分为:
相位超前时的重新同步,如图 相位超前时的重新同步 所示。
发送节点 Node_A 比接收节点 Node_B 的慢,也就是 Node_A 当前位的 ss 段产生的时候,Node_B 当前 Bit 的 ss 段已经在 2 个 Tq 之前产生
所以这个时候接收节点 Node_B 就将 PBS1 延长 2 个 Tq 的时间
于是此时 Node_A 当前位的采样点就和 Node_B 的采样点同步
相位滞后时的重新同步,如图 相位滞后时的重新同步 所示。
发送节点 Node_A 当前位的 SS 段诞生 2Tq 时长之后,接收节点 Node_B 的当前位才产生 SS 段
于是,接收节点 Node_B 当前位的 PBS2 段缩短
这样就会导致接收节点 Node_B 的下一 Bit 能够提前 2 个 Tq,从而 Node_B 的下一 Bit 采样点和 Node_A 下一 Bit 的采样点能够同步。
相位超前时的重新同步
相位滞后时的重新同步
重新同步时,Phase_Seg1 增加和 Phase_Seg2 减少的这段时长被定义为 重新同步补偿宽度 SJW (reSynchronization Jump Width),单次同步的时候不能增加或减少超过 SJW 的时间长度。若有需要, 控制器会通过多次小幅度调整来实现同步。 当控制器设置的 SJW 较大时,可以吸收的误差加大,但通信速度会下降。