关键概念
时间量子 (Time Quantum, Tq)
CAN 位时序的最小时间单位,由 CAN 时钟经预分频器(Prescaler)分频得到:Tq = (BRP+1) / fCAN。一个完整的位时间由若干个整数个 Tq 拼成。所有时序段(同步段、传播段、相位段)都以 Tq 为砖块搭建,因此调整 Tq 和各段的 Tq 数就能配置任意波特率。
位时间 (Bit Time)
传输一个位所占的总时间,等于所有时序段 Tq 之和:位时间 = SYNC_SEG + PROP_SEG + PHASE_SEG1 + PHASE_SEG2。波特率是它的倒数:波特率 = 1 / 位时间。例如 2μs 的位时间对应 500kbps。全网所有节点必须配置成相同的波特率(位时间可由不同 Tq 组合,但总时长一致)。
同步段 (SYNC_SEG)
位时间的第一段,固定为 1 个 Tq。预期总线电平跳变(边沿)应发生在此段内。硬同步和再同步都以此段为基准对齐——如果边沿正好落在同步段,说明本节点时钟与总线完美同步,无需调整。
传播段 (PROP_SEG)
用于补偿信号在总线上的物理传播延迟以及收发器、控制器的延迟。它必须足够长,以保证一个节点发出的电平能在采样前传遍全网并被回读(这是仲裁与错误检测正确工作的前提)。长度 1~8 个 Tq,随总线长度增加而加长。
相位段 1 / 2 (PHASE_SEG1 / PHASE_SEG2)
位于采样点两侧的缓冲段,用于吸收时钟误差。再同步时会拉长 PHASE_SEG1 或缩短 PHASE_SEG2 来微调采样时刻。采样点就位于 PHASE_SEG1 结束、PHASE_SEG2 开始的交界处。在 STM32 bxCAN 中,PROP_SEG 与 PHASE_SEG1 合并称为 BS1,PHASE_SEG2 称为 BS2。
采样点 (Sample Point)
在一个位时间内,CAN 控制器读取总线电平以判定该位是 0 还是 1 的时刻,用相对于位时间起点的百分比表示:采样点% = (SYNC+PROP+PHASE1) / 位时间。推荐值 75%~87.5%——靠后采样能等信号在长总线上稳定,但要留出 PHASE_SEG2 应对下一边沿。ISO 11898-2 常用 87.5%。全网采样点应尽量一致。
SJW (Synchronization Jump Width, 重同步跳转宽度)
再同步时允许调整 PHASE_SEG 的最大 Tq 数(1~4)。当边沿未落在同步段(说明本节点时钟偏快或偏慢),控制器最多拉长 PHASE_SEG1 或缩短 PHASE_SEG2 SJW 个 Tq 来追赶。SJW 越大容错越强,但过大会牺牲时序裕量。约束:SJW ≤ min(PHASE_SEG1, PHASE_SEG2) 且 SJW ≤ 4。
硬同步与再同步 (Hard-Sync / Re-Sync)
硬同步:仅在帧起始 SOF 的隐→显下降沿发生,强制把位时间计数器归零,全网对齐一次。再同步:帧传输过程中每遇到一个隐→显跳变(在非同步段),就用 SJW 微调相位段,持续跟踪发送方时钟。位填充保证了位流里总有足够的跳变供再同步使用,二者协同让无独立时钟线的 CAN 保持全网位对齐。
一个位的四段结构
把一个位时间放大来看,它由四段拼成,采样点落在 PHASE_SEG1 与 PHASE_SEG2 之间。
一个 CAN 位的时序结构(以 Tq 为单位)
═══════════════════════════════════════════════════════════
┌────┬──────────────┬──────────────┬──────────────┐
│SYNC│ PROP_SEG │ PHASE_SEG1 │ PHASE_SEG2 │
│ 1Tq│ 1~8 Tq │ 1~8 Tq │ 1~8 Tq │
└────┴──────────────┴──────────────┴──────────────┘
↑边沿 ↑
应落在此 采样点(Sample Point)
(硬/再同步基准) 在此读电平判 0/1
STM32 bxCAN 的合并视角:
┌────┬─────────────────────────────┬──────────────┐
│SYNC│ BS1 = PROP+PHASE1 │ BS2=PHASE2 │
│ 1Tq│ (1~16 Tq) │ (1~8 Tq) │
└────┴─────────────────────────────┴──────────────┘
↑ 采样点
位时间 = (1 + BS1 + BS2) 个 Tq
采样点% = (1 + BS1) / (1 + BS1 + BS2) × 100%
波特率是怎么算出来的
波特率由三个量决定:CAN 外设时钟频率、预分频器 BRP、以及每个位的 Tq 总数。公式如下:
波特率计算链
f_CAN (外设时钟, 如 APB1 = 42MHz)
│ ÷ (BRP+1) 预分频
▼
f_Tq = f_CAN / (BRP+1) ← 一个 Tq 的频率
│
│ Tq_total = 1(SYNC) + BS1 + BS2
▼
位时间 = Tq_total × (1 / f_Tq) = Tq_total × (BRP+1) / f_CAN
波特率 = 1 / 位时间
= f_CAN
─────────────────────────
(BRP+1) × (1 + BS1 + BS2)
实战计算:500kbps @ 42MHz APB1
STM32F407 的 bxCAN 挂在 APB1,时钟为 42MHz。目标波特率 500kbps,采样点约 87.5%。逐步求解:
目标: 500kbps, f_CAN = 42MHz, 采样点 ≈ 87.5%
① 选每位的 Tq 总数
令 Tq_total = 7 (常见取 7~16 之间)
② 求预分频 BRP
波特率 = f_CAN / ((BRP+1) × Tq_total)
500000 = 42_000_000 / ((BRP+1) × 7)
(BRP+1) × 7 = 84
BRP+1 = 12 ⇒ BRP = 11
③ 分配 BS1 / BS2 使采样点≈87.5%
Tq_total = 1(SYNC) + BS1 + BS2 = 7
采样点 = (1+BS1)/7 ≈ 87.5% ⇒ 1+BS1 ≈ 6.125
取 BS1 = 5, BS2 = 1 ⇒ 采样点 = (1+5)/7 = 85.7% ✓
④ 验算波特率
42_000_000 / (12 × 7) = 42_000_000 / 84 = 500000 = 500kbps ✓
⑤ 选 SJW
SJW ≤ min(BS1,BS2)=1 ⇒ 取 SJW = 1
结论: BRP=11(Prescaler=12), BS1=5, BS2=1, SJW=1
/* STM32 HAL CAN 位时序配置:500kbps @ 42MHz APB1 */
CAN_HandleTypeDef hcan;
hcan.Instance = CAN1;
hcan.Init.Prescaler = 12; /* BRP+1 = 12 */
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ; /* SJW = 1 Tq */
hcan.Init.TimeSeg1 = CAN_BS1_5TQ; /* BS1 = 5 Tq (含PROP+PHASE1) */
hcan.Init.TimeSeg2 = CAN_BS2_1TQ; /* BS2 = 1 Tq (PHASE2) */
/* 位时间 = 1+5+1 = 7 Tq;波特率 = 42e6/(12*7) = 500kbps
采样点 = (1+5)/7 = 85.7% */
hcan.Init.Mode = CAN_MODE_NORMAL;
if (HAL_CAN_Init(&hcan) != HAL_OK) {
/* 初始化失败 */
}
采样点为何常取 87.5%
采样点靠后(如 87.5%)给信号更多时间在长总线上稳定并让全网都收到,提高长距离与多节点时的鲁棒性;但不能太靠后,否则 PHASE_SEG2 太短、再同步(缩短 PHASE_SEG2)的余量不足。CANopen/汽车领域约定俗成用 87.5%,能兼容大多数节点。同一网络中所有节点的采样点应尽量一致,否则在临界时序下容易偶发误码。
波特率配错的典型症状
若某节点波特率与总线不符,最常见现象是:该节点无法应答(不产生 ACK),导致发送方反复重发、错误计数器飙升,甚至进入总线关闭;而其它节点之间通信正常。排查时用示波器测一个位的实际时长换算波特率,或用 CAN 分析仪的"自动波特率检测"。另一个隐患是采样点差异过大:波特率对了但采样点相差悬殊,会在总线较长或负载重时偶发误帧。
再同步:无时钟线如何保持对齐
再同步:用 SJW 微调相位段追赶发送方
情况A: 边沿落在 SYNC 段 ⇒ 完美同步,无需调整
┌SYNC┬─BS1─────┬─BS2──┐
│↑边沿 采样↑ │
情况B: 边沿"迟到"(本节点偏快) ⇒ 拉长 PHASE_SEG1(≤SJW)
┌SYNC┬─BS1+Δ───┬─BS2──┐ 延后采样,等发送方
(Δ ≤ SJW)
情况C: 边沿"早到"(本节点偏慢) ⇒ 缩短 PHASE_SEG2(≤SJW)
┌SYNC┬─BS1─────┬BS2-Δ┐ 提前进入下一位
(Δ ≤ SJW)
每个隐→显跳变都触发一次再同步(非同步段内)
位填充保证跳变足够密 ⇒ 时钟持续被校准
本章小结
CAN 没有独立时钟线,靠边沿再同步保持全网位对齐。一个位时间由整数个时间量子 Tq拼成,Tq =(BRP+1)/fCAN。位分四段:SYNC_SEG(固定 1Tq,同步基准)、PROP_SEG(补偿总线传播延迟)、PHASE_SEG1/2(采样点两侧缓冲,可被再同步微调)。采样点=(1+PROP+PHASE1)/位时间,推荐 75%~87.5%,汽车常用 87.5%。波特率 = fCAN /((BRP+1)×(1+BS1+BS2))。在 STM32 bxCAN 中 PROP+PHASE1 合并为 BS1、PHASE2 为 BS2。以 500kbps@42MHz 为例:Tq_total=7、BRP=11(Prescaler=12)、BS1=5、BS2=1、SJW=1,采样点 85.7%。SJW(1~4)限定再同步时相位段的最大调整量。硬同步只在 SOF 发生并归零计数器,再同步在每个隐→显跳变用 SJW 追踪发送方时钟,位填充保证跳变密度。波特率或采样点配错会导致该节点无法应答、发送方反复重发进而总线关闭。