3、CAN通信基础:从物理层到错误处理

各位同学,今天我们来聊聊CAN通信。说实话,CAN总线在汽车圈里摸爬滚打这么多年,早就成了车载通信的“老大哥”。我入行那会儿,第一个项目就是调试CAN报文,当时被一个隐性位搞到凌晨三点——嗯,这个坑后面我会讲。

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

CAN总线物理层,说白了就是两根线:CAN_H和CAN_L。它用差分信号传输,抗干扰能力很强。你想想看,发动机舱里电磁环境那么恶劣,普通串口早就废了,但CAN还能稳如老狗。

物理层有几个关键参数:

  • 总线电平:显性(Dominant)对应逻辑0,隐性(Recessive)对应逻辑1。显性时CAN_H≈3.5V,CAN_L≈1.5V;隐性时两者都≈2.5V。
  • 传输速率:常见的有125kbps、250kbps、500kbps、1Mbps。速率越高,总线长度越短。
  • 终端电阻:总线两端各接120Ω电阻,用来消除信号反射。

重要提醒:CAN总线是“线与”逻辑。多个节点同时发送显性位时,总线呈现显性状态。这个特性是仲裁机制的基础。

我在项目中遇到过一个问题:某次台架测试,CAN通信时断时续。查了半天,发现终端电阻焊错了,用了100Ω。换回120Ω后,一切正常。所以啊,硬件细节真不能马虎。

3.2 CAN数据链路层:帧是怎么组织的?

数据链路层负责把数据打包成帧。CAN有两种帧格式:标准帧(11位ID)和扩展帧(29位ID)。

先看标准帧的结构:

SOF | 11位ID | RTR | IDE | r0 | DLC | 数据段(0-8字节) | CRC | ACK | EOF

扩展帧呢,就是把ID扩展到29位:

SOF | 11位ID | SRR | IDE | 18位扩展ID | RTR | r1 | r0 | DLC | 数据段 | CRC | ACK | EOF

这里有几个关键位,我解释一下:

  • SOF(Start of Frame):帧起始,一个显性位。
  • ID:标识符,决定优先级。数值越小,优先级越高。
  • RTR(Remote Transmission Request):远程帧标志。0是数据帧,1是远程帧。
  • IDE(Identifier Extension):0表示标准帧,1表示扩展帧。
  • DLC(Data Length Code):数据长度,0-8字节。
  • CRC:循环冗余校验,15位。
  • ACK:应答位,接收节点发送显性位确认。

个人经验:我建议你在设计CAN节点时,优先使用标准帧。扩展帧虽然ID空间大,但仲裁效率略低。除非ID不够用,否则别折腾。

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

CAN总线是多主总线,多个节点可以同时发送。那冲突了怎么办?靠仲裁。

仲裁的原理很简单:ID越小,优先级越高。发送时,每个节点逐位比较ID。如果某个节点发送隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发送,它就自动退出发送。

举个例子:

节点A ID = 0x100(二进制:001 0000 0000)
节点B ID = 0x200(二进制:010 0000 0000)

第1位:A发0,B发0 → 总线0,继续
第2位:A发0,B发1 → 总线0(显性),B检测到冲突,退出
A继续发送,B转为接收

为什么会这样?因为显性位(0)会覆盖隐性位(1)。所以ID小的节点,高位0更多,自然占优势。

避坑指南:我曾经在一个项目中,把两个ECU的ID设成了0x100和0x101。结果0x101的节点几乎发不出数据,因为0x100优先级太高。后来我把0x101改成了0x200,问题解决。记住:ID分配要留足间隔,别挤在一起。

3.4 CAN错误处理机制:出错了怎么办?

CAN的错误处理机制,我觉得是它最牛的地方之一。它不依赖上层协议,硬件自己就能搞定。

错误类型有5种:

错误类型 说明 检测位置
位错误(Bit Error) 发送节点监控总线,发现发送的位与总线状态不一致 发送节点
填充错误(Stuff Error) 连续5个相同位后,未检测到填充位 所有节点
CRC错误 接收节点计算的CRC与发送的不一致 接收节点
格式错误(Form Error) 帧格式不符合规范(如EOF位不是隐性) 所有节点
应答错误(ACK Error) 发送节点未收到ACK显性位 发送节点

错误处理流程是这样的:

  1. 节点检测到错误,立即发送错误帧(6个显性位)。
  2. 其他节点收到错误帧,丢弃当前报文。
  3. 发送节点根据错误计数器决定是否重发。

每个节点有两个错误计数器:

  • TEC(Transmit Error Counter):发送错误计数。
  • REC(Receive Error Counter):接收错误计数。

节点状态根据计数器值变化:

  • 错误主动(Error Active):TEC<127且REC<127。正常发送,检测到错误时发送主动错误帧。
  • 错误被动(Error Passive):TEC>127或REC>127。发送被动错误帧,且发送间隔延长。
  • 总线关闭(Bus Off):TEC>255。节点完全断开总线,不再参与通信。

关键点:总线关闭状态需要上层协议介入恢复。我建议你在AUTOSAR的Can模块中配置自动恢复机制,别让节点永久离线。

我记得有一次,客户反馈某ECU在高温测试中频繁丢帧。查日志发现REC飙升到200多,节点进入了错误被动状态。原因是CAN收发器在高温下性能下降,导致位采样出错。后来换了宽温范围的收发器,问题解决。所以啊,硬件选型一定要考虑环境边界

3.5 本章知识体系

下面这张图,是我自己画的CAN通信基础结构图。你看一眼,就能把物理层、数据链路层、仲裁和错误处理串起来。

CAN通信基础知识体系 物理层 • 差分信号:CAN_H / CAN_L • 显性(0):CAN_H≈3.5V, CAN_L≈1.5V • 隐性(1):CAN_H≈2.5V, CAN_L≈2.5V • 终端电阻:120Ω × 2 • 速率:125kbps ~ 1Mbps 数据链路层 • 标准帧:11位ID • 扩展帧:29位ID • 帧结构:SOF → ID → 控制 → 数据 → CRC → ACK → EOF • 数据段:0~8字节 • 远程帧:RTR=1,无数据段 仲裁机制 • 多主总线,逐位仲裁 • ID越小,优先级越高 • 显性位覆盖隐性位 • 仲裁失败节点自动转为接收 • 无损仲裁,不浪费带宽 错误处理 • 5种错误类型:位/填充/CRC/格式/应答 • 错误帧:6个显性位 • 错误计数器:TEC / REC • 三种状态:主动 → 被动 → 总线关闭 • 自动重发机制 CAN通信基础:物理层 → 数据链路层 → 仲裁 → 错误处理

这张图把本章的核心内容都串起来了。物理层是基础,数据链路层是框架,仲裁机制保证多节点有序通信,错误处理确保可靠性。四者缺一不可。

我的建议:学CAN通信,别只盯着协议看。找个CAN分析仪,抓几帧实际报文看看,比读十遍书都管用。我当年就是这么入门的。


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