· CAN

CAN

3199 字
16 分钟
CAN
StarryLin/Geek · 摘要

CAN是差分多主总线,用ID位仲裁实现非破坏性优先级,并靠CRC、ACK与位填充检错,CAN FD为其延伸。

CAN 总线入门:汽车与工业的”神经网络”#

前面聊了 UART、RS-485、I2C、SPI 这些”点对点/主从”通信。今天进入真正的多主对等网络——CAN(Controller Area Network)。它是汽车电子、工业控制、医疗设备里无处不在的”神经系统”。


目录#

  1. CAN 是什么
  2. 物理层:差分信号与显性/隐性
  3. 数据帧格式
  4. 遥控帧
  5. 位填充:给时钟”打节拍”
  6. 总线仲裁:谁小谁说话
  7. ACK 机制
  8. 协议对比与选型
  9. CAN 的独到之处
  10. CAN FD 延伸

一、CAN 是什么#

CAN 全称 Controller Area Network(控制器局域网),由博世(Bosch)在 1986 年提出。它的设计目标非常明确:

  • 不需要主机,任何设备都可以在总线空闲时主动发送
  • 抗干扰极强,专为汽车发动机舱、工厂车间等恶劣环境设计
  • 高可靠性,硬件层面自带错误检测和自动重发机制

如今从汽车 ECU、电池管理系统(BMS),到电梯控制、工业机器人、医疗设备,CAN 总线都是标配。


二、物理层:差分信号与显性/隐性#

CAN 在物理层采用差分传输,使用一对双绞线:

信号线名称
CAN_H高电平线
CAN_L低电平线

CAN 不直接定义”高电平=1,低电平=0”,而是看两根线之间的电位差:

状态CAN_HCAN_L差分电压逻辑值
显性(Dominant)~3.5V~1.5V≈ 2V逻辑 0
隐性(Recessive)~2.5V~2.5V≈ 0V逻辑 1

注意:CAN 的逻辑是反直觉的——有电压差(显性)= 0,无电压差(隐性)= 1。这是为了配合后面的”线与”仲裁机制。

收发器与终端电阻#

CAN 控制器(芯片内部)不能直接挂到总线上,中间必须加 CAN 收发器(如 TJA1051、SN65HVD230)。收发器负责把逻辑电平转成差分信号。

总线拓扑是总线型,所有设备的 CAN_H 接在一起,CAN_L 接在一起。总线两端必须各接一个 120Ω 终端电阻,用于阻抗匹配、防止信号反射。

graph LR subgraph CAN_Bus[CAN 总线] direction LR BUS_H[CAN_H 主线] BUS_L[CAN_L 主线] end ECU1[ECU1: 发动机<br/>控制器+收发器] -->|TX/RX| T1[收发器] T1 -->|CAN_H| BUS_H T1 -->|CAN_L| BUS_L ECU2[ECU2: 仪表盘<br/>控制器+收发器] -->|TX/RX| T2[收发器] T2 -->|CAN_H| BUS_H T2 -->|CAN_L| BUS_L ECU3[ECU3: ABS<br/>控制器+收发器] -->|TX/RX| T3[收发器] T3 -->|CAN_H| BUS_H T3 -->|CAN_L| BUS_L R1[120Ω 终端电阻] --- BUS_H R1 --- BUS_L R2[120Ω 终端电阻] --- BUS_H R2 --- BUS_L style BUS_H fill:#e1f5e1,stroke:#333 style BUS_L fill:#ffe1e1,stroke:#333 style R1 fill:#ffcc99 style R2 fill:#ffcc99

线与特性#

CAN 总线有一个核心特性:显性会覆盖隐性。

  • 如果所有设备都”不说话”(隐性),总线就是隐性(逻辑 1)
  • 只要有一个设备发送显性(逻辑 0),总线就被拉成显性

这类似于 I2C 的”线与”,但 CAN 是差分层面的线与。这个特性是实现”非破坏性仲裁”的基础。


