1. CAN总线基础:从物理层到帧结构

大家好,我是你们的CAN总线调试讲师。做嵌入式这些年,我调试过的CAN节点少说也有上百个了。说实话,CAN总线看起来协议不复杂,但真正出问题的时候,能把人折腾得够呛。这一章我们先打好基础,把CAN协议的核心概念、物理层特性和帧结构理清楚。

为什么要先讲这些?因为我在项目里见过太多人,上来就写代码、调收发,结果总线一直报错,连是硬件问题还是软件问题都分不清。嗯,基础不牢,后面排查故障会很痛苦。

1.1 CAN协议概述

CAN,全称Controller Area Network,控制器局域网。它最早是德国Bosch公司为汽车电子开发的串行通信协议。现在不光汽车在用,工业控制、医疗设备、机器人里也随处可见。

CAN协议有几个关键特点,我挑重要的说:

  • 多主总线:总线上任何一个节点都可以主动发消息,不需要主从关系
  • 基于消息的寻址:不是给每个节点分配地址,而是给每条消息分配一个ID
  • 非破坏性仲裁:多个节点同时发送时,ID小的优先,不会冲突
  • 错误检测与自动重发:硬件自动检测错误,出错后自动重发
  • 实时性强:最坏情况下的响应时间可以计算

我个人习惯把CAN总线比作一个会议室。谁想发言都可以,但ID小的(优先级高的)先讲。如果有人讲错了,大家都会指出来,讲错的人会自动重讲一遍。这个比喻虽然简单,但能帮你快速理解CAN的核心机制。

核心要点:CAN总线不是靠节点地址通信,而是靠消息ID。你发送的消息,总线上所有节点都能收到,由每个节点的硬件过滤器决定要不要处理这条消息。

1.2 差分信号与物理层

CAN物理层用的是差分信号传输。说白了,就是两根线——CAN_H和CAN_L,通过它们之间的电压差来表示逻辑状态。

为什么会用差分信号?我在一个工业现场项目中遇到过强电磁干扰的环境,单端信号根本没法用,换上CAN总线就稳了。差分信号对共模干扰有天然的抑制能力,两根线受到的干扰基本一样,差值的跳变不受影响。

CAN总线的逻辑状态有两种:

状态 CAN_H电压 CAN_L电压 差分电压
显性(Dominant) 约3.5V 约1.5V 约2V
隐性(Recessive) 约2.5V 约2.5V 约0V

显性位会覆盖隐性位。仲裁的时候,显性位对应的ID位为0,隐性位为1。所以ID值越小,显性位越多,优先级越高。

避坑指南:我曾经遇到过一批板子CAN通信时好时坏,排查了半天,最后发现是CAN_H和CAN_L接反了。差分信号极性接反,总线还能工作,但通信极不稳定。所以焊接和接线时一定要仔细核对。

物理层还有一些关键参数:

  • 终端电阻:总线两端各接一个120Ω电阻,用于阻抗匹配,防止信号反射
  • 总线长度:与通信速率成反比,1Mbps时最长约40米,125kbps时可达500米
  • 节点数量:标准CAN驱动最多支持110个节点,实际建议不超过30个

1.3 CAN帧结构

CAN总线上一共定义了四种帧类型。我刚开始学的时候觉得记不住,后来发现只要理解每种帧的用途,自然就记住了。

1.3.1 数据帧

数据帧是最常用的,用来发送数据。它由7个段组成:

  1. 帧起始(SOF):1个显性位,标志帧的开始
  2. 仲裁段:包含11位(标准帧)或29位(扩展帧)的ID,以及RTR位
  3. 控制段:包含IDE位、保留位和4位数据长度码(DLC)
  4. 数据段:0~8字节的数据
  5. CRC段:15位CRC校验码和1位CRC界定符
  6. ACK段:1位ACK槽和1位ACK界定符
  7. 帧结束(EOF):7个隐性位

标准帧和扩展帧的区别主要在仲裁段:

