前言
在汽车电子、工业控制领域,CAN总线绝对是最经典的串行通信总线。和串口、I2C、SPI不一样,CAN天生支持多节点组网、总线容错、非破坏性位仲裁,一条总线可以挂几十个MCU、ECU,即使某一个节点故障短路,也不会让整个总线瘫痪。本文结合CAN总线物理层结构、帧结构、仲裁逻辑、容错机制完整讲解,适合车载开发、工业设备开发人员阅读。
一、CAN总线硬件物理结构
1.1 总线线缆组成
CAN总线采用两根差分信号线:CAN_H、CAN_L,不是单端信号。
- 空闲状态下:CAN_H和CAN_L电位相等,约2.5V,总线隐性电平;
- 显性状态下:CAN_H拉高至约3.5V,CAN_L拉低至约1.5V,两根线产生2V左右压差;
- 差分信号的优势:抗干扰能力极强,汽车发动机、继电器产生的电磁干扰,对差分信号几乎没有影响,这也是车载全部使用CAN而不用UART的核心原因。
总线两端必须接120Ω终端电阻,两个120Ω电阻并联为60Ω匹配阻抗。
- 作用:消除信号反射、抑制高频干扰;
- 常见错误:只接一个终端电阻,会出现波形畸变、通信丢包;完全不接电阻,远距离完全无法通信。
1.2 总线拓扑结构
CAN是多主式总线,没有主机、从机之分,所有节点地位完全平等。
一条总线可以挂载最多110个节点,所有节点并联在CAN_H和CAN_L两根线上,任意一个节点都可以主动发起报文发送,不需要主机轮询。
1.3 收发器结构
MCU内部只有CAN控制器(CAN外设),不能直接驱动差分总线,必须搭配外置CAN收发器(典型型号TJA1050、SN65HVD230):
- 控制器:处理帧格式、校验、仲裁、重发逻辑;
- 收发器:把控制器的单端逻辑电平,转换成CAN_H/CAN_L差分电平。
二、CAN两种电平:显性位与隐性位
CAN总线只有两种电平状态,所有节点同步监听总线:
- 隐性电平(1):CAN_H=2.5V,CAN_L=2.5V,压差为0;多个节点同时发隐性位,总线依然保持隐性。
- 显性电平(0):CAN_H=3.5V,CAN_L=1.5V,压差2V;显性位优先级高于隐性位。
核心规则:只要总线上任意一个节点发出显性0,整条总线就会变成显性,覆盖所有节点的隐性1,这个特性就是CAN仲裁的基础。
三、非破坏性逐位仲裁(CAN最核心机制)
这也是CAN区别于其他总线的灵魂,也就是CSMA/CD+非破坏性仲裁。
3.1 仲裁过程
- 多个节点同时检测到总线空闲,同时开始发送报文ID(仲裁段);
- 所有节点逐位发出ID,一边发一边回读总线上的电平;
- 如果自己发出的是隐性1,但是读到总线变成了显性0,说明有更高优先级节点抢占总线;
- 失去仲裁的节点立刻停止发送,转为接收模式,等待下一次总线空闲;
- 获胜的节点不受任何影响,继续完整发送报文,数据不会损坏、不会中断。
3.2 ID优先级规则
CAN标准帧ID共11位,ID数值越小,优先级越高。
举例:
节点A ID:0x001,节点B ID:0x002;两个节点同时发送。
从最高位开始逐位对比,高位相同,到低位时,低ID会发出显性0,抢占总线。
3.3 为什么叫“非破坏性”
以太网冲突检测后,双方都必须停止发送、等待随机延时重发;
而CAN输掉仲裁的节点仅仅放弃发送,赢家完整发完数据,不会造成数据损坏,总线利用率远高于以太网。
四、CAN报文帧类型
CAN一共有四种帧:数据帧、远程帧、错误帧、过载帧,日常开发只用数据帧。
标准数据帧结构分段(从起始到结尾):
- 帧起始:1位显性0,通知所有节点总线开始传输;
- 仲裁段:11位ID + RTR位,RTR=0代表数据帧;
- 控制段:4位,标识后面数据场长度(0~8字节);
- 数据段:0~8字节有效数据,这是用户真正需要传输的内容;
- CRC校验段:15位CRC校验,保证数据传输无误;
- ACK应答段:发送器发出隐性位,接收正确的节点拉低为显性应答;
- 帧结束:7位隐性位,一帧结束。
补充:CAN FD扩展了数据长度,最大支持64字节,工业设备使用较多。
五、总线容错与故障隔离
CAN具备强大的错误处理机制,这也是车载安全等级的关键:
- 每个节点都时刻校验CRC、位错误、填充错误;
- 检测到错误时,节点立刻发送错误帧,终止当前报文;
- 节点内置错误计数器,发送错误、接收错误分别计数;
- 计数器超限后,节点会自动进入总线关闭状态,脱离总线,不会因为一个节点硬件短路,把整条总线拉死。
就算某个ECU内部短路,收发器损坏,其余上百个节点依旧可以正常通信,这是普通串口完全做不到的。
六、CAN总线典型应用场景
- 汽车电子:发动机ECU、ABS、仪表、车灯、BMS电池管理系统全部挂在CAN总线上;
- 工业自动化:伺服驱动器、PLC、传感器组网;
- 工程机械:挖掘机、装载机控制器通信;
- 新能源设备:电池BMS、电机控制器、车载充电机交互。
七、CAN和UART、I2C核心对比表
| 总线 | 拓扑 | 多主仲裁 | 抗干扰 | 节点数量 | 容错能力 |
|---|---|---|---|---|---|
| UART串口 | 点对点 | 不支持 | 差 | 2个 | 无容错 |
| I2C | 多节点 | 主机轮询 | 一般 | 最多8个 | 无故障隔离 |
| CAN | 多主总线 | 硬件自动仲裁 | 极强(差分信号) | 110个 | 故障自动脱离总线 |
八、STM32最简CAN收发示例(标准帧)
#include "stm32f10x.h" #include "can.h" CAN_TxHeaderTypeDef TxHeader; CAN_RxHeaderTypeDef RxHeader; uint8_t TxData[8]; uint8_t RxData[8]; uint32_t TxMailbox; // CAN发送函数 void CAN_Send_Msg(uint16_t id,uint8_t *buf,uint8_t len) { TxHeader.StdId = id; TxHeader.IDE = CAN_ID_STD; TxHeader.RTR = CAN_RTR_DATA; TxHeader.DLC = len; HAL_CAN_AddTxMessage(&hcan1,&TxHeader,buf,&TxMailbox); } // CAN中断接收回调 void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&RxHeader,RxData); // 在这里解析RxData数据 }九、开发常见坑点总结
- 总线两端必须安装120Ω终端电阻,只装一端波形失真;
- CAN_H和CAN_L不能反接,反接后收发器无法正常工作;
- 长距离布线必须使用双绞屏蔽线,减少电磁干扰;
- ID越小优先级越高,报警、紧急信号使用低ID;
- CAN控制器自带重发机制,软件不需要手动重发报文。
十、总结
CAN总线的核心优势总结为三点:差分抗干扰、多主非破坏性仲裁、硬件级容错隔离。
没有固定主机,多节点自由抢占总线,冲突时低ID报文优先发送,故障节点自动下线,让CAN成为汽车、工业控制领域几十年经久不衰的总线标准。理解物理差分电平与位仲裁逻辑,就能彻底看懂CAN所有底层行为。