三、数据帧格式#

CAN 协议中,用于实际传输数据的是数据帧。CAN 是广播式的:发送方把帧丢到总线上,所有节点都能收到,由接收方自己判断要不要处理。

标准帧(Standard Frame,11 位 ID)#

graph LR A[SOF<br/>1 bit<br/>值: 0] --> B[仲裁段<br/>ID: 11 bit<br/>RTR: 1 bit] B --> C[控制段<br/>IDE: 1 bit<br/>r0: 1 bit<br/>DLC: 4 bit] C --> D[数据段<br/>0 ~ 8 字节] D --> E[CRC 段<br/>CRC: 15 bit<br/>界定符: 1 bit] E --> F[ACK 段<br/>ACK 槽: 1 bit<br/>界定符: 1 bit] F --> G[EOF<br/>7 bit<br/>值: 1] style A fill:#ff9999,stroke:#333 style B fill:#ffcc99,stroke:#333 style C fill:#ffff99,stroke:#333 style D fill:#99ff99,stroke:#333 style E fill:#99ffff,stroke:#333 style F fill:#cc99ff,stroke:#333 style G fill:#ff99cc,stroke:#333
字段长度说明
SOF1 bit起始位,固定为 0(显性),标志帧开始
ID11 bit报文标识符,决定优先级,数值越小优先级越高
RTR1 bit0 = 数据帧,1 = 遥控帧
IDE1 bit0 = 标准帧,1 = 扩展帧
r01 bit保留位,固定为 0
DLC4 bit数据长度码,0~8,表示数据段字节数
DATA0~64 bit实际数据,长度必须是 8 的倍数(0~8 字节)
CRC15 bit循环冗余校验,用于检错
CRC 界定符1 bit固定为 1(隐性),分隔 CRC 和 ACK
ACK 槽1 bit接收方在此位发送 0(显性)表示”收到且正确”
ACK 界定符1 bit固定为 1(隐性),分隔 ACK 和 EOF
EOF7 bit帧结束,连续 7 个 1(隐性)

扩展帧(Extended Frame,29 位 ID)#

当 11 位 ID 不够用时(比如大型汽车网络),CAN 支持扩展帧:

字段长度说明
SRR1 bit固定为 1,无实际意义,仅用于兼容标准帧格式(占位)
IDE1 bit固定为 1,表示扩展帧
ID 总长度29 bit前 11 位 + 后 18 位

扩展帧的优先级永远低于同等前缀的标准帧,这是协议设计时故意为之的兼容性策略。


四、遥控帧:请求数据#

除了数据帧,CAN 还定义了遥控帧(Remote Frame)。它的结构和数据帧几乎一样,但有两个关键区别:

  1. RTR = 1
  2. 没有数据段(DATA 字段)

遥控帧的作用是请求数据。当节点 A 想要节点 B 的某个数据时,A 发送一个遥控帧(带上对应的数据帧 ID)。节点 B 收到后,会返回一帧对应 ID 的数据帧作为应答。

节点A: [遥控帧: ID=0x123, RTR=1, 无数据] ──→ 总线
节点B: ──→ [数据帧: ID=0x123, RTR=0, DATA=...]

五、位填充:给时钟”打节拍”#

CAN 规定:发送方在发送时,如果检测到连续 5 个相同的位,就必须自动插入1 个相反的位。接收方收到后,再自动移除这个填充位。

graph LR subgraph 发送端处理 D1[原始数据:<br/>00000 11111] OP1[发送方检测:<br/>连续 5 个相同位] D2[线路实际发送:<br/>00000<b style="color:red">1</b> 11111<b style="color:red">0</b>] end subgraph 接收端处理 OP2[接收方检测:<br/>连续 5 个相同位] D3[恢复原始数据:<br/>00000 11111] end D1 --> OP1 OP1 -->|插入反位| D2 D2 -.->|总线传输| OP2 OP2 -->|移除填充位| D3 style D2 fill:#ffcc99,stroke:#333