特性 标准帧 扩展帧
ID长度 11位 29位
ID范围 0x000~0x7FF 0x00000000~0x1FFFFFFF
仲裁段长度 12位 32位
兼容性 所有节点都支持 需要扩展帧支持

经验之谈:我建议在CMS32项目里优先使用标准帧。扩展帧虽然ID范围大,但仲裁段更长,总线利用率会降低。除非你的系统需要超过2048个不同的消息ID,否则标准帧完全够用。

1.3.2 远程帧

远程帧用来请求数据。它没有数据段,但DLC字段要设置为请求的数据长度。发送远程帧后,目标节点收到后会发送对应的数据帧。

远程帧和数据帧的区别:

  • 远程帧的RTR位为隐性(1),数据帧的RTR位为显性(0)
  • 远程帧没有数据段
  • 远程帧的DLC表示请求的数据长度,而不是实际发送的数据长度

我记得有一次调试一个传感器节点,主机发远程帧请求数据,传感器就是不响应。查了半天,发现是传感器固件里把远程帧处理逻辑写错了。嗯,远程帧在实际项目中用得不多,但一旦用上,调试起来确实容易踩坑。

1.3.3 错误帧

错误帧是CAN总线自我纠错的核心机制。当任何节点检测到总线错误时,就会发送错误帧,通知其他节点。

错误帧由两部分组成:

  • 错误标志:6个连续相同极性的位(主动错误节点发6个显性位,被动错误节点发6个隐性位)
  • 错误界定符:8个隐性位

CAN节点有3种错误状态:

状态 条件 行为
主动错误 发送错误计数≤127 正常通信,检测到错误时发送主动错误帧
被动错误 发送错误计数128~255 只能发送被动错误帧,不能主动干扰总线
总线关闭 发送错误计数>255 完全断开与总线的连接

避坑指南:我曾经调试一个系统,发现某个节点时不时掉线,但过一会儿又自己恢复了。用CAN分析仪抓包一看,这个节点的发送错误计数一直在涨,到255后就总线关闭了,等计数降下来又重新连上。最后发现是它的CAN收发器供电不稳导致的。所以,遇到节点间歇性掉线,先查硬件供电和地线。

1.3.4 过载帧

过载帧用于节点在接收数据时,因为内部处理不过来而请求延迟。它和错误帧结构类似,也是由过载标志和过载界定符组成。

过载帧的触发条件:

  • 接收节点内部缓冲区满,需要更多时间处理
  • 在帧间隔期间检测到显性位

说实话,过载帧在实际项目中很少见到。现在的MCU处理速度都很快,只要软件设计合理,很少会出现处理不过来的情况。如果你在调试时频繁看到过载帧,那说明你的系统负载已经很高了,需要优化软件或者降低总线速率。

1.4 CAN总线知识体系总览

下面这张图把CAN总线的基础知识结构梳理了一下,方便你建立整体认知:

CAN总线基础知识体系结构图 CAN总线基础知识体系 CAN协议概述 差分信号与物理层 CAN帧结构 多主总线 消息寻址 非破坏性仲裁 错误检测与重发 CAN_H / CAN_L差分对 显性位 vs 隐性位 终端电阻120Ω 数据帧(7段) 远程帧(RTR=1) 错误帧(6+8位) 过载帧 数据帧结构:SOF → 仲裁段 → 控制段 → 数据段(0~8B) → CRC段 → ACK段 → EOF 💡 学习建议: 先理解CAN协议的核心思想(多主、仲裁、错误检测),再掌握物理层差分信号原理, 最后重点吃透数据帧的结构。四种帧类型中,数据帧和错误帧是调试时最常打交道的。

1.5 本章小结

这一章我们覆盖了CAN总线最基础的三块内容:协议概述、物理层和帧结构。你不需要一下子全记住,但至少要理解:

  • CAN总线靠差分信号传输,抗干扰能力强
  • 消息ID决定优先级,ID越小优先级越高
  • 数据帧是最常用的帧类型,标准帧11位ID够用就优先用
  • 错误帧是排查故障的重要线索,要学会看错误计数