第4章:CAN总线位时序与同步:位时间组成、同步段(SS)、传播段(PTS)、相位缓冲段1(PBS1)、相位缓冲段2(PBS2)、硬同步与重同步

各位工程师,大家好。欢迎来到第四章。

前面我们聊了CAN的物理层和数据链路层,但有个核心问题一直没细说——时钟同步。说白了,CAN总线没有单独的时钟线,所有节点都得靠自己的晶振“猜”别人的节奏。这怎么行?

嗯,今天我们就来彻底搞懂CAN的位时序与同步机制。我个人觉得,这是CAN协议里最精妙、也最容易踩坑的地方。

4.1 位时间的组成:一个“位”是怎么切开的?

先问个问题:一个CAN数据位,在总线上持续多久?

答案取决于波特率。比如1Mbps,一个位就是1微秒。但CAN控制器不会傻等1微秒,它会把这一微秒切成四段来精细控制。

这四段分别是:

  • 同步段(SS):用于检测总线上的跳变沿。固定为1个Tq(时间量子)。
  • 传播段(PTS):补偿信号在总线上的传播延迟。我一般设2-3个Tq。
  • 相位缓冲段1(PBS1):用于重同步时延长采样点。可调。
  • 相位缓冲段2(PBS2):用于重同步时缩短采样点。可调。

一个完整的位时间 = SS + PTS + PBS1 + PBS2。采样点就在PBS1和PBS2之间。

核心公式:

位时间(Tbit)= 同步段 + 传播段 + 相位缓冲段1 + 相位缓冲段2

采样点位置 = (SS + PTS + PBS1) / Tbit × 100%

举个例子。假设Tq=100ns,位时间=10Tq=1μs(即1Mbps)。我习惯这样分配:

  • SS = 1 Tq
  • PTS = 3 Tq
  • PBS1 = 3 Tq
  • PBS2 = 3 Tq

采样点就在第7个Tq结束时,也就是70%的位置。为什么是70%?后面会讲。

4.2 同步段(SS):一切同步的起点

同步段只有一个作用:检测总线上的下降沿(从显性到隐性,或隐性到显性)。

CAN协议规定,每个节点必须在SS段内采样总线电平。如果检测到跳变沿,就认为这是一个“同步信号”。

我的经验: 有些新手会把SS段设得很长,觉得这样能提高容错。其实没必要。SS固定为1Tq就够了。设长了反而会压缩后面的缓冲段,导致同步范围变小。

4.3 传播段(PTS):补偿物理延迟

信号在总线上传输需要时间。比如总线长度40米,信号传播速度约5ns/m,那么来回就是40×5×2=400ns。

传播段就是用来补偿这个延迟的。它必须大于等于2倍的物理延迟(发送到接收再返回)。

我建议这样算:

  • 先测量总线长度
  • 估算最远两个节点的往返延迟
  • PTS ≥ 2 × 最大传播延迟

举个例子。总线长50米,传播延迟5ns/m,往返就是500ns。如果Tq=125ns,那么PTS至少需要4个Tq。我一般会留余量,设成5个Tq。

注意: PTS设得太小,远距离节点会采样到错误电平。我曾经在一个项目中,因为PTS少设了1个Tq,导致总线长度超过30米后频繁出错。排查了整整两天才找到原因。

4.4 相位缓冲段1和2(PBS1/PBS2):同步的“弹性空间”

这两个段是同步机制的核心。它们的作用是:允许采样点前后移动

  • PBS1:重同步时,可以延长(增加采样前的等待时间)。
  • PBS2:重同步时,可以缩短(减少采样后的等待时间)。

说白了,如果某个节点发现自己的时钟比总线慢了一点,它就会延长PBS1,让采样点往后挪。如果发现自己的时钟快了,就缩短PBS2,让采样点往前挪。

这个调整范围叫做同步跳转宽度(SJW)。SJW决定了每次重同步最多能调整多少个Tq。

重要规则:

  • SJW ≤ PBS1
  • SJW ≤ PBS2
  • SJW ≥ 1(通常设1-2个Tq)

