1. CAN总线基础:从物理层到仲裁机制
大家好,我是老张。做汽车电子这行十几年了,CAN总线就像我的老朋友。今天咱们聊聊CAN总线的基础知识。别小看这些基础,我见过太多工程师因为忽略细节,在实车上栽跟头。
1.1 CAN协议概述
CAN,全称Controller Area Network,控制器局域网。上世纪80年代由德国Bosch公司开发,初衷是为了解决汽车内部电子设备之间的通信问题。
说白了,就是让车上的各个ECU(电子控制单元)能互相说话。发动机、变速箱、ABS、气囊、仪表盘……这些家伙都得通过CAN总线交换信息。
我个人习惯把CAN总线比作一个会议室。所有ECU都坐在会议室里,谁想发言就抢话筒。但有个规矩——优先级高的先讲。这就是后面要说的仲裁机制。
核心特点:
- 多主站通信:任何节点都可以主动发消息
- 实时性强:优先级高的消息延迟可控
- 可靠性高:有完善的错误检测机制
- 成本低:只需要两根线(CAN_H和CAN_L)
1.2 CAN物理层
物理层,就是实实在在的硬件。CAN总线用两根差分信号线:CAN_H(高)和CAN_L(低)。
为什么用差分信号?抗干扰啊!我在一个项目中遇到过,某款车在电磁干扰强的环境下,单端信号全乱了,但CAN总线纹丝不动。差分信号就是有这个好处——两根线受到的干扰几乎一样,相减之后干扰就被抵消了。
CAN总线的电平状态有两种:
| 状态 | CAN_H电压 | CAN_L电压 | 说明 |
|---|---|---|---|
| 显性(Dominant) | 3.5V | 1.5V | 逻辑0,优先级高 |
| 隐性(Recessive) | 2.5V | 2.5V | 逻辑1,优先级低 |
嗯,这里要注意:显性电平会覆盖隐性电平。也就是说,只要有一个节点发送显性位,总线上就是显性状态。这个特性是仲裁机制的基础。
实战经验:终端电阻一定要加!标准是120Ω,在总线两端各接一个。我见过有人偷懒不加,结果信号反射严重,通信时好时坏。排查了整整两天才找到原因。
1.3 CAN数据链路层
数据链路层,负责把物理层的信号组织成有意义的报文。CAN的报文帧结构是核心中的核心。
你想想看,总线上那么多节点,怎么知道哪条消息是发给自己的?靠的就是报文中的标识符(ID)。每个报文都有一个唯一的ID,接收节点根据ID决定是否接收。
1.4 CAN报文帧结构
CAN有四种帧类型:数据帧、远程帧、错误帧、过载帧。咱们重点说数据帧,因为平时用得最多。
数据帧
数据帧是干活的主力。它由7个段组成:
- 帧起始(SOF):1个显性位,告诉所有节点"我要发消息了"
- 仲裁段:包含ID和RTR位。ID决定优先级,RTR区分数据帧和远程帧
- 控制段:包含IDE位和DLC(数据长度码)。DLC告诉接收方数据有多少字节
- 数据段:0-8字节,真正要传的数据
- CRC段:15位CRC校验码+1位CRC界定符。用来检查数据有没有传错
- ACK段:接收节点在这里回应"我收到了"
- 帧结束(EOF):7个隐性位,表示帧结束
标准帧 vs 扩展帧:
- 标准帧:11位ID,仲裁段共12位
- 扩展帧:29位ID,仲裁段共32位
我建议能用标准帧就别用扩展帧。扩展帧虽然ID多,但帧长增加,总线利用率降低。除非你的系统节点特别多,ID不够用。
远程帧
远程帧是用来请求数据的。比如ECU A想知道ECU B的某个参数,就发一个远程帧,ID填上想要的数据ID。ECU B收到后,就会发送对应的数据帧。
说白了,远程帧就是"我要数据,你发给我"。
错误帧
错误帧是CAN总线的"警察"。当节点检测到错误时,就会发送错误帧,通知所有节点"刚才那条消息有问题,别用"。错误帧由6个显性位组成,会破坏当前帧的填充规则,让所有节点都发现错误。
注意:错误帧有主动错误和被动错误之分。主动错误节点发送6个显性位,被动错误节点发送6个隐性位。如果一个节点频繁发送错误帧,它可能会从主动错误变成被动错误,甚至进入总线关闭状态。我曾经调试过一个项目,某个节点因为硬件问题一直发错误帧,最后把自己"踢出群聊"了。
过载帧
过载帧用来告诉发送方"我忙不过来,慢点发"。它和错误帧结构类似,但用途不同。过载帧在两种情况下触发:
- 接收节点内部条件未准备好
- 检测到位填充规则违规
1.5 CAN总线仲裁机制
仲裁机制是CAN总线的精髓。多个节点同时发送时,谁优先级高谁先发。
怎么判断优先级?看ID。ID越小,优先级越高。仲裁过程是这样的:
- 所有想发送的节点同时发送仲裁段的第一位
- 每个节点发送一位后,读取总线电平
- 如果自己发送的是隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发,自己退出
- 重复这个过程,直到只剩一个节点
举个例子:节点A的ID是0x100,节点B的ID是0x200。二进制分别是:
- A: 001 0000 0000
- B: 010 0000 0000
发送第一位时,A发0(显性),B发0(显性),总线是0,都继续。发送第二位时,A发0(显性),B发1(隐性),总线是0(显性覆盖隐性)。B发现总线和自己发的不一样,就知道自己输了,乖乖退出。A继续发送剩余位。
你想想看,这个过程完全在硬件层面完成,不需要软件干预。这就是CAN总线实时性好的原因之一。
避坑指南:我曾经设计一个系统,把两个关键消息的ID设成了0x100和0x101。结果发现0x100的消息总是先发,0x101的消息经常被延迟。后来我把0x101改成了0x200,问题解决了。记住:ID分配要合理,关键消息用小的ID。
1.6 知识体系总览
下面这张图总结了CAN总线基础的核心内容,我习惯用这种图来梳理知识结构:
这张图把CAN总线基础分成了四个模块。我个人习惯先讲物理层,因为它是基础。然后是数据链路层,理解报文结构。最后是仲裁机制,这是CAN总线的灵魂。协议概述作为开篇,让大家有个整体认识。
好了,CAN总线的基础就聊到这儿。记住:物理层是骨架,数据链路层是血肉,仲裁机制是灵魂。三者缺一不可。
可可精品资料库