从零开始认识CAN网通信引言为什么需要CAN总线物理层差分信号与“线与”逻辑电平定义“线与”逻辑为什么用差分信号数据链路层报文、仲裁与帧结构CAN通信模型非破坏性仲裁机制标准帧 vs 扩展帧CAN报文接收与发送流程引言为什么需要CAN总线想象一下现代的汽车里装着几十个电子控制单元ECU发动机控制、ABS防抱死、自动空调、车窗控制……如果每个模块之间都单独拉线那汽车里的线束会多得像一团乱麻不仅成本高、接线麻烦还容易出故障。传统点对点通信CAN总线通信每个ECU之间都需要独立连线所有ECU挂载在同一对双绞线上节点数量增加线束呈指数增长节点增加只需并联接入线束不变故障排查困难维护成本高分布式诊断故障定位方便CAN总线就是为了解决这个问题而生的。它全称是控制器局域网Controller Area Network由德国博世BOSCH公司在1986年开发后来成为国际标准ISO 11898。简单来说它就像一条数据高速公路让所有电子控制单元都能挂在这条“路”上通过一对双绞线进行高效、可靠的通信大大减少了线束数量。如今CAN总线不仅统治了汽车电子在工业自动化、医疗设备、船舶控制、机器人等领域也是应用广泛。物理层差分信号与“线与”逻辑CAN总线物理层只用两根线CAN_H 和 CAN_L。它通过两根线之间的电压差差分信号来传输数据而不是像串口那样依赖对地电压。电平定义信号类型CAN_H电压CAN_L电压差分电压逻辑值显性Dominant约3.5V约1.5V2V0隐性Recessive约2.5V约1.5V2V0“线与”逻辑总线执行线与机制。可以把显性0理解为“强势”信号隐性1理解为“弱势”信号。节点A输出节点B输出总线最终电平隐性 (1)隐性 (1)隐性 (1)显性 (0)隐性 (1)显性 (0)隐性 (1)显性 (0)显性 (0)显性 (0)显性 (0)显性 (0)为什么用差分信号抗干扰能力强外界噪声几乎同时耦合到两根线上接收端只关心差分值共模干扰相互抵消。电磁辐射低两根线绞在一起双绞线对外辐射相互抵消。数据链路层报文、仲裁与帧结构CAN总线通信是以“报文”为单位的。它不指定发送者和接收者而是通过报文标识符ID 来区分不同的消息。CAN通信模型注意CAN总线两端必须各接一个120Ω的终端电阻用于匹配阻抗防止信号在总线末端反射造成数据错误。非破坏性仲裁机制这是CAN最精妙的设计。当多个节点同时要发送数据时它们会从ID的最高位开始一位一位地比较。谁先发送出隐性位1而总线上却是显性位0谁就立即停止发送转为接收状态。关键结论ID数值越小优先级越高所以一般比较重要的任务ID号都比较小标准帧 vs 扩展帧对比项标准帧 (Standard Frame)扩展帧 (Extended Frame)ID位数11位29位ID范围0x000 ~ 0x7FF0x00000000 ~ 0x1FFFFFFF帧格式ID RTR IDE DLCID SRR IDE ID扩展 RTR DLC可挂载节点数最多 2048 个最多 5.3 亿个数据字节数0 ~ 8 字节0 ~ 8 字节应用场景简单系统、传统汽车复杂系统、J1939协议标准帧格式帧起始位1位仲裁段11位ID控制段6位数据段0~64位CRC段16位ACK段2位帧结束7位扩展帧格式帧起始位1位基ID11位SRR1位IDE1位扩展ID18位控制段6位数据段0~64位CRC段16位ACK段2位帧结束7位CAN报文接收与发送流程发送流程图Created with Raphaël 2.3.0开始发送检查总线是否空闲连续11个隐性位发送帧起始SOF显性位0发送仲裁段ID逐位发送并监听仲裁是否失败退出发送转为接收状态继续发送遥控段/数据段发送CRC校验段等待ACK确认位监测显性电平是否接收ACK发送帧结束7个隐性位重发或报错错误帧yesnoyesno接收流程图Created with Raphaël 2.3.0等待接收检测到帧起始SOF显性位下降沿接收仲裁段ID逐位接收并存储ID是否通过过滤器继续接收控制段/数据段接收CRC校验段本地计算CRCCRC校验是否通过发送ACK确认位显性位接收帧结束EOF7个隐性位处理并存储数据触发回调函数发送错误帧显性位忽略该帧不发送ACKyesnoyesno