我个人习惯把SJW设成1个Tq。为什么?因为大多数晶振的误差在1%以内,1个Tq的调整量足够应对。设大了反而可能引入抖动。

4.5 硬同步与重同步:两种同步方式

CAN的同步分两种:硬同步重同步

4.5.1 硬同步

发生在总线空闲时。当节点检测到SOF(帧起始)的下降沿,它会立即将当前位时间重置到SS段。这就是硬同步。

硬同步只发生在帧开始时,且只调整一次。

4.5.2 重同步

发生在帧传输过程中。如果节点在SS段之后检测到跳变沿,说明时钟有偏差,需要调整。

  • 如果跳变沿出现在PBS1内:说明节点时钟偏慢,需要延长PBS1。
  • 如果跳变沿出现在PBS2内:说明节点时钟偏快,需要缩短PBS2。

重同步可以多次发生,每次调整不超过SJW。

避坑指南: 我曾经在一个项目中,把SJW设成了3个Tq,结果发现总线偶尔出现位错误。后来分析波形才发现,重同步调整量太大,导致采样点跳过了正确的电平。从那以后,我坚持SJW不超过2个Tq。

4.6 采样点位置的选择:70%还是80%?

采样点位置直接影响通信可靠性。太靠前,容易采到信号前沿的振荡;太靠后,又可能采到下一个位的开始。

我推荐以下经验值:

波特率 推荐采样点位置 说明
125kbps 70% - 75% 低速总线,传播延迟影响小
250kbps 70% - 75% 常用值
500kbps 75% - 80% 高速总线,需要更多余量
1Mbps 80% - 85% 极高速,采样点尽量靠后

为什么高速时要靠后?因为信号在总线上有建立时间。采样点靠后,能确保信号已经稳定。

4.7 实战配置示例

假设我们要配置一个500kbps的CAN网络,Tq=125ns(即8MHz晶振,分频后得到)。

位时间 = 1/500kbps = 2000ns = 16个Tq。

我这样分配:

  • SS = 1 Tq
  • PTS = 5 Tq(补偿约625ns的传播延迟)
  • PBS1 = 5 Tq
  • PBS2 = 5 Tq
  • SJW = 1 Tq

采样点位置 = (1+5+5)/16 = 68.75%。嗯,稍微偏低,但考虑到总线长度不超过20米,这个值完全够用。

配置代码示例(基于STM32 HAL库):

// 假设CAN时钟频率为8MHz
// 目标波特率500kbps
// 位时间 = 16 Tq

CAN_HandleTypeDef hcan;
hcan.Instance = CAN1;
hcan.Init.Prescaler = 1;      // 分频系数,Tq = 125ns
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;   // SJW = 1 Tq
hcan.Init.TimeSeg1 = CAN_BS1_10TQ;       // SS + PTS + PBS1 = 1+5+5 = 11 Tq
hcan.Init.TimeSeg2 = CAN_BS2_5TQ;        // PBS2 = 5 Tq
// 注意:TimeSeg1包含了SS段,所以实际是11Tq
// 采样点位置 = 11/16 = 68.75%

配置完成后,记得用示波器抓一下CAN_H和CAN_L的波形,确认位时间是否正确。我习惯在总线上发一个0x55(交替位),这样能清楚看到每个位的长度。

4.8 常见问题与排查

最后,分享几个我踩过的坑:

  • 问题: 总线偶尔出现位错误,但频率不高。
    排查: 检查采样点位置。我遇到过采样点设在50%的情况,结果信号上升沿刚好在采样点附近,导致误判。
  • 问题: 长距离通信失败。
    排查: 计算传播延迟,适当增加PTS。我曾经把PTS从3Tq增加到5Tq,问题就解决了。
  • 问题: 不同晶振的节点无法通信。
    排查: 检查SJW是否足够大。如果晶振误差超过1%,SJW需要设成2Tq。

嗯,这一章的内容就到这里。位时序和同步是CAN协议的基石,理解透了,后面的错误处理、总线仲裁都会轻松很多。

下一章,我们聊聊CAN的帧格式——数据帧、远程帧、错误帧和过载帧。到时候见。