1. CAN总线基础:从物理层到仲裁机制

各位同学好,我是老周。做嵌入式网络这行十几年了,CAN总线算是我打交道最多的现场总线之一。今天咱们就从最基础的东西聊起——CAN协议到底是什么、物理层有啥讲究、数据帧长什么样、仲裁又是怎么玩的。

说实话,很多工程师一上来就调网关、配路由,结果遇到总线冲突、丢帧、波特率对不上,折腾半天才发现是基础没打牢。我个人习惯是:先把CAN的底子摸透,再碰硬件和协议栈。你想想看,连帧结构都分不清,怎么去配置CAN转以太网的网关?

1.1 CAN协议概述——为什么它能在工业现场活这么久?

CAN(Controller Area Network)是上世纪80年代Bosch为汽车开发的串行通信协议。后来工业自动化、医疗设备、机器人全用上了。为什么?因为它有三个硬本事:

  • 多主通信——总线上任何节点都能主动发数据,不需要主站轮询
  • 实时性强——优先级高的报文永远先走,延迟可预测
  • 错误处理机制完善——5种错误检测+自动重发,误码率极低

我在一个AGV项目里遇到过这种情况:8个电机控制器挂同一条CAN总线,如果用Modbus轮询,一圈下来几百毫秒,车早撞了。换成CAN,高优先级的急停报文2微秒内就能抢到总线。这就是CAN的硬实时能力。

核心要点:CAN不是最快的总线(最高1Mbps),但它是确定性最强的总线之一。在工业现场,确定性比峰值速度更重要。

1.2 CAN物理层特性——差分信号到底好在哪?

CAN物理层用的是差分信号,两条线:CAN_H和CAN_L。逻辑1叫隐性位,逻辑0叫显性位。显性位会覆盖隐性位——这个特性是仲裁机制的基础。

参数 典型值 说明
总线电平(显性) CAN_H=3.5V, CAN_L=1.5V 差分电压约2V
总线电平(隐性) CAN_H=2.5V, CAN_L=2.5V 差分电压约0V
最大速率 1 Mbps 总线长度≤40m
最大距离 10 km 速率需降至5 kbps以下
终端电阻 120 Ω 总线两端各一个

差分信号的好处很明显:抗共模干扰。工厂里电机启停、变频器开关,电磁环境一塌糊涂。单端信号早被淹没了,但CAN的差分对能把这些共模噪声抵消掉。我曾经在一条200米长的CAN总线上测过,旁边就是380V动力电缆,照样跑125kbps没丢一帧。

注意:终端电阻必须加,而且只能加在总线两端。少了会有信号反射,多了会拉低差分电压。我见过有人图省事只加一个120Ω,结果总线长度超过100米就开始丢帧。

1.3 CAN数据帧结构——报文里到底装了啥?

CAN数据帧分两种:标准帧(11位ID)和扩展帧(29位ID)。咱们做网关配置时,帧格式必须搞清楚,否则路由表配了也白配。

先看标准帧的结构:

SOF | 11位ID | RTR | IDE | r0 | DLC | 0~8字节数据 | CRC | ACK | EOF

每个字段的作用:

  • SOF(1位)——帧起始,同步所有节点
  • ID(11位)——标识符,决定优先级,数值越小优先级越高
  • RTR(1位)——远程帧标志,0=数据帧,1=远程帧
  • IDE(1位)——扩展标志,0=标准帧
  • DLC(4位)——数据长度,0~8字节
  • Data(0~64位)——实际数据
  • CRC(15位)——循环冗余校验
  • ACK(2位)——应答槽,接收节点拉低表示收到
  • EOF(7位)——帧结束

扩展帧就是把11位ID换成29位,多出来的18位放在标准ID后面。我建议你在做CAN转以太网网关时,优先支持标准帧。因为工业现场90%的设备用的都是11位ID,扩展帧多见于J1939这类高层协议。

经验之谈:DLC字段很多人忽略。我曾经遇到一个设备,明明只发了2字节数据,DLC却填了8。网关收到后把后面6个空字节也转发到以太网,导致上位机解析出错。记住:DLC必须与实际数据长度一致。

1.4 CAN总线仲裁机制——谁先说话?

这是CAN最精彩的设计。多个节点同时发数据怎么办?靠ID仲裁。

原理很简单:总线是线与逻辑。显性位(0)会覆盖隐性位(1)。每个节点在发送ID时,同时监听总线电平。如果自己发的是隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发数据,自己立刻退出发送,转为接收。

举个例子:

  • 节点A发ID=0x100(二进制 0001 0000 0000)
  • 节点B发ID=0x200(二进制 0010 0000 0000)
  • 从最高位开始比,第3位A是0,B是1,A的显性位覆盖了B的隐性位
  • B检测到总线与自己的发送不一致,立即退出
  • A继续发送,直到整帧结束

整个过程在微秒级完成,而且没有数据丢失。退出的节点会在总线空闲后自动重发。

关键结论:ID数值越小,优先级越高。0x000是最高优先级,0x7FF是最低优先级(标准帧)。配置网关路由时,高优先级报文(如急停、故障)的ID要尽量小。

下面这张图展示了仲裁过程的完整流程:

CAN总线仲裁流程 节点A (ID=0x100) 节点B (ID=0x200) CAN 总线 仲裁过程(逐位比较) 位1: A=0, B=0 → 相同,继续 位2: A=0, B=0 → 相同,继续 位3: A=0 (显性), B=1 (隐性) → A获胜! A 继续发送数据帧 B 退出,等待重发 仲裁结果:ID=0x100 优先级高于 ID=0x200 总线空闲后,B自动重发,无需软件干预

仲裁机制带来的好处很明显:

  • 无破坏性仲裁——高优先级报文不受影响,低优先级自动退让
  • 实时性有保障——最坏等待时间可计算,适合硬实时系统
  • 总线利用率高——没有碰撞浪费,仲裁本身不消耗额外带宽
避坑指南:我曾经在一个项目中,把两个急停按钮的ID都配成了0x001。结果同时按下时,两个节点ID完全一样,仲裁无法分出胜负,总线直接报错。记住:同一总线上不允许有两个节点使用完全相同的ID。

1.5 小结——CAN基础决定了网关的上限

好了,这一章的内容就这些。CAN的物理层、帧结构、仲裁机制,这三块是后面配置CAN转以太网网关的基石。你想想看:

  • 不懂物理层,你连终端电阻该加在哪都不知道
  • 不懂帧结构,你连DLC填错了都发现不了
  • 不懂仲裁机制,你配的路由优先级可能全是反的