2、CAN总线基础:从物理层到仲裁机制

各位同学,今天我们正式进入CAN总线的核心地带。说实话,CAN总线看起来简单,但真正把它吃透的人并不多。我在车载项目里摸爬滚打这么多年,见过太多因为CAN基础不牢导致的“灵异现象”——比如报文莫名其妙丢了,或者总线突然挂死。其实,这些问题大多出在物理层和数据链路层。

好,我们一步步来拆解。

2.1 CAN总线物理层:信号怎么在线上跑?

CAN总线物理层,说白了就是解决“0和1怎么在两根线上传输”的问题。它用的是差分信号,也就是CAN_H和CAN_L两根线。

关键点:

  • 显性电平(Dominant):CAN_H比CAN_L高约2V(通常CAN_H=3.5V,CAN_L=1.5V),代表逻辑“0”。
  • 隐性电平(Recessive):CAN_H和CAN_L电压接近(约2.5V),代表逻辑“1”。

嗯,这里要注意:显性电平会“覆盖”隐性电平。也就是说,只要有一个节点发送显性位,总线就是显性。这个特性,直接决定了后面的仲裁机制。

我个人的习惯:在设计CAN节点时,一定要用示波器看CAN_H和CAN_L的波形。如果差分电压低于1.2V,通信就会不稳定。我曾经在一个项目中,因为线束过长导致信号衰减,折腾了整整两天才找到原因。

避坑指南:我曾经遇到过终端电阻没接对的情况。CAN总线两端各需要120Ω电阻,少一个都不行。少了,信号反射会导致误码;多了,驱动能力不够。

2.2 CAN总线数据链路层:帧是怎么组织的?

数据链路层负责把物理层的比特流组装成有意义的“帧”。CAN有四种帧类型:数据帧、远程帧、错误帧、过载帧。我们一个一个说。

2.2.1 数据帧(Data Frame)

这是最常用的帧,用来传输实际数据。标准格式有11位ID,扩展格式有29位ID。我个人建议:能用标准帧就别用扩展帧,因为扩展帧的仲裁场更长,总线利用率会低一些。

数据帧结构:

  • 帧起始(SOF):1位显性位,同步所有节点。
  • 仲裁场:11位ID(标准)或29位ID(扩展)+ RTR位(远程帧请求位)。
  • 控制场:IDE位、保留位、DLC(数据长度码,4位)。
  • 数据场:0~8字节数据。
  • CRC场:15位CRC校验 + 1位CRC界定符。
  • ACK场:1位ACK槽 + 1位ACK界定符。
  • 帧结束(EOF):7位隐性位。

注意:DLC虽然只有4位,但最大只能表示8。所以CAN数据帧最多带8字节数据。别问我为什么不能更多——这是协议规定的,为了实时性。

2.2.2 远程帧(Remote Frame)

远程帧用来请求数据。它没有数据场,但RTR位是显性(数据帧的RTR是隐性)。你想想看,一个节点发远程帧,另一个节点收到后就会发对应的数据帧。

我在项目中很少用远程帧。为什么呢?因为远程帧的优先级和对应的数据帧ID相同,容易造成总线冲突。我建议用定时发送数据帧的方式代替远程帧请求。

2.2.3 错误帧(Error Frame)

当节点检测到总线错误时,会主动发送错误帧。错误帧由6个显性位(错误标志)和8个隐性位(错误界定符)组成。

错误类型:

  • 位错误:发送节点监控总线,发现发送的位和总线上的位不一致。
  • 填充错误:连续5个相同电平后没有填充位。
  • CRC错误:接收节点计算的CRC和发送的不一致。
  • 形式错误:固定格式的位(如EOF)出现错误电平。
  • ACK错误:发送节点没有收到ACK应答。

警告:我曾经遇到过一个节点频繁发送错误帧,导致整个总线瘫痪。最后发现是它的晶振偏差太大,导致位时序不对。所以,CAN节点的时钟精度一定要控制在1%以内。

2.2.4 过载帧(Overload Frame)

过载帧用于节点忙不过来时请求延迟。它和错误帧结构类似,但触发条件不同。说实话,我在实际项目中几乎没见过过载帧——现在的MCU处理能力都够强。

2.3 CAN总线仲裁机制:谁先说话?

这是CAN总线最巧妙的地方。多个节点同时发送时,怎么决定谁先发?答案是:按ID优先级仲裁

仲裁过程是这样的:

  1. 所有节点同时发送帧起始(SOF)和ID位。
  2. 每个节点在发送每一位时,都会监控总线电平。
  3. 如果某个节点发送隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发送。这个节点立即停止发送,转为接收。
  4. ID值越小,优先级越高(因为显性位多)。

为什么会这样?因为显性位覆盖隐性位。你想想看,如果两个节点同时发,一个ID=0x100,另一个ID=0x200,在ID的第1位,0x100发0(显性),0x200发1(隐性),总线是显性,0x200就知道自己输了,乖乖退出发送。

关键点:仲裁不会破坏数据。因为仲裁过程中,所有节点发送的ID位都是同步的,仲裁失败的节点只是停止发送,不会影响总线上的数据完整性。

我在项目中遇到过一个问题:两个节点ID相同,同时发送数据帧和远程帧。结果数据帧的RTR是隐性,远程帧的RTR是显性,远程帧赢了。但远程帧没有数据场,接收节点收到后一脸懵。所以,ID必须唯一,这是铁律。

2.4 知识体系总览

下面这张图,是我自己总结的CAN总线基础框架。你可以把它当作一个“地图”,随时回来对照。

CAN总线基础:知识体系 物理层 • 差分信号:CAN_H/CAN_L • 显性电平:逻辑0 • 隐性电平:逻辑1 • 终端电阻:120Ω×2 • 位时序:Tq、采样点 数据链路层 • 数据帧:0~8字节 • 远程帧:请求数据 • 错误帧:错误标志 • 过载帧:延迟请求 • 帧格式:标准/扩展 仲裁机制 • 按ID优先级仲裁 • 显性位覆盖隐性位 • ID越小优先级越高 • 无损仲裁 • ID必须唯一 核心要点总结 1. 物理层是基础:差分信号抗干扰能力强,适合车载环境。 2. 数据帧最常用:标准帧11位ID,扩展帧29位ID,优先用标准帧。 3. 错误帧是“救火队”:一旦发现错误,立即通知所有节点。 4. 仲裁机制是灵魂:无损仲裁,保证高优先级报文实时性。 5. 避坑:ID唯一、终端电阻、时钟精度,缺一不可。

我的建议:学CAN总线,别死记硬背帧格式。你只要记住“物理层管信号,数据链路层管帧,仲裁管优先级”这个逻辑链,剩下的细节用到时再查都来得及。

好了,这一章的内容就到这里。CAN总线的基础打牢了,后面讲网络管理和诊断协议时,你才会觉得“哦,原来如此”。


公众号:蓝海资料掘金营,微信deep3321