1. CAN总线基础回顾:CAN协议概述、CAN帧结构、CAN总线物理层、CAN总线仲裁机制
各位同学,咱们今天先不急着上手搞网关迁移。做嵌入式这么多年,我有个习惯——不管项目多急,先把基础过一遍。尤其是CAN总线,这东西看着简单,但坑不少。我见过太多工程师,上来就调代码,结果连帧格式都搞混了,最后查问题查到怀疑人生。
好,咱们正式开始。CAN总线,全称Controller Area Network,是德国BOSCH公司在80年代搞出来的。你想想看,那会儿汽车电子刚起步,线束多得像蜘蛛网。CAN的出现,说白了就是给ECU之间拉了一条"公用电话线",大家共用一根线来传数据。
核心要点:CAN总线是一种多主总线,任何节点都可以主动发消息。不是主从结构,这点和LIN总线完全不同。
1.1 CAN协议概述
CAN协议分两层:物理层和数据链路层。物理层管信号怎么在线上跑,数据链路层管帧怎么组织、怎么仲裁、怎么检错。
我个人习惯把CAN协议理解成"带优先级的广播"。为什么这么说?因为每个消息都有一个ID,ID越小,优先级越高。两个节点同时发消息时,ID小的那个会"抢到"总线,ID大的自动退让。这个机制,咱们后面细讲。
CAN协议有几个版本:
- CAN 2.0A:标准帧,11位ID
- CAN 2.0B:扩展帧,29位ID
- CAN FD:灵活数据速率,数据段可以更快,数据长度可达64字节
我在项目中遇到过最坑的事,就是CAN 2.0A和2.0B混用。有些老设备只支持标准帧,你发个扩展帧过去,它直接不理你。嗯,这个坑踩过一次就记住了。
1.2 CAN帧结构
CAN帧有四种类型:数据帧、远程帧、错误帧、过载帧。咱们最常用的是数据帧,今天重点讲它。
一个标准数据帧长这样:
SOF | 11位ID | RTR | IDE | r0 | DLC | 0-8字节数据 | CRC | ACK | EOF
咱们拆开来看:
| 字段 | 长度 | 说明 |
|---|---|---|
| SOF | 1位 | 帧起始,显性电平(0) |
| ID | 11位 | 标识符,决定优先级 |
| RTR | 1位 | 远程帧标志,0=数据帧,1=远程帧 |
| IDE | 1位 | 扩展标志,0=标准帧,1=扩展帧 |
| r0 | 1位 | 保留位 |
| DLC | 4位 | 数据长度,0-8 |
| Data | 0-64位 | 实际数据 |
| CRC | 15位 | 循环冗余校验 |
| ACK | 2位 | 应答位 |
| EOF | 7位 | 帧结束,隐性电平(1) |
小技巧:我调试时习惯先看DLC。如果DLC是0,但数据段还有值,那八成是协议栈配置错了。曾经有个项目,就是因为DLC和实际数据长度不匹配,导致网关转发时丢数据,查了整整两天。
扩展帧和标准帧的区别,主要在ID字段。扩展帧的ID是29位,由11位基本ID和18位扩展ID组成。IDE位为1时表示扩展帧。
1.3 CAN总线物理层
物理层这块,说白了就是两根线:CAN_H和CAN_L。信号靠差分电压来传输。
CAN总线的电平逻辑是这样的:
- 显性电平(Dominant):CAN_H比CAN_L高2V左右,逻辑0
- 隐性电平(Recessive):CAN_H和CAN_L电压相等,逻辑1
为什么会这样设计?你想想看,如果多个节点同时拉低总线,总线就是显性。如果都没拉,总线就是隐性。这个特性,正好用来做仲裁。
物理层还有一些关键参数:
| 参数 | 典型值 | 说明 |
|---|---|---|
| 总线长度 | ≤40m@1Mbps | 速率越高,距离越短 |
| 终端电阻 | 120Ω | 两端各一个,防止信号反射 |
| 节点数 | ≤110个 | 受驱动能力限制 |
| 波特率 | 125k-1Mbps | 常用250k、500k、1M |
注意:终端电阻必须加在总线两端,不是每个节点都加。我曾经见过一个项目,每个节点都焊了120Ω电阻,结果总线信号完全畸变,通讯时好时坏。排查了三天才发现是电阻并联太多,等效电阻只有十几欧姆。
1.4 CAN总线仲裁机制
仲裁机制,这是CAN总线最精妙的设计。说白了,就是多个节点同时发消息时,谁优先级高谁先发。
仲裁的过程是这样的:
- 所有节点同时发送SOF位(显性),总线被拉低
- 接着发送ID位,从高位到低位逐位比较
- 如果某个节点发送隐性位(1),但总线上是显性(0),说明有更高优先级的节点在发
- 这个节点立即停止发送,转为接收模式
- 优先级最高的节点继续发送,不受影响
我举个例子:节点A发ID=0x100,节点B发ID=0x200。二进制分别是:
A: 001 0000 0000
B: 010 0000 0000
从最高位开始比,第2位A是0,B是1。A发显性,B发隐性,但总线上是显性。B检测到总线和自己发的不一致,立刻退出。A继续发完整个帧。
关键点:仲裁过程中不会丢失任何数据。退出的节点会在总线空闲后自动重发。这就是"无损仲裁"的含义。
我记得刚入行时,有个老工程师跟我说:"CAN的仲裁,就像一群人过独木桥,官大的先走。"这个比喻虽然糙,但道理是对的。ID越小,优先级越高,0x000是最高优先级。
这里有个容易忽略的细节:仲裁只发生在帧起始到ACK之前。一旦进入数据段,仲裁就结束了。所以数据段的内容不会影响优先级。
实战建议:设计CAN网络时,把实时性要求高的消息分配小ID。比如刹车信号用0x001,车窗信号用0x100。这样紧急消息总能优先通过。我有个项目,就是因为把空调和刹车信号ID搞反了,差点出安全事故。
好,CAN总线基础就回顾到这里。这些内容看着简单,但都是后面做网关迁移的基石。下一章咱们开始讲CAN到以太网网关的硬件设计,到时候会用到这些知识。
有什么问题,欢迎随时交流。