1. CAN协议概述:从起源到分层模型

大家好,我是老周。做嵌入式通信这行快十五年了,CAN总线是我打交道最多的协议之一。今天咱们聊聊CAN协议的来龙去脉,以及它为什么能在汽车和工业领域站稳脚跟。

1.1 CAN总线的起源

上世纪80年代,汽车里的电子设备越来越多。空调、ABS、发动机控制、变速箱……每个模块都独立接线,线束越来越重,故障率也越来越高。我记得当时看过一个数据:一辆豪华车的线束总重能超过50公斤,长度接近2公里。

1983年,德国Bosch公司开始研发一种新的串行通信协议。1986年,CAN(Controller Area Network)正式发布。它的目标很明确:用两根线替代一堆线,让所有电子控制单元(ECU)共享一条总线。

1993年,CAN成为国际标准ISO 11898。到今天,几乎每辆汽车里都有至少两条CAN总线——一条跑动力总成,一条跑车身控制。

核心思想: CAN不是主从架构,而是多主总线。任何节点都可以主动发消息,谁先抢到总线谁说话。这一点和后面要讲的RS485完全不同。

1.2 CAN vs RS485:一场硬碰硬的对比

很多初学者会问:CAN和RS485都是差分信号,都能跑几十米,到底差在哪?

我直接说结论:CAN是为实时控制设计的,RS485是为数据采集设计的。

咱们看个表格,一目了然:

对比项 CAN RS485
总线架构 多主,无主节点 单主多从,或主从轮询
通信方式 广播式,所有节点都能收 点对点,需寻址
冲突处理 非破坏性逐位仲裁 无冲突检测,靠协议避免
错误处理 5种错误检测机制,自动重发 通常只有CRC,需应用层处理
实时性 确定性的,最坏情况可计算 不确定,取决于主站轮询周期
典型速率 125kbps ~ 1Mbps 9.6kbps ~ 10Mbps
典型距离 40m @ 1Mbps,1km @ 50kbps 1.2km @ 100kbps
硬件成本 稍高,需CAN控制器+收发器 低,UART+收发器即可

我在一个工业项目中遇到过这样的坑:客户坚持用RS485做伺服驱动器同步控制,结果每次启停都有丢帧,电机抖动得厉害。后来换成CAN,仲裁机制自动解决了总线冲突,问题再没出现过。

避坑指南: 我曾经见过有人用RS485跑CAN的协议栈,结果总线冲突时数据全乱套。记住:RS485没有硬件仲裁,多节点同时发送就是短路。CAN的物理层和链路层是绑定的,别想着混用。

1.3 CAN物理层特性

CAN物理层用的是差分信号,两条线分别叫CAN_H和CAN_L。闲时两条线都是2.5V,这叫隐性电平(逻辑1)。显性时CAN_H拉到3.5V,CAN_L降到1.5V,差分电压约2V(逻辑0)。

为什么用差分?说白了就是抗干扰。两根线绞在一起,外部噪声对两根线的干扰几乎一样,差分电压不变。我在工厂现场调试时,CAN总线就铺在变频器旁边,从来没出过问题。换成单端信号早废了。

几个关键参数:

  • 终端电阻: 总线两端各接一个120Ω电阻。作用是消除信号反射。少了不行,多了也不行。
  • 总线长度: 和速率成反比。1Mbps时最长40米,125kbps时可以到500米。想跑更远?降速。
  • 节点数量: 标准ISO 11898支持最多30个节点。用高速收发器(如TJA1050)可以到110个。
  • 电平标准: 隐性2.5V,显性CAN_H=3.5V、CAN_L=1.5V。别和RS485的±5V搞混。

个人习惯: 我设计CAN节点时,一定在PCB上预留终端电阻焊盘。调试时先不焊,用示波器看总线波形,有振铃再焊上。这样能精确匹配实际走线阻抗。

1.4 CAN协议分层模型

CAN协议只定义了物理层和数据链路层。应用层协议(如CANopen、J1939、DeviceNet)是后来各家厂商自己加的。为什么?因为Bosch当年只解决了“怎么可靠传数据”,没管“数据代表什么意思”。

咱们看这张分层图:

CAN协议分层模型 应用层(Application Layer) CANopen · J1939 · DeviceNet · 自定义协议 数据链路层(Data Link Layer) LLC:帧过滤 · 报文管理 MAC:仲裁 · 错误检测 · 封装 物理层(Physical Layer) PLS:位编码 · 时序 PMA:驱动器特性 MDI:连接器 物理介质:双绞线 · 光纤 · 无线(CAN FD) ISO/OSI 七层模型对应

我来拆解一下各层:

  • 物理层: 负责信号的收发、电平转换、位时序。CAN控制器(如SJA1000)和收发器(如TJA1050)干这活。嗯,这里要注意:不同厂家的收发器电气参数有差异,换型号时一定要重新测波形。
  • 数据链路层: 这是CAN协议的核心。它又分两个子层:
    • MAC子层: 负责帧封装、总线仲裁、错误检测、应答。说白了,谁先发、发错了怎么办,都是它管。
    • LLC子层: 负责帧过滤、报文管理。比如你只想收ID为0x123的帧,LLC帮你筛掉其他的。
  • 应用层: 标准CAN协议没定义这层。实际项目中,要么用现成的CANopen或J1939,要么自己定义一套协议。我个人建议:能用现成就别自己造,除非你有特殊需求。

关键理解: CAN的数据链路层是硬件实现的。你写软件时,只需要配置寄存器、填充报文缓冲区,剩下的仲裁、错误重发、CRC校验,硬件自动完成。这和UART、SPI那种纯软件协议完全不同。

1.5 为什么CAN能成为工业通信的常青树

我总结三点:

  1. 实时性有保障。 CAN的逐位仲裁机制保证高优先级报文永远最先发出。最坏情况下的响应时间可以计算出来。这在汽车刹车、安全气囊等场景里是刚需。
  2. 错误处理强悍。 每个节点都会监控总线,发现错误立刻发错误帧。连续错误过多的节点会自动离线,不影响其他节点。我曾经在一条CAN总线上故意短路一根线,结果其他节点照常通信,只是那个故障节点被踢出总线了。
  3. 成本可控。 一颗CAN控制器加一颗收发器,总成本不到10块钱。对于量产产品来说,这个成本优势很明显。

一点经验: 如果你刚开始接触CAN,建议先买一块USB-CAN分析仪(比如周立功的USBCAN-II),再找两块带CAN的STM32开发板。用分析仪抓包,用开发板发数据,来回对比着看。我当年就是这么入门的,比光看书快得多。