3、CAN总线数据链路层:CAN帧结构(数据帧、远程帧、错误帧、过载帧、帧间隔)

各位工程师朋友,咱们今天聊聊CAN总线最核心的部分——数据链路层。说白了,就是CAN报文在线上到底长什么样。我刚开始接触CAN时,总觉得帧结构就是一堆0和1,没啥好研究的。直到有一次调试一个电机控制器,死活收不到数据,最后发现是远程帧用错了地方……嗯,从那以后我再也不敢小看这些帧类型了。

3.1 数据帧:最常用的“快递包裹”

数据帧,顾名思义,就是用来传输数据的。它就像你寄快递时填的那个面单——有发件人、收件人、包裹内容,还有各种校验信息。

一个标准数据帧(CAN 2.0A)长这样:

SOF + 11位ID + RTR + IDE + r0 + 4位DLC + 0~8字节数据 + 15位CRC + CRC分隔符 + ACK槽 + ACK分隔符 + EOF

我习惯把帧结构拆成三块来看:

  • 帧起始(SOF):1个显性位,告诉总线“我要开始说话了”。
  • 仲裁场:包含11位标识符(ID)和RTR位。ID越小,优先级越高。我在项目中遇到过两台设备同时发数据,ID小的那个总能抢到总线——这就是CAN的“无损仲裁”机制。
  • 控制场:IDE位、r0保留位,还有4位DLC(数据长度码)。DLC告诉你后面跟了多少字节数据,范围是0~8。
  • 数据场:0~8字节,你想传啥就传啥。我个人习惯把关键参数放在前两个字节,方便快速解析。
  • CRC场:15位CRC校验码 + 1位CRC分隔符。这是防错的关键,我曾经见过一个项目因为CRC计算错误,导致整个网络丢包率飙升。
  • ACK场:ACK槽 + ACK分隔符。发送方发出数据后,接收方会在ACK槽拉低电平,告诉发送方“我收到了”。如果没人应答,发送方就知道出问题了。
  • 帧结束(EOF):7个隐性位,表示帧结束。

重点提醒:标准帧ID是11位,扩展帧(CAN 2.0B)是29位。扩展帧的IDE位为1,标准帧为0。两者可以共存于同一总线,但扩展帧的仲裁优先级低于标准帧。

3.2 远程帧:只问不拿的“查询请求”

远程帧,说白了就是“我只问你要数据,但我自己不带数据”。它的结构和数据帧几乎一样,唯一的区别是RTR位为1(隐性)。

你想想看,什么时候会用远程帧?比如一个温度传感器,平时不主动发数据,只有主机发一个远程帧问它“温度多少?”,它才回复一个数据帧。这样可以减少总线负载。

我的经验:远程帧的DLC必须和对应数据帧的DLC一致。我曾经犯过一个低级错误——远程帧DLC设成2,但传感器回复的数据帧DLC是8,结果接收方直接丢弃了数据。嗯,细节决定成败。

3.3 错误帧:总线的“报警器”

错误帧是CAN总线自我保护的机制。当节点检测到错误时,它会主动发送错误帧,通知其他节点“刚才那帧有问题,别用了”。

错误帧由两部分组成:

  • 错误标志:6个连续显性位(主动错误)或6个连续隐性位(被动错误)。
  • 错误分隔符:8个隐性位。

为什么会这样设计?因为6个显性位会破坏CAN帧的位填充规则(连续5个相同位后必须插入一个相反位),其他节点检测到违规后,也会发送错误帧,形成“错误叠加”。

避坑指南:我曾经调试过一个设备,总线频繁出现错误帧。查了半天,发现是某个节点的晶振偏差太大,导致位时序错乱。记住,CAN总线的位采样点设置很关键,一般建议采样点在75%~85%之间。

3.4 过载帧:总线的“稍等一下”

过载帧,说白了就是“我太忙了,你慢点发”。当接收节点来不及处理数据时,它会发送过载帧,要求发送方延迟发送。

过载帧的结构和错误帧很像:

  • 过载标志:6个显性位。
  • 过载分隔符:8个隐性位。

不过,过载帧只能在帧间隔期间发送,不能在帧中间发送。这一点和错误帧不同。

我建议你在设计系统时,尽量避免频繁出现过载帧。如果某个节点总是发过载帧,说明它的处理能力跟不上总线速度,该升级硬件了。

3.5 帧间隔:帧与帧之间的“呼吸间隙”

帧间隔,就是两帧之间的空闲时间。它让总线有时间“喘口气”,也让节点有机会判断总线是否空闲。

帧间隔由三部分组成:

  • 间歇场:3个隐性位。
  • 总线空闲:任意长度的隐性位,直到有节点开始发送。
  • 暂停发送场:仅被动错误节点需要,8个隐性位。

你想想看,如果没有帧间隔,节点怎么知道上一帧结束了?怎么判断总线是否空闲?所以这个“呼吸间隙”虽然小,但必不可少。

3.6 五种帧的对比总结

帧类型 用途 RTR位 数据场 触发条件
数据帧 传输数据 0(显性) 0~8字节 节点主动发送
远程帧 请求数据 1(隐性) 节点主动发送
错误帧 报告错误 检测到错误
过载帧 延迟发送 接收节点忙
帧间隔 帧间分隔 每帧结束后

3.7 实战中的帧结构分析

最后,我分享一个实战技巧。当你用CAN分析仪抓包时,看到一帧数据,怎么快速判断它是哪种帧?

  1. 先看SOF之后的第一位——如果是显性(0),就是数据帧;如果是隐性(1),就是远程帧。
  2. 如果帧中间突然出现6个连续显性位,那就是错误帧或过载帧。怎么区分?看它出现在帧的哪个位置——错误帧可以在帧的任何位置出现,过载帧只能在帧间隔期间出现。
  3. 帧结束后,如果总线空闲时间超过3个位时间,那就是帧间隔。

一句话总结:数据帧是“送货上门”,远程帧是“下单催货”,错误帧是“报警投诉”,过载帧是“稍等片刻”,帧间隔是“中场休息”。把这五种帧搞明白了,CAN总线通信你就掌握了七成。

好了,这一章就到这里。下一章咱们聊聊CAN总线的位时序和同步机制——这可是保证所有节点“步调一致”的关键。到时候见!