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 位时序配置实战流程

下面是我在实际项目中配置位时序的步骤,你可以直接拿来用:

  1. 确定目标波特率:比如500kbps。
  2. 确定系统时钟频率:比如CAN控制器时钟是40MHz。
  3. 计算Tq数量:位时间 = 1/500k = 2μs。Tq = 1/40M = 25ns。位时间需要的Tq数 = 2000ns / 25ns = 80个Tq。
  4. 分配Tq到各段:Sync_Seg=1,Prop_Seg=10,Phase_Seg1=59,Phase_Seg2=10。采样点 = (1+10+59)/80 = 87.5%。
  5. 设置SJW:一般设为1~2个Tq,保证重同步的稳定性。
  6. 写入寄存器:根据芯片手册设置BRP、TSEG1、TSEG2、SJW。

注意:Prop_Seg的长度要能覆盖整个网络的物理延迟。计算公式:Prop_Seg ≥ 2 × (线缆延迟 + 收发器延迟 + 控制器延迟)。线缆延迟大约5ns/m,收发器延迟约50~100ns,控制器延迟约20~50ns。算出来不够就加Prop_Seg。

3.6 位时序与同步机制知识结构图

下面这张图把位时序的组成、同步机制和采样点位置的关系画清楚了:

CAN位时序与同步机制结构图 CAN位时序与同步机制结构图 一个CAN位时间(Bit Time) Sync_Seg Prop_Seg Phase_Seg1 采样点 Phase_Seg2 同步机制 硬同步 发生在帧起始(SOF) 所有节点对齐到下降沿 重同步 发生在帧传输过程中 调整Phase_Seg1或Phase_Seg2 边沿提前 缩短Phase_Seg1 边沿推迟 延长Phase_Seg2 关键约束:SJW(同步跳转宽度)≤ min(Phase_Seg1, Phase_Seg2) 采样点位置 = (Sync_Seg + Prop_Seg + Phase_Seg1) / 总Tq数 × 100%

3.7 常见位时序问题与排查

最后,我把实战中遇到最多的位时序问题列出来,你对照排查:

现象 可能原因 排查方向
偶尔丢帧,波形正常 采样点位置偏差 检查各节点采样点是否一致
错误帧增多,尤其长报文 SJW设置过小 增大SJW,但不超过Phase_Seg1/2
总线长距离通信失败 Prop_Seg不够 计算物理延迟,增加Prop_Seg
不同厂家设备互连丢包 位时序参数不兼容 统一采样点,建议87.5%
低温或高温下丢包 晶振温漂导致时钟偏差 使用温漂小的晶振,或增大SJW

我的习惯:每次做新项目,我都会在代码里把位时序参数做成宏定义,方便调试时快速修改。而且我会在CAN初始化后,回读寄存器确认写入值是否正确——有些芯片的寄存器有保留位,写错了也不报错,但通信就是不稳定。

嗯,位时序这部分就讲到这里。记住一句话:采样点就是CAN总线的命门。配置对了,通信稳如老狗;配置错了,你查三天三夜也找不到原因。