第2章:CAN总线基础:CAN协议物理层与数据链路层核心概念
好,咱们今天聊聊CAN总线。说实话,这玩意儿在车载领域太常见了。我入行那会儿,第一件事就是被师傅扔了一堆CAN协议文档,让我自己啃。当时觉得头大,后来才发现——搞懂物理层和数据链路层,你就抓住了CAN的命门。
2.1 物理层:信号怎么在线上跑
CAN总线的物理层,说白了就是两根线——CAN_H和CAN_L。它用的是差分信号传输。为什么用差分?抗干扰啊!你想想看,发动机舱里电磁环境多恶劣,单端信号早被干趴下了。
我遇到过一件事。有次台架上测CAN通信,波形老是莫名其妙地跳变。查了半天,发现是CAN_H和CAN_L的线束绞合不够紧密。嗯,这里要注意——双绞线的绞距是有讲究的,不是随便拧两下就行。
关键参数:
- 显性电平(Dominant):CAN_H ≈ 3.5V,CAN_L ≈ 1.5V,差分电压约2V
- 隐性电平(Recessive):CAN_H ≈ 2.5V,CAN_L ≈ 2.5V,差分电压约0V
- 总线终端电阻:120Ω(两端各一个)
这里有个坑。显性电平会覆盖隐性电平。也就是说,只要有一个节点拉低总线,其他节点都得跟着走。这跟后面要讲的总线仲裁直接相关。
避坑指南:我曾经在项目里见过有人把终端电阻焊在PCB上,结果线束一长,信号反射得一塌糊涂。记住:终端电阻一定要放在总线物理末端,不是ECU内部随便找个位置。
2.2 数据链路层:帧结构长啥样
CAN的数据链路层,核心就是帧结构。标准帧(CAN 2.0A)有11位ID,扩展帧(CAN 2.0B)有29位ID。我个人习惯,能用标准帧就别用扩展帧——省带宽,也省CPU处理时间。
来看一个标准数据帧的结构:
SOF | 11位ID | RTR | IDE | r0 | DLC | 数据段(0-8字节) | CRC | ACK | EOF
每个字段都有它的意义:
- SOF(Start of Frame):1位显性,告诉总线“我要发数据了”
- ID:标识符,决定优先级。数值越小,优先级越高
- RTR(Remote Transmission Request):区分数据帧还是远程帧
- DLC(Data Length Code):数据长度,0到8字节
- CRC:15位校验,加上1位隐性定界符
- ACK:应答位,接收节点拉低表示收到
小技巧:我调试时经常用示波器抓SOF和ACK位。如果看不到ACK的显性位,说明总线上没有其他节点在听——这通常是终端电阻没接好,或者节点根本没上电。
2.3 总线仲裁:谁先说话谁有理
CAN总线没有主从节点。所有节点都能发,但同一时间只能有一个发。那冲突了怎么办?靠仲裁。
仲裁的原理很简单:ID小的优先。发送节点在发送ID位时,会同时监听总线。如果自己发的是隐性(1),但总线上是显性(0),说明有更高优先级的节点在发,自己就乖乖退出发送。
我刚开始做CAN开发时,总觉得仲裁是硬件自动处理的,不用管。直到有一次,两个ECU同时发相同ID的报文,结果总线一直冲突,系统直接卡死。后来查出来,是软件配置把两个节点的报文ID设重复了。嗯,这个坑我踩过,你们别踩。
仲裁规则总结:
- ID越小,优先级越高
- 显性位(0)覆盖隐性位(1)
- 仲裁失败的节点自动转为接收模式
- 仲裁过程不破坏数据,也不浪费带宽
2.4 位时序与同步
CAN总线的位时序,说白了就是每个bit怎么划分。一个位时间分成4段:
| 段名称 | 作用 | 典型长度 |
|---|---|---|
| 同步段(Sync_Seg) | 检测边沿跳变 | 1 Tq |
| 传播段(Prop_Seg) | 补偿物理延迟 | 1-8 Tq |
| 相位缓冲段1(Phase_Seg1) | 采样点前调整 | 1-8 Tq |
| 相位缓冲段2(Phase_Seg2) | 采样点后调整 | 1-8 Tq |
采样点通常设置在Phase_Seg1和Phase_Seg2之间。我个人习惯把采样点设在87.5%左右,也就是Phase_Seg1比Phase_Seg2长一点。为什么?因为总线传播延迟是固定的,采样点靠后能留出更多余量。
注意:不同ECU的晶振精度不一样。如果位时序配置不当,两个节点之间会出现累积误差,最终导致同步丢失。我曾经在500kbps的速率下,因为晶振偏差超过1%,总线直接罢工。解决办法是缩短采样点位置,或者用更高精度的晶振。
2.5 错误检测与处理
CAN总线有5种错误检测机制:
- 位错误(Bit Error):发送时监听到的电平与自己发的不一致
- 填充错误(Stuff Error):连续6个相同电平,违反位填充规则
- CRC错误:接收方计算的CRC与发送方不一致
- 格式错误(Form Error):固定格式位(如CRC定界符)不是隐性
- ACK错误:发送方没收到显性应答
每个节点都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。错误多了,节点会进入被动错误状态,甚至总线关闭状态。我见过一个极端案例——某个ECU的CAN收发器坏了,不停地发错误帧,把整个总线都拖垮了。最后只能拔掉那个节点的供电。
调试建议:用CAN分析仪看错误帧类型。如果全是CRC错误,大概率是总线干扰大。如果全是填充错误,可能是位时序没配好。如果ACK错误频繁,检查终端电阻和节点数量。
2.6 实际项目中的选型建议
最后聊点实际的。选CAN收发器时,我一般看这几个参数:
- 速率:125kbps到1Mbps,根据总线长度选。线越长,速率越低
- 共模电压范围:至少±12V,最好±27V(应对地偏移)
- ESD防护:HBM至少±8kV,不然产线上静电一打就挂
- 待机功耗:休眠模式下,电流最好小于10μA
常用的收发器有TJA1040、TJA1050、SN65HVD230这些。我个人偏爱NXP的TJA1040,皮实耐造,就是贵了点。不过车载嘛,可靠性第一,省那几毛钱不值得。
好了,CAN总线的基础就聊到这儿。物理层搞懂了线怎么走,数据链路层搞懂了帧怎么传,后面讲通信矩阵和网络管理就顺了。下一章咱们聊聊CAN的更高层协议——比如J1939和CANopen,看看它们怎么在CAN基础上搭出更复杂的应用。