2. 物理层详解:CAN总线基础、差分信号、终端电阻、波特率配置
各位同学,咱们今天聊聊CAN总线的物理层。说实话,很多做BMS(电池管理系统)和PMS(电源管理系统)通信的工程师,往往把精力都放在协议解析上,却忽略了物理层。我见过太多项目,协议栈写得天衣无缝,结果一上电就跑飞,最后查出来是终端电阻没焊对,或者波特率配错了。嗯,物理层这东西,看似基础,但坑是真不少。
2.1 CAN总线基础:为什么是它?
先问大家一个问题:BMS和PMS之间,为什么非得用CAN?用串口不行吗?用I2C不行吗?
说白了,CAN总线是为工业环境量身定做的。BMS和PMS之间,动不动就是几十米的线缆,电机、逆变器产生的电磁干扰能把弱信号直接淹没。串口那种单端信号,抗干扰能力太弱。I2C更别提了,开漏输出、上拉电阻,距离一长就完蛋。
CAN总线不一样。它采用多主结构,任何节点都可以主动发消息。而且它的仲裁机制——非破坏性逐位仲裁——保证了高优先级的数据永远不丢失。我在一个储能项目中遇到过,PMS需要紧急下电,如果用的是RS485,还得等总线空闲才能发,那黄花菜都凉了。CAN总线直接抢占总线,优先级高的报文先走,这才是实时性的保障。
核心特点:
- 多主通信:任何节点都能主动发起传输
- 非破坏性仲裁:ID小的报文优先级高,自动赢得总线
- 差分信号:抗共模干扰能力强
- 错误检测与重发:CRC校验、位填充、错误帧等机制
2.2 差分信号:CAN的“秘密武器”
CAN总线用两条线——CAN_H和CAN_L——来传输信号。你想想看,如果外界有强电磁干扰,它会同时作用在两条线上。差分信号的精髓就在于:接收器只关心两条线之间的电压差,而不是对地的绝对电压。
具体来说:
- 显性电平(Dominant):CAN_H比CAN_L高约2V(CAN_H≈3.5V,CAN_L≈1.5V),逻辑上代表“0”
- 隐性电平(Recessive):CAN_H和CAN_L电压相等(约2.5V),逻辑上代表“1”
显性电平会“覆盖”隐性电平。这就是仲裁的基础——谁先拉低总线,谁就赢。
个人经验: 我在调试一个BMS时,发现CAN通信偶尔丢帧。用示波器一看,CAN_H和CAN_L的共模电压漂到了5V以上。原来是地线回路出了问题,导致共模电压超出收发器的承受范围。差分信号虽然抗干扰,但收发器都有共模输入范围(通常是-2V到+7V),超出这个范围,神仙也救不了。
下面我用一张SVG图来展示CAN总线的差分信号原理:
看到没?隐性时两条线电压相同,差分电压为0;显性时CAN_H被拉高、CAN_L被拉低,差分电压约为2V。接收器就靠这个差值来判断是0还是1。
2.3 终端电阻:为什么是120Ω?
终端电阻这个话题,我每次培训都要重点讲。因为太多人在这上面翻车了。
CAN总线本质上是一个传输线。信号在线上传播时,如果遇到阻抗不连续的地方,就会发生反射。反射回来的信号会叠加在原始信号上,造成波形畸变,严重时直接导致通信失败。
终端电阻的作用,就是吸收信号能量,消除反射。标准CAN总线要求两端各接一个120Ω电阻,这样总线的等效阻抗就是60Ω——正好匹配CAN收发器的输出阻抗。
避坑指南: 我曾经在一个项目中,看到有人把终端电阻焊在了PCB上,但实际布线时节点离总线主干很远,相当于电阻接在了分支末端。结果反射照样存在,通信时好时坏。正确的做法是:终端电阻必须接在总线物理拓扑的两个最远端,而不是随便找个节点焊上去。
关于终端电阻,有几点需要记住:
- 必须两个:只在总线一端接一个120Ω,等效阻抗是120Ω,不匹配。必须两端各一个,并联后才是60Ω。
- 不能多也不能少:如果接了三个或更多,等效阻抗低于60Ω,信号幅值会衰减。
- 分支越短越好:CAN总线的分支(stub)长度建议不超过0.3米,否则分支本身就会成为反射源。
2.4 波特率配置:快与稳的博弈
波特率,说白了就是CAN总线每秒能传多少位数据。常见的波特率有125kbps、250kbps、500kbps、1Mbps等。BMS和PMS之间,我建议用250kbps或500kbps。
为什么不是越快越好?因为波特率越高,对总线长度的要求就越苛刻。CAN总线的最大长度与波特率成反比:
| 波特率 | 最大总线长度(约) | 典型应用场景 |
|---|---|---|
| 1 Mbps | 40 m | 车内短距离通信 |
| 500 kbps | 100 m | BMS/PMS 常见配置 |
| 250 kbps | 250 m | 储能系统、工业控制 |
| 125 kbps | 500 m | 长距离、低速场景 |
波特率配置时,还有一个关键参数叫采样点。CAN总线的一个位时间被分成若干段:同步段、传播段、相位缓冲段1、相位缓冲段2。采样点通常设置在相位缓冲段1的末尾,也就是整个位时间的70%~80%位置。
采样点计算公式:
采样点 = (同步段 + 传播段 + 相位缓冲段1) / (同步段 + 传播段 + 相位缓冲段1 + 相位缓冲段2)
例如:8Tq + 3Tq + 1Tq + 2Tq,采样点 = (8+3+1)/(8+3+1+2) = 12/14 ≈ 85.7%
我个人习惯把采样点设在80%左右。太靠前,容易采样到信号上升沿的毛刺;太靠后,留给时钟误差的余量就少了。你想想看,如果总线上有多个节点,每个节点的晶振都有误差,采样点太靠后,可能一个节点已经发出下一位了,另一个节点还在采样上一位——这不就乱套了吗?
调试技巧: 如果你不确定当前配置的采样点是否合理,可以用示波器抓取CAN_H和CAN_L的波形,观察显性位和隐性位的宽度是否一致。如果显性位明显比隐性位宽,说明采样点偏后了;反之则偏前。调整相位缓冲段的比例,直到波形对称为止。
最后,关于波特率配置,我建议所有节点使用相同的晶振精度(至少±0.5%以内),并且统一采用相同的波特率参数配置。不要一个节点用16MHz晶振,另一个用8MHz,然后指望它们能自动同步——CAN的位同步机制虽然能容忍一定误差,但误差太大照样会丢帧。
好了,物理层的内容就讲到这里。记住一句话:物理层是通信的基石,基石不稳,上层协议再牛也白搭。下次咱们聊聊数据链路层,看看CAN帧到底是怎么打包和解包的。