为什么要位填充?#

CAN 是异步串行通信,收发双方靠各自的时钟采样。为了保证长期同步,CAN 采用两种同步机制:

  1. 硬同步(Hard Synchronization):检测到 SOF(起始位)的下降沿时,立即把采样点重置到该位中心
  2. 再同步(Resynchronization):帧传输过程中,每次检测到跳变沿(0→1 或 1→0),就微调采样点

但如果数据中出现一长串连续的 0 或连续的 1,总线上就没有跳变沿,再同步就会失效,时钟漂移累积后导致采样错位。

位填充强制制造跳变沿,确保每 5 位至少有一次翻转,给接收方的时钟恢复电路提供”对表”的机会。


六、总线仲裁:谁小谁说话#

CAN 总线是多主结构,任何节点都可以在总线空闲时发起通信。但如果两个节点同时开始发送,怎么办?

CAN 的解决方案是非破坏性仲裁(Non-destructive Arbitration):

仲裁规则#

  1. 总线空闲时,任何节点都可以开始发送
  2. 如果多个节点同时发送,它们从报文 ID 的最高位开始逐位比较
  3. 每个节点在发送每一位的同时,回读总线状态
  4. 如果某节点发送了隐性 1,但回读到显性 0,说明有别的节点在发 0,该节点立即退出竞争,转为接收方
  5. 最终,ID 数值最小的节点(二进制 0 最多的)赢得总线,继续发送完整帧
sequenceDiagram participant NodeA as 节点 A<br/>ID: 0x6A5 participant Bus as CAN 总线 participant NodeB as 节点 B<br/>ID: 0x6A3 Note over NodeA,NodeB: 总线空闲,两节点同时开始发送 NodeA->>Bus: 位1: 发送 1 NodeB->>Bus: 位1: 发送 1 Bus-->>NodeA: 回读: 1 ✓ 一致 Bus-->>NodeB: 回读: 1 ✓ 一致 Note over NodeA,NodeB: ...前 8 位相同 ... NodeA->>Bus: 位9: 发送 1 NodeB->>Bus: 位9: 发送 0 Note right of Bus: 显性覆盖隐性<br/>总线实际状态 = 0 Bus-->>NodeA: 回读: 0 ✗ 不一致! Bus-->>NodeB: 回读: 0 ✓ 一致! Note over NodeA: 仲裁失败<br/>立即退出发送,转为接收 Note over NodeB: 仲裁胜出<br/>继续发送完整帧 NodeB->>Bus: 继续发送后续位...

因为仲裁过程中数据没有损坏,所以叫**“非破坏性”**。这是 CAN 相比以太网 CSMA/CD 的最大优势——没有冲突、没有重发浪费。

RTR 位也参与仲裁:相同 ID 下,数据帧(RTR=0)优先级高于遥控帧(RTR=1)。


七、ACK 机制#

ACK 槽是接收方回复的,不是发送方发的。

发送方在 ACK 槽期间会释放总线(发隐性 1),如果至少有一个接收方认为 CRC 正确,就会把总线拉成显性 0。发送方回读到 0,就知道”有人收到了”。

如果发送方在 ACK 槽读到的是 1(没有任何接收方应答),它会认为自己发送失败,自动重发。


八、协议对比与选型#

graph TB ROOT[嵌入式通信协议<br/>选型地图] ROOT --> UART[UART] ROOT --> I2C[I2C] ROOT --> SPI[SPI] ROOT --> RS485[RS-485] ROOT --> CAN[CAN 总线] UART --> U1[点对点调试<br/>GPS / 串口日志] I2C --> I1[两线板级总线<br/>传感器 / EEPROM / RTC] SPI --> S1[四线高速专线<br/>Flash / TFT屏 / SD卡] RS485 --> R1[差分长距组网<br/>Modbus / 工业传感器] CAN --> C1[多主对等网络<br/>汽车ECU / BMS / 实时控制] style ROOT fill:#f0f0f0,stroke:#333,stroke-width:2px style CAN fill:#ff9999,stroke:#333,stroke-width:3px style UART fill:#e1f5fe style I2C fill:#e8f5e9 style SPI fill:#fff9c4 style RS485 fill:#f3e5f5
特性UARTRS-485I2CSPICAN
线数2~3224+N2(CAN_H/L)
拓扑点对点总线型总线型星型/总线总线型
主从结构无一主多从/多主一主多从一主多从多主对等
寻址无无/轮询7/10 位地址片选 CS报文 ID(内容寻址)
仲裁机制无无时钟拉伸无非破坏性位仲裁
错误检测可选奇偶校验无ACK无CRC + ACK + 位填充 + 形式检查
最大速率1 Mbps10 Mbps3.4 Mbps几十 MHz1 Mbps(CAN 2.0)/ 5 Mbps(CAN FD)
最大距离15m1200m1m30cm1km@50kbps / 40m@1Mbps
抗干扰弱强(差分)弱弱极强(差分+协议级容错)
广播能力点对点可广播支持不支持原生广播,内容寻址
典型场景调试、GPS工业传感器组网板级传感器Flash/屏高速读写汽车 ECU、BMS、工业控制

九、CAN 的独到之处#

1. 内容寻址,不是设备寻址#

传统协议(I2C、SPI、Modbus)是”找某个设备,读某个寄存器”。CAN 是”发一条 ID 为 0x123 的数据,谁关心谁就拿走”。这种发布-订阅模型非常适合汽车:发动机发转速帧,仪表盘、变速箱、ESP 都可以同时订阅,不需要发动机知道谁在听。

2. 错误自动处理#

CAN 控制器内置错误计数器。如果某个节点频繁出错,它会自动从”主动报错”退到”被动监听”,甚至”总线关闭”(Bus Off),避免一个坏节点拖垮全网。

3. 实时性保证#

因为仲裁是确定性的(ID 越小优先级越高,且可预测),CAN 非常适合硬实时系统。汽车刹车信号的 ID 通常设得极小,确保它永远能第一时间抢到总线。


十、CAN FD 延伸#

传统 CAN(CAN 2.0)最高 1 Mbps,数据段最多 8 字节,在汽车智能化时代渐渐不够用了。于是有了 CAN FD(Flexible Data-rate):

  • 仲裁段保持 1 Mbps 兼容老设备
  • 数据段可提速到 2~8 Mbps
  • 数据段长度扩展到 64 字节
  • CRC 校验增强

再往后还有 CAN XL,数据段可达 2048 字节,速率 10 Mbps+,开始向以太网领地渗透。


总结#

概念一句话理解
显性/隐性有差分=0(显性,能覆盖别人),无差分=1(隐性,会被覆盖)
终端电阻总线两端各 120Ω,防信号反射,稳定隐性电平
标准帧/扩展帧11 位 ID 够用选标准,不够用选 29 位扩展
遥控帧不带数据的”求数据”请求,RTR=1
ACK 槽接收方在此位拉低总线,告诉发送方”我收到了”
位填充每 5 个相同位强插一个反位,提供跳变沿用于时钟同步
非破坏性仲裁ID 小的赢,输家自动退赛,不损坏数据
内容寻址不关心谁发的,关心这条数据是什么(看 ID)

如果说 SPI 是板级高速专线,I2C 是板级经济公交,RS-485 是工业长距干线,那么 CAN 就是汽车与工业现场里那张去中心化的神经网络——没有老大,人人平等,谁急谁先讲,讲错了自动纠错。搞懂它,你就摸到了现代嵌入式分布式系统的脉搏。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

CAN
https://mjzy.tech/posts/通信协议/08-can/
作者
JIA
发布于
2026-08-21
许可协议
CC BY-NC-SA 4.0

评论区

正在加载 GitHub 评论…

Tips · 随手记
仅自己可见 · 每篇文章单独保存

文章目录