📚 CAN总线技术系列 · 持续更新中
本系列从差分电气层一路打到 Linux SocketCAN,把"两根线"背后的电气/协议/控制器/驱动/实战全拧成一根线。
👉 想系统追更,戳这里查看完整专栏:
👉 其他技术系列专栏,欢迎关注、交流、共同成长:
【SPI 技术系列】 【I2C 技术系列】 【串口技术系列】【RISC-V 架构系列】【Linux内核系列】 【操作系统设计思想系列】 【 Android 系统全景专栏】
03 · CAN 位定时与同步
本篇定位 :CAN 物理层和拓扑讲完,本篇讲位定时------CAN 的灵魂。CAN 是同步总线(位填充维持跳变),但没有共享时钟线 (不像 SPI/I2C),靠硬同步 + 重同步对齐。采样点、SJW、时钟容差配错,全网通信失败。本篇讲位时间组成、采样点、同步机制、BTR 寄存器配置。读完你能配任何 CAN 控制器的位定时。
位定时是 CAN 配错必死项UART 异步,波特率配对就行。SPI/I2C 有共享时钟,主控速度。CAN 没有共享时钟,所有节点靠位定时参数各自同步,采样点/SJW/时钟容差必须全网一致 + 满足约束。配错一个节点,全网通信失败。这是 CAN 调试第二大坑(终端电阻第一)。做 CAN 网络,位定时必须算清。
目录
- [03 · CAN 位定时与同步](#03 · CAN 位定时与同步)
- 一、位时间组成
-
- [1.1 位时间分段](#1.1 位时间分段)
- [1.2 总位时间](#1.2 总位时间)
- [1.3 Tq 计算](#1.3 Tq 计算)
- 二、采样点
-
- [2.1 采样点定义](#2.1 采样点定义)
- [2.2 采样点推荐](#2.2 采样点推荐)
- [2.3 采样点为何要靠后](#2.3 采样点为何要靠后)
- [2.4 多采样(可选)](#2.4 多采样(可选))
- 三、同步机制
-
- [3.1 为什么需要同步](#3.1 为什么需要同步)
- [3.2 硬同步(Hard Sync)](#3.2 硬同步(Hard Sync))
- [3.3 重同步(Resync)](#3.3 重同步(Resync))
- [3.4 同步规则](#3.4 同步规则)
- [3.5 同步的物理意义](#3.5 同步的物理意义)
- 四、SJW(同步跳转宽度)
-
- [4.1 SJW 定义](#4.1 SJW 定义)
- [4.2 SJW 工作原理](#4.2 SJW 工作原理)
- [4.3 SJW 选择](#4.3 SJW 选择)
- [4.4 SJW 与时钟容差](#4.4 SJW 与时钟容差)
- 五、时钟容差
-
- [5.1 时钟容差来源](#5.1 时钟容差来源)
- [5.2 时钟容差约束](#5.2 时钟容差约束)
- [5.3 典型容差](#5.3 典型容差)
- [5.4 选晶振](#5.4 选晶振)
- [六、BTR 寄存器配置](#六、BTR 寄存器配置)
-
- [6.1 STM32 bxCAN BTR](#6.1 STM32 bxCAN BTR)
- [6.2 配置示例:1Mbit/s, SP 87.5%, f_CAN=42MHz](#6.2 配置示例:1Mbit/s, SP 87.5%, f_CAN=42MHz)
- [6.3 配置口诀](#6.3 配置口诀)
- [6.4 DesignWare/M_CAN 位定时](#6.4 DesignWare/M_CAN 位定时)
- [七、CAN FD 位定时](#七、CAN FD 位定时)
-
- [7.1 两套位定时](#7.1 两套位定时)
- [7.2 NBTP(标称位定时)](#7.2 NBTP(标称位定时))
- [7.3 DBTP(数据位定时)](#7.3 DBTP(数据位定时))
- [7.4 FD 位定时约束](#7.4 FD 位定时约束)
- [7.5 FD 配置示例](#7.5 FD 配置示例)
- [八、关键问题 Q&A](#八、关键问题 Q&A)
-
- [Q1:采样点 87.5% 怎么算?](#Q1:采样点 87.5% 怎么算?)
- [Q2:CAN 没有共享时钟,怎么同步?](#Q2:CAN 没有共享时钟,怎么同步?)
- [Q3:SJW 配多大?](#Q3:SJW 配多大?)
- Q4:时钟容差怎么满足?
- Q5:位定时配错会怎样?
- [Q6:CAN FD 数据段位定时怎么配?](#Q6:CAN FD 数据段位定时怎么配?)
- 九、实战案例
-
- [案例 1:采样点不一致,通信失败](#案例 1:采样点不一致,通信失败)
- [案例 2:时钟偏差大,偶发错](#案例 2:时钟偏差大,偶发错)
- [案例 3:SJW 太小,长帧错](#案例 3:SJW 太小,长帧错)
- [案例 4:采样点太前,长总线错](#案例 4:采样点太前,长总线错)
- [案例 5:CAN FD 数据段 CRC 错](#案例 5:CAN FD 数据段 CRC 错)
- [案例 6:晶振温漂,低温通信失败](#案例 6:晶振温漂,低温通信失败)
- [案例 7:BRP 算错,波特率不对](#案例 7:BRP 算错,波特率不对)
- [案例 8:多节点位定时不一致](#案例 8:多节点位定时不一致)
- 十、本篇小结与速查
-
- 核心要点
- 位定时速查(f_CAN=48MHz)
- [BTR 配置步骤](#BTR 配置步骤)
- [CAN FD 双位定时](#CAN FD 双位定时)
- 检查清单
- 延伸阅读
- 参考资料
一、位时间组成
1.1 位时间分段
CAN 一个位时间(Time Quantum, Tq)分四段:
┌──────────┬─────────────────┬──────────────┐
│ SYNC_SEG │ TSEG1(PTS+ │ TSEG2 │
│ (同步段) │ PBS1) │ (PBS2) │
│ 1 Tq │ 1~16 Tq │ 1~8 Tq │
└──────────┴─────────────────┴──────────────┘
↑采样点(SP)
| 段 | 含义 | Tq 数 |
|---|---|---|
| SYNC_SEG | 同步段(跳变应在此时) | 1 |
| TSEG1 | 时间段1(传播 + 相位缓冲1) | 1~16 |
| TSEG2 | 时间段2(相位缓冲2) | 1~8 |
- SYNC_SEG:期望信号跳变发生在这(1 Tq)
- TSEG1:采样前的时间(含传播延迟 + 相位调整)
- TSEG2:采样后的时间(相位调整)
- 采样点在 TSEG1/TSEG2 交界
1.2 总位时间
位时间 = SYNC_SEG + TSEG1 + TSEG2 = (1 + TSEG1 + TSEG2) Tq
- 典型位时间:16~25 Tq(采样点 75~87.5%)
- Tq = CAN 时钟 / 分频
1.3 Tq 计算
Tq = 1 / (f_CAN / BRP) = BRP / f_CAN
- f_CAN:CAN 控制器输入时钟(如 40MHz)
- BRP:波特率预分频(BTR 寄存器配)
二、采样点
2.1 采样点定义
采样点(Sample Point, SP)= 在位时间内的位置(百分比):
SP = (1 + TSEG1) / (1 + TSEG1 + TSEG2) × 100%
- 采样点在 TSEG1 末尾(TSEG2 开始)
- 采样点越后,留给传播延迟的时间越多
2.2 采样点推荐
| 标准/协议 | 推荐采样点 |
|---|---|
| CAN 2.0 | 75~87.5% |
| CANopen | 87.5% |
| DeviceNet | 87.5% |
| J1939 | 87.5%(高速)/ 85%(低速) |
| ARINC 825 | 75~80% |
- 87.5% 是主流(CANopen/J1939/DeviceNet)
- 例:16 Tq 位时间,SP 87.5% → TSEG1=13, TSEG2=2
2.3 采样点为何要靠后
- 传播延迟(信号从一节点到另一节点往返)占位时间一部分
- 采样点靠后,留够传播延迟时间
- 高速 + 长总线,采样点更要靠后(87.5%)
2.4 多采样(可选)
- 部分控制器支持 3 采样(采 TSEG1 末 + 前两 Tq,多数表决)
- 抗扰更好,但减少传播延迟裕量
- 一般不用(单采样够)
三、同步机制
3.1 为什么需要同步
- CAN 没有共享时钟(不像 SPI/I2C)
- 各节点时钟独立(晶振),有偏差
- 靠信号跳变(位填充保证跳变密度)同步
3.2 硬同步(Hard Sync)
-
**帧起始(SOF)**时,所有节点收到跳变,重置位定时到 SYNC_SEG
-
每帧开始同步一次
-
SOF 是显性位(从隐性跳显性),所有节点看到
隐性 ──↓ SOF(显性)── 所有节点硬同步,位定时归 SYNC_SEG
3.3 重同步(Resync)
-
帧中间,信号跳变(位填充保证)用来微调相位
-
跳变比期望早或晚 → 调整 TSEG1 或 TSEG2 长度
期望跳变在 SYNC_SEG:
跳变早(TSEG1 还没到)→ TSEG1 延长(最多 SJW)
跳变晚(TSEG1 过了)→ TSEG2 缩短(最多 SJW)
3.4 同步规则
- 只有隐性→显性跳变触发重同步(显性→隐性不触发)
- 位填充保证最多 5 位有跳变(足够同步)
- SOF 硬同步 + 帧中重同步 = 全程同步
3.5 同步的物理意义
- 抵消节点间时钟偏差(晶振不完全一致)
- 抵消传播延迟(信号到达各节点时刻不同)
- 保证采样点对齐(各节点同时采样)
四、SJW(同步跳转宽度)
4.1 SJW 定义
- 重同步时,TSEG1/TSEG2 可调整的最大量
- SJW = 1~4 Tq
- 太小:无法补偿时钟偏差
- 太大:过度调整,振荡
4.2 SJW 工作原理
跳变比期望早 3 Tq,SJW=2:
→ TSEG1 只能延长 2 Tq(SJW 限制),剩余 1 Tq 误差累积
跳变比期望晚 1 Tq,SJW=2:
→ TSEG2 缩短 1 Tq(在 SJW 内),完全补偿
4.3 SJW 选择
- SJW = min(TSEG1, TSEG2, 4) 通常
- 经验:SJW = TSEG2 / 2 或固定 1~2 Tq
- 时钟偏差大,SJW 适当大;但不超过 TSEG2
4.4 SJW 与时钟容差
- SJW 决定能补偿的最大时钟偏差
- 时钟偏差 > SJW 能补偿 → 同步失败,通信错
五、时钟容差
5.1 时钟容差来源
- 晶振初始偏差(±50ppm)
- 温度漂移(±50ppm)
- 老化(±50ppm)
- 总计:可达 ±100~200ppm(差晶振),好晶振 ±20~50ppm
5.2 时钟容差约束
CAN 协议规定时钟容差上限:
df < min(
SJW / (20 × NBT), // 重同步能力
(1 - SP) / (2 × (13 + SP)), // 13 位累积偏差(填充前)
SP / (2 × (14 - SP)) // 14 位累积偏差(填充后)
)
- NBT:位时间 Tq 数(1+TSEG1+TSEG2)
- SP:采样点(小数,如 0.875)
- 三者取最小,就是允许的时钟容差
5.3 典型容差
| 配置 | 容差 |
|---|---|
| 1M, 16Tq, SP87.5%, SJW=2 | 0.5%(5000ppm) |
| 500k, 16Tq, SP87.5%, SJW=2 | 0.5% |
| 125k, 16Tq, SP87.5%, SJW=2 | 0.5% |
- 一般配置容差 0.10.5%(10005000ppm)
- 普通晶振(±50ppm)远满足
- 容差太严(SJW 小/位时间短)要选好晶振
5.4 选晶振
- 普通 CAN:±50ppm 晶振够
- 高速短位时间(1M, 8Tq):选 ±20ppm 晶振
- 严禁 RC 振荡器(偏差 1%+)
六、BTR 寄存器配置
6.1 STM32 bxCAN BTR
CAN_BTR:
bit 25-24 SJW[1:0]: 同步跳转宽度(0~3,值+1)
bit 22-16 TS2[6:0]: TSEG2(0~7,值+1)
bit 15-0 TS1[3:0]: TSEG1(0~15,值+1) (注意位段,实际 TS1 4bit)
bit 9-0 BRP[9:0]: 波特率预分频(0~1023,值+1)
6.2 配置示例:1Mbit/s, SP 87.5%, f_CAN=42MHz
位时间 = 42MHz / 1Mbit/s = 42 Tq
但要 TSEG1+TSEG2+1 ≤ 25(STM32 限制),要分频:
BRP = 3, Tq = 3/42MHz = 71.4ns
位时间 Tq 数 = 1Mbit/s 周期 / Tq = 1000ns / 71.4ns ≈ 14 Tq
NBT = 14:
SP 87.5% → TSEG1 = 12, TSEG2 = 1, SYNC=1 → 1+12+1=14 ✓
SP = 13/14 = 92.8%(过高)
重算 NBT=16(更标准):
BRP=2.625(非整数,不行)
换 f_CAN=48MHz:
BRP=3, Tq=62.5ns, NBT=16
SP 87.5% → TSEG1=13, TSEG2=2, 1+13+2=16
SP = 14/16 = 87.5% ✓
BTR = SJW=1(00) | TS2=1(2-1=1) | TS1=12(13-1=12) | BRP=2(3-1=2)
6.3 配置口诀
- 算 Tq 数:
NBT = f_CAN / (BRP × bit_rate) - 选 BRP 让 NBT 在 16~25(采样点好调)
- 按 SP 算 TSEG1/TSEG2:
TSEG1 = NBT × SP - 1(取整) - SJW 选 1~2
- 写 BTR
6.4 DesignWare/M_CAN 位定时
- Bosch M_CAN 用 NBTP(标称位定时)/ DBTP(数据位定时 FD)
- 字段:TSEG1/TSEG2/SJW/BRP,逻辑同 STM32
七、CAN FD 位定时
7.1 两套位定时
CAN FD 仲裁段和数据段速率不同,两套位定时:
| 段 | 速率 | 位定时 |
|---|---|---|
| 仲裁段 | 1M(兼容) | NBTP(标称) |
| 数据段 | 5M/8M | DBTP(数据) |
7.2 NBTP(标称位定时)
- 和经典 CAN 一样
- 仲裁段 + CRC 之前 + ACK 之后
- SP 87.5%,1M
7.3 DBTP(数据位定时)
- 数据段(BRS 后到 CRC 前)用
- 5M/8M,位时间短
- 采样点可以不同(通常也 75~87.5%)
- TSEG1/TSEG2 数值小(短位时间)
7.4 FD 位定时约束
- 数据段速率高,传播延迟约束严
- 5M 位时间 200ns,传播延迟要 < 50ns(约 10m 总线)
- 8M 位时间 125ns,总线更短
- SJW 数据段通常 1~2 Tq
7.5 FD 配置示例
仲裁段(NBTP):1M, SP87.5%, f_CAN=80MHz
BRP=5, NBT=16, TSEG1=13, TSEG2=2, SJW=2
数据段(DBTP):5M, SP80%, f_CAN=80MHz
BRP=2, NBT=8, TSEG1=5, TSEG2=2, SJW=1
(5M 位时间 200ns,8 Tq × 25ns)
嵌入式视角:FD 位定时是升级难点
升 CAN FD,位定时要配两套(NBTP + DBTP)。数据段 5M 位时间 200ns,容差极小,总线要短(< 10m),收发器要 FD,采样点要算准。配错数据段 CRC 错。M_CAN,DBTP 寄存器配数据段位定时。
八、关键问题 Q&A
Q1:采样点 87.5% 怎么算?
A :SP = (1 + TSEG1) / (1 + TSEG1 + TSEG2)。NBT=16,SP 87.5%:TSEG1=13, TSEG2=2 → (1+13)/16 = 14/16 = 87.5%。采样点靠后(87.5%)留传播延迟裕量,主流推荐(CANopen/J1939)。
Q2:CAN 没有共享时钟,怎么同步?
A :硬同步 + 重同步。① 硬同步:每帧 SOF(隐性→显性跳变),所有节点位定时归 SYNC_SEG。② 重同步:帧中位填充保证跳变,跳变早晚调整 TSEG1/TSEG2(最多 SJW)。两者抵消时钟偏差 + 传播延迟。
Q3:SJW 配多大?
A :1~2 Tq 通常,不超过 TSEG2。SJW = min(TSEG1, TSEG2, 4)。时钟偏差大 SJW 适当大,但太大过度调整振荡。经验:SJW = TSEG2 / 2 或固定 2 Tq。
Q4:时钟容差怎么满足?
A :选好晶振 。CAN 协议容差通常 0.10.5%(10005000ppm),普通晶振 ±50ppm 远满足。严禁 RC 振荡器(偏差 1%+)。高速短位时间(1M,8Tq)容差严,选 ±20ppm 晶振。
Q5:位定时配错会怎样?
A :全网通信失败 (采样错位,误码)。配错的节点发的帧别人采错(可能 ACK 错),收的帧自己采错。位定时必须全网一致 + 满足传播延迟/时钟容差约束。这是 CAN 调试第二大坑(终端电阻第一)。
Q6:CAN FD 数据段位定时怎么配?
A :两套位定时(NBTP 仲裁段 + DBTP 数据段)。数据段 5M,位时间 200ns,NBT 小(8 Tq),SP 75~80%,SJW 1~2。数据段传播延迟约束严(总线 < 10m @ 5M)。配错数据段 CRC 错,仲裁段正常。
九、实战案例
案例 1:采样点不一致,通信失败
现象:两节点 CAN 通信失败,各自单测正常。
分析:节点 A 采样点 75%,节点 B 87.5%,互相采样错位。
解决:统一采样点 87.5%(重配 BTR),通信正常。
案例 2:时钟偏差大,偶发错
现象:某节点用 RC 振荡器(偏差 1%),CAN 偶发错。
分析:RC 偏差 10000ppm,超 CAN 容差(5000ppm),重同步跟不上。
解决:换晶振(±50ppm),通信稳定。
案例 3:SJW 太小,长帧错
现象:8 字节帧正常,长帧(连续多帧)偶发错。
分析:SJW=1 Tq,补偿能力弱,长帧累积偏差超 SJW。
解决:SJW 加到 2 Tq,长帧稳定。
案例 4:采样点太前,长总线错
现象:100m 总线 500k,采样点 75%,偶发错。
分析:采样点 75%,传播延迟裕量小,100m 往返延迟超裕量。
解决:采样点改 87.5%,传播延迟裕量大,稳定。
案例 5:CAN FD 数据段 CRC 错
现象:CAN FD 仲裁段正常,数据段 5M 偶发 CRC 错。
分析:DBTP 配错(采样点 70%),数据段位时间 200ns,采样窗口窄。
解决:DBTP 重配,采样点 80%,TSEG1/TSEG2 重新算,5M 稳定。
案例 6:晶振温漂,低温通信失败
现象:CAN 通信常温正常,-40°C 低温通信失败。
分析:晶振低温漂移到 +100ppm,超容差(配的 SJW 小)。
解决:换宽温晶振(±30ppm 全温),或加大 SJW。
案例 7:BRP 算错,波特率不对
现象:配 500kbit/s,实测 250kbit/s。
分析:BRP 寄存器值 = 实际分频 - 1(STM32),代码写 BRP=4 当成 4 分频,实际 5 分频。
解决:BRP 寄存器写 3(4-1),实际 4 分频,波特率正确。
案例 8:多节点位定时不一致
现象:5 节点 CAN,某节点加入后全网通信失败。
分析:该节点 BTR 配错(TSEG1 差 1),采样点不一致。
解决:所有节点统一 BTR 配置(相同 f_CAN + 相同 BRP/TSEG1/TSEG2/SJW),全网一致。
十、本篇小结与速查
核心要点
- 位时间 = SYNC_SEG(1 Tq) + TSEG1(1~16) + TSEG2(1~8)
- 采样点 SP = (1+TSEG1)/(1+TSEG1+TSEG2),主流 87.5%
- 同步:硬同步(SOF 重置)+ 重同步(帧中跳变调整 TSEG1/TSEG2)
- SJW(同步跳转宽度):1~4 Tq,重同步调整量上限,通常 1~2
- 时钟容差:协议限 0.1~0.5%,选 ±50ppm 晶振(严禁 RC)
- BTR 配置:算 NBT → 选 BRP → 按 SP 算 TSEG1/TSEG2 → 选 SJW
- CAN FD 两套位定时:NBTP(仲裁段1M)+ DBTP(数据段5M/8M)
- 位定时必须全网一致 + 满足传播延迟/时钟容差约束
位定时速查(f_CAN=48MHz)
| 速率 | BRP | NBT | TSEG1 | TSEG2 | SJW | SP |
|---|---|---|---|---|---|---|
| 1M | 3 | 16 | 13 | 2 | 2 | 87.5% |
| 500k | 6 | 16 | 13 | 2 | 2 | 87.5% |
| 250k | 12 | 16 | 13 | 2 | 2 | 87.5% |
| 125k | 24 | 16 | 13 | 2 | 2 | 87.5% |
| 50k | 60 | 16 | 13 | 2 | 2 | 87.5% |
BTR 配置步骤
- 算 NBT = f_CAN / (BRP × bit_rate),选 BRP 让 NBT=16
- TSEG1 = NBT × SP - 1 = 16 × 0.875 - 1 = 13
- TSEG2 = NBT - 1 - TSEG1 = 16 - 1 - 13 = 2
- SJW = 2(通常)
- BTR = (SJW-1)<<24 | (TSEG2-1)<<16 | (TSEG1-1)<<0 | (BRP-1)
CAN FD 双位定时
- NBTP(仲裁段):同经典,1M, SP87.5%
- DBTP(数据段):5M/8M, NBT小(8), SP75~80%, SJW=1
检查清单
- 全网位定时一致(BRP/TSEG1/TSEG2/SJW)
- 采样点 87.5%(主流)
- SJW 1~2 Tq
- 晶振 ±50ppm 以内(禁 RC)
- 传播延迟满足(总线长度)
- FD 两套位定时(NBTP + DBTP)
延伸阅读
- \[01-CAN物理层与差分电气] ------ 位填充维持同步
- \[02-CAN信号完整性与拓扑] ------ 传播延迟与总线长
- \[04-CAN帧格式] ------ SOF 同步
- \[08-CAN控制器寄存器与IP架构] ------ BTR 寄存器
- \[13-CAN调试与排查] ------ 位定时问题排查
- \[03-SPI速度与电气约束] ------ 对比 SPI 采样窗口
参考资料
- Bosch CAN Specification 2.0(位定时章节)
- CiA 301(CANopen 位定时推荐)
- STM32 RM0090(CAN BTR 章节)
- Bosch M_CAN User Manual(NBTP/DBTP)
CAN 技术系列 00 · 总目录 · 上一篇:\[02-CAN信号完整性与拓扑] · 下一篇:\[04-CAN帧格式]
✨ 感谢你的阅读 ✨
技术之路漫漫,分享是为了更好地交流。
如果本文的内容对你有启发,希望能得到你的支持:
👍 点赞 | ⭐ 收藏 | 👀 关注
如果你在调试过程中遇到了其他问题,
欢迎在 评论区 💬 留言,我们一起探讨。
关注我,一起交流底层开发的那些事儿!🚀