4、CAN总线位时序:位时间组成、同步段、传播段、相位缓冲段、采样点设置

好,咱们今天来聊聊CAN总线里一个特别关键、但也特别容易让人迷糊的概念——位时序。

说实话,我刚开始接触CAN的时候,觉得这东西不就是个通信协议嘛,配置好波特率不就行了?结果第一次调试的时候,总线死活同步不上,示波器一看,波形乱七八糟。后来才发现,问题就出在位时序上。你想想看,CAN总线是异步通信,没有单独的时钟线,全靠节点自己“猜”什么时候该采样。这个“猜”的过程,就是位时序要解决的问题。

4.1 位时间的基本组成

一个CAN位时间,说白了就是发送一个bit需要多长时间。它被分成了四个段:

  • 同步段(Sync_Seg):用于同步总线上的各个节点。固定为1个时间量子(Tq)。
  • 传播段(Prop_Seg):用于补偿网络上的物理延迟。包括收发器延迟、总线传播延迟等。
  • 相位缓冲段1(Phase_Seg1):用于补偿边沿相位误差。采样点就在这个段的末尾。
  • 相位缓冲段2(Phase_Seg2):采样点之后的缓冲段,用于调整下一个同步。

每个段都是由整数个时间量子(Tq)组成的。Tq是CAN控制器内部的最小时间单位,由系统时钟分频得到。

核心公式:

位时间 = (Sync_Seg + Prop_Seg + Phase_Seg1 + Phase_Seg2) × Tq

采样点位置 = (Sync_Seg + Prop_Seg + Phase_Seg1) / 位时间 × 100%

嗯,这里要注意,不同CAN控制器对这些段的命名可能略有不同。比如有些芯片把Prop_Seg和Phase_Seg1合并叫TSEG1,把Phase_Seg2叫TSEG2。但本质是一样的。

4.2 同步段(Sync_Seg)

同步段是每个位时间的起点。它的作用只有一个:检测总线上的边沿跳变。

每个节点都会在同步段内采样总线电平。如果检测到下降沿(从隐性到显性),就认为这是一个同步信号。我习惯把同步段想象成“对齐窗口”——所有节点都在这个窗口里看总线,谁先看到边沿,谁就主动对齐。

同步段固定为1个Tq,不能配置。为什么是1个?因为CAN协议规定,同步段内必须完成边沿检测和同步逻辑。1个Tq足够用了,多了反而浪费。

4.3 传播段(Prop_Seg)

传播段是用来补偿物理延迟的。这个延迟包括:

  • 发送节点的收发器延迟
  • 总线传播延迟(信号在线上跑的时间)
  • 接收节点的收发器延迟

我在项目中遇到过一个问题:两个节点距离50米,波特率设成了1Mbps,结果通信时好时坏。后来一算,传播延迟都快赶上位时间的一半了。你想想看,信号从A发到B需要250ns,B再回应又需要250ns,一来一回500ns。1Mbps的位时间才1000ns,传播段如果设得太短,采样点就采不到正确的电平。

所以,传播段的长度必须满足:

经验公式:

Prop_Seg ≥ 2 × (收发器延迟 + 总线传播延迟)

一般建议Prop_Seg设为2~8个Tq,具体看你的网络规模。

我个人习惯,在项目初期先按最坏情况估算。比如总线长度100米,信号传播速度约5ns/m,那单向延迟就是500ns。加上收发器延迟(通常100~200ns),来回就是1.2μs左右。如果Tq是100ns,Prop_Seg至少得设12个Tq。当然,实际中很少这么极端,但心里要有数。

4.4 相位缓冲段(Phase_Seg1 & Phase_Seg2)

这两个段是位时序的“弹性区域”。

Phase_Seg1:位于采样点之前。它的作用是吸收由于时钟漂移或噪声引起的边沿相位误差。采样点就在Phase_Seg1的末尾。

Phase_Seg2:位于采样点之后。它用于调整下一个位时间的同步。如果发生了重同步,Phase_Seg2的长度可能会被缩短或延长。

说白了,这两个段就是给CAN总线“容错”用的。没有它们,只要时钟稍微有点偏差,通信就会失败。

我记得有一次调试,两个节点的晶振精度都是20ppm,理论上没问题。但实际跑起来,偶尔会出现错误帧。查了半天,发现是Phase_Seg1设得太短了。20ppm的误差,在1000个位时间后就会累积出1个Tq的偏差。如果Phase_Seg1只有1个Tq,那根本来不及补偿。后来我把Phase_Seg1加到了3个Tq,问题就解决了。

4.5 采样点设置

采样点,就是CAN控制器读取总线电平的那个瞬间。它的位置直接决定了通信的可靠性。

采样点太靠前,信号还没稳定,容易采到毛刺。采样点太靠后,留给Phase_Seg2的时间不够,重同步能力会变差。

避坑指南:

我曾经在一个项目里,为了追求高波特率,把采样点设在了85%的位置。结果在实验室跑得好好的,一到现场就出问题。后来发现,现场的总线长度比实验室长了30米,传播延迟变大,采样点太靠后导致Phase_Seg2被压缩得太短,重同步失败。

从那以后,我一般把采样点设在75%~80%之间。这个范围比较安全,既能保证信号稳定,又能留足重同步的余量。

常见的采样点配置参考:

波特率 推荐采样点位置 说明
125 kbps 80% ~ 85% 低速网络,总线较长,采样点靠后更安全
250 kbps 75% ~ 80% 中等速率,兼顾延迟和重同步
500 kbps 75% ~ 80% 常用速率,我一般设87.5%
1 Mbps 70% ~ 75% 高速网络,总线长度受限,采样点靠前

你可能会问,为什么1Mbps反而要采样点靠前?因为高速时位时间短,传播延迟占比大。如果采样点太靠后,Phase_Seg2可能只剩1~2个Tq,重同步能力严重不足。所以,高速场景下,我宁愿牺牲一点信号稳定度,也要保证重同步的余量。

4.6 实际配置示例

假设我们有一个系统,系统时钟为16MHz,目标波特率为500kbps。我们来算一下位时序参数。

首先,确定Tq。一般建议Tq在100ns~200ns之间。我们选Tq = 125ns,那么:

  • 分频系数 = 16MHz × 125ns = 2,即2分频
  • 位时间 = 1 / 500kbps = 2000ns
  • 每个位时间的Tq数 = 2000ns / 125ns = 16个Tq

接下来分配各段:

  • Sync_Seg = 1 Tq
  • Prop_Seg = 3 Tq(假设网络延迟较小)
  • Phase_Seg1 = 8 Tq
  • Phase_Seg2 = 4 Tq

采样点位置 = (1 + 3 + 8) / 16 = 75%。嗯,这个配置比较均衡。

小技巧:

很多CAN控制器允许你直接配置采样点位置,而不是手动算各段长度。比如STM32的bxCAN,你可以直接设BS1和BS2的值。但不管怎么配,核心原则不变:采样点要在75%~80%之间,Phase_Seg2至少要有2个Tq。

好了,关于位时序,今天就聊这么多。说白了,这东西就是CAN总线的“节拍器”。节拍器调好了,整个乐队才能合拍。调不好,再好的乐手也白搭。下次调试CAN的时候,别忘了先看看你的位时序配对了没有。