3. CAN总线位时序与同步机制:同步段、传播段、相位缓冲段、采样点设置
位时序这东西,说白了就是CAN总线的“心跳节奏”。
很多工程师遇到丢包,第一反应就是查硬件、查终端电阻、查线缆。但说实话,我见过太多案例——硬件看着没问题,示波器波形也漂亮,可就是时不时丢一帧。最后定位下来,全是位时序配置的锅。
所以这一章,咱们把位时序掰开揉碎了讲清楚。
3.1 为什么位时序这么重要?
CAN总线是异步通信,没有单独的时钟线。所有节点靠什么同步?靠的是总线上的电平跳变。
你想想看,如果每个节点的时钟漂移一点点,采样点位置差那么一丁点,高速通信时就会采样到错误的位。一次两次可能没事,积累多了,错误帧就来了。
我曾经调试一个项目,波特率500kbps,总线长度也就两米。可就是丢包。折腾了两天,最后发现是某个节点的采样点设在了75%,而其他节点是87.5%。就差这么12.5%,通信就不稳定。
核心结论:位时序决定了采样点位置。采样点位置决定了通信的容错边界。边界不够,丢包就是必然。
3.2 位时间的五段结构
一个CAN位时间,被分成了五段。记住这五段的名字和顺序:
| 段名称 | 英文 | 作用 | 可编程长度 |
|---|---|---|---|
| 同步段 | Sync_Seg | 总线电平跳变发生在这里 | 固定1个Tq |
| 传播段 | Prop_Seg | 补偿物理延迟(线缆+收发器) | 1~8个Tq |
| 相位缓冲段1 | Phase_Seg1 | 采样点前调整,补偿边沿相位误差 | 1~8个Tq |
| 相位缓冲段2 | Phase_Seg2 | 采样点后调整,补偿边沿相位误差 | 1~8个Tq |
| 采样点 | Sample Point | 读取总线电平的位置 | 位于Phase_Seg1与Phase_Seg2之间 |
这里有个关键点:同步段是固定的1个Tq。Tq是什么?是CAN控制器的最小时间单位,一个位时间由若干个Tq组成。
举个例子,如果位时间=16个Tq,那么:
- Sync_Seg = 1 Tq
- Prop_Seg + Phase_Seg1 + Phase_Seg2 = 15 Tq
- 采样点位置 = (Sync_Seg + Prop_Seg + Phase_Seg1) / 总Tq数
3.3 采样点到底设多少合适?
这是实战中最常被问的问题。我直接给结论:
| 波特率 | 推荐采样点位置 | 说明 |
|---|---|---|
| 125kbps 及以下 | 80% ~ 87.5% | 低速总线,线缆延迟影响小,采样点可靠后 |
| 250kbps | 80% ~ 87.5% | 常用工业总线配置 |
| 500kbps | 75% ~ 87.5% | 高速总线,建议87.5% |
| 1Mbps | 75% ~ 80% | 极限速率,采样点不能太靠后 |
我个人习惯:能设87.5%就设87.5%。为什么?采样点越靠后,留给信号稳定建立的时间越长,抗干扰能力越强。
但注意,不是所有控制器都支持87.5%。有些芯片的Tq分配有限制,比如必须整数倍。这时候退而求其次,80%也行。
实战技巧:如果你不确定采样点设多少,先查芯片手册的BRP(波特率预分频器)和TSEG1/TSEG2寄存器。大多数CAN控制器用TSEG1表示Prop_Seg+Phase_Seg1,TSEG2表示Phase_Seg2。采样点 = (Sync_Seg + TSEG1) / (Sync_Seg + TSEG1 + TSEG2)。
3.4 同步机制:硬同步与重同步
同步机制是CAN总线能容忍时钟误差的关键。它分两种:
3.4.1 硬同步
发生在总线从空闲到有数据的时候。每个节点检测到总线上的下降沿(从隐性到显性),立即把自己的位时序对齐到这个边沿。硬同步只发生在帧起始。
3.4.2 重同步
发生在帧传输过程中。如果某个节点的时钟比发送节点快或慢,它检测到边沿位置与预期有偏差,就会调整Phase_Seg1或Phase_Seg2的长度。
- 边沿提前了:说明本地时钟偏慢,缩短Phase_Seg1,让采样点提前。
- 边沿推迟了:说明本地时钟偏快,延长Phase_Seg2,让采样点推后。
这里有个限制——SJW(同步跳转宽度)。SJW决定了每次重同步最多能调整多少个Tq。SJW一般设为1~4个Tq,不能超过Phase_Seg1或Phase_Seg2的最小值。
我曾经踩过的坑:有次把SJW设成了4,Phase_Seg2只设了3。结果重同步时调整量超过了Phase_Seg2的长度,直接导致位错误。记住:SJW ≤ min(Phase_Seg1, Phase_Seg2)。
3.5 位时序配置实战流程
下面是我在实际项目中配置位时序的步骤,你可以直接拿来用:
- 确定目标波特率:比如500kbps。
- 确定系统时钟频率:比如CAN控制器时钟是40MHz。
- 计算Tq数量:位时间 = 1/500k = 2μs。Tq = 1/40M = 25ns。位时间需要的Tq数 = 2000ns / 25ns = 80个Tq。
- 分配Tq到各段:Sync_Seg=1,Prop_Seg=10,Phase_Seg1=59,Phase_Seg2=10。采样点 = (1+10+59)/80 = 87.5%。
- 设置SJW:一般设为1~2个Tq,保证重同步的稳定性。
- 写入寄存器:根据芯片手册设置BRP、TSEG1、TSEG2、SJW。
注意:Prop_Seg的长度要能覆盖整个网络的物理延迟。计算公式:Prop_Seg ≥ 2 × (线缆延迟 + 收发器延迟 + 控制器延迟)。线缆延迟大约5ns/m,收发器延迟约50~100ns,控制器延迟约20~50ns。算出来不够就加Prop_Seg。
3.6 位时序与同步机制知识结构图
下面这张图把位时序的组成、同步机制和采样点位置的关系画清楚了:
3.7 常见位时序问题与排查
最后,我把实战中遇到最多的位时序问题列出来,你对照排查:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 偶尔丢帧,波形正常 | 采样点位置偏差 | 检查各节点采样点是否一致 |
| 错误帧增多,尤其长报文 | SJW设置过小 | 增大SJW,但不超过Phase_Seg1/2 |
| 总线长距离通信失败 | Prop_Seg不够 | 计算物理延迟,增加Prop_Seg |
| 不同厂家设备互连丢包 | 位时序参数不兼容 | 统一采样点,建议87.5% |
| 低温或高温下丢包 | 晶振温漂导致时钟偏差 | 使用温漂小的晶振,或增大SJW |
我的习惯:每次做新项目,我都会在代码里把位时序参数做成宏定义,方便调试时快速修改。而且我会在CAN初始化后,回读寄存器确认写入值是否正确——有些芯片的寄存器有保留位,写错了也不报错,但通信就是不稳定。
嗯,位时序这部分就讲到这里。记住一句话:采样点就是CAN总线的命门。配置对了,通信稳如老狗;配置错了,你查三天三夜也找不到原因。