4. CAN FD 标准波特率配置:Nominal & Data Bit Timing 计算
好,咱们进入第四章。这一章是 CAN FD 配置里最“硬核”的部分——波特率计算。说白了,就是告诉芯片:你什么时候采样,什么时候跳转,什么时候发下一个位。
我刚开始接触 CAN FD 时,觉得这东西不就是设几个寄存器嘛。结果第一次调试,总线死活不通。后来才发现,是 Nominal 和 Data 两套时序没分开。嗯,这里面的坑,咱们一个个填。
4.1 Nominal Bit Timing:仲裁段的“心跳”
Nominal Bit Timing 负责 CAN FD 的仲裁段和 ACK 段。它的时钟源通常是 APB 时钟(比如 80MHz),然后经过分频、时间段组合,生成一个位时间。
一个 Nominal 位时间由三部分组成:
- Sync_Seg:同步段,固定 1 个 Tq(Time Quantum)。
- BS1(Prop_Seg + Phase_Seg1):传播段 + 相位段1,可编程 1~16 Tq。
- BS2(Phase_Seg2):相位段2,可编程 1~8 Tq。
采样点就在 BS1 和 BS2 的交界处。这个位置很关键——采样点太靠前,信号还没稳定;太靠后,可能错过边沿。
Nominal 位时间公式:
Nominal Bit Time = (Sync_Seg + BS1 + BS2) × Tq
Tq = (BRP + 1) / f_APB
Nominal Baud Rate = 1 / Nominal Bit Time
举个例子。APB 时钟 80MHz,目标波特率 1Mbps,采样点 75%。
| 参数 | 计算过程 | 结果 |
|---|---|---|
| 位时间 Tq 数 | 80MHz / 1Mbps = 80 Tq | 80 |
| Sync_Seg | 固定 1 Tq | 1 |
| BS1 + BS2 | 80 - 1 = 79 Tq | 79 |
| 采样点 75% | BS1 = 79 × 0.75 ≈ 59 Tq | 59 |
| BS2 | 79 - 59 = 20 Tq | 20 |
等等,BS2 最大才 8 Tq,20 超了。这说明什么?说明 80MHz 下 1Mbps 用 75% 采样点,单靠 Tq 数调不过来。得换分频比。
我的经验:Nominal 位时间 Tq 数建议在 8~25 之间。太少,采样精度不够;太多,寄存器位数浪费。我一般先定 Tq 数,再反推 BRP。
4.2 Data Bit Timing:数据段的“高速通道”
Data Bit Timing 是 CAN FD 独有的。它负责数据段的快速传输,最高可达 8Mbps 甚至更高。它的结构和 Nominal 类似,但 Tq 更短,时间段更紧凑。
Data 位时间同样有三段:
- Sync_Seg:固定 1 Tq。
- BS1:可编程 1~16 Tq。
- BS2:可编程 1~8 Tq。
但注意,Data 段的 Tq 时钟源可能和 Nominal 不同。STM32 的 CAN FD 控制器通常允许独立配置 Data 段的预分频器。
Data 位时间公式:
Data Bit Time = (Sync_Seg + BS1 + BS2) × Tq_Data
Tq_Data = (DIV + 1) / f_APB
Data Baud Rate = 1 / Data Bit Time
我做过一个项目,要求 Nominal 500kbps,Data 2Mbps。当时我直接把 Nominal 的 BRP 套到 Data 上,结果 Data 段全是错误帧。后来才意识到,Data 段的 Tq 必须单独算。
| 参数 | Nominal (500kbps) | Data (2Mbps) |
|---|---|---|
| APB 时钟 | 80MHz | 80MHz |
| 预分频 | BRP = 3 → Tq = 50ns | DIV = 0 → Tq = 12.5ns |
| 位时间 Tq 数 | 40 Tq | 40 Tq |
| Sync_Seg | 1 Tq | 1 Tq |
| BS1 | 29 Tq | 29 Tq |
| BS2 | 10 Tq | 10 Tq |
| 采样点 | 75% | 75% |
你看,Tq 数一样,但实际时间差 4 倍。这就是 Data 段能跑高速的秘密。
4.3 采样点配置:别小看这 1%
采样点位置直接影响总线抗干扰能力。CAN 标准推荐采样点在 75%~87.5% 之间。我个人习惯:
- 低速(125kbps 以下):采样点 80%~85%,容忍线缆延迟。
- 中速(250k~500k):采样点 75%~80%,平衡延迟和抖动。
- 高速(1M 以上):采样点 70%~75%,优先保证边沿捕获。
采样点计算公式:
Sample_Point = (Sync_Seg + BS1) / (Sync_Seg + BS1 + BS2) × 100%
举个例子,BS1=29,BS2=10,Sync=1:
Sample_Point = (1 + 29) / (1 + 29 + 10) = 30 / 40 = 75%
我曾经踩过的坑:有一次把采样点设到 68%,结果总线长度超过 10 米就疯狂丢帧。后来改成 80%,问题解决。采样点太靠前,远端节点的信号还没建立稳定就被采样了。
4.4 同步跳转宽度(SJW):给时钟一点“弹性”
SJW 决定了 CAN 控制器在一个位时间内最多能调整多少 Tq 来同步。说白了,就是容忍时钟偏差的能力。
SJW 的取值范围:1~4 Tq,且不能超过 BS2 的值。
为什么不能超过 BS2?因为 SJW 是在同步段之后、BS2 之前调整的。如果 SJW 比 BS2 大,调整后可能超出位时间边界。
| 场景 | SJW 建议 | 理由 |
|---|---|---|
| 晶振精度高(±20ppm) | 1~2 Tq | 时钟偏差小,不需要大跳转 |
| 晶振精度低(±100ppm) | 2~3 Tq | 需要更多余量补偿偏差 |
| 多节点长距离 | 3~4 Tq | 线缆延迟和时钟累积偏差大 |
我一般设 SJW = 2 Tq。除非总线节点超过 20 个,或者线缆长度超过 50 米,我才会考虑 3 Tq。
4.5 波特率表设计:一次配好,到处复用
实际项目中,一个设备可能要适配多种波特率。比如诊断模式用 250kbps,正常通信用 500kbps,固件升级用 1Mbps。手动一个个算太累,我习惯建一个波特率表。
下面是我常用的 STM32 CAN FD 波特率表模板(APB=80MHz):
| 模式 | 波特率 | BRP | Sync | BS1 | BS2 | SJW | 采样点 |
|---|---|---|---|---|---|---|---|
| 低速 | 125kbps | 7 | 1 | 13 | 6 | 2 | 70% |
| 标准 | 250kbps | 3 | 1 | 13 | 6 | 2 | 70% |
| 高速 | 500kbps | 1 | 1 | 13 | 6 | 2 | 70% |
| CAN FD Data | 2Mbps | 0 | 1 | 29 | 10 | 2 | 75% |
| CAN FD Data | 5Mbps | 0 | 1 | 11 | 4 | 2 | 75% |
这个表怎么用?我一般把它定义成结构体数组,放在头文件里。初始化时根据需求查表,直接写寄存器。
typedef struct {
uint32_t baudrate;
uint8_t brp;
uint8_t sync_seg;
uint8_t bs1;
uint8_t bs2;
uint8_t sjw;
} CANFD_BitTiming_TypeDef;
const CANFD_BitTiming_TypeDef canfd_timing_table[] = {
{125000, 7, 1, 13, 6, 2},
{250000, 3, 1, 13, 6, 2},
{500000, 1, 1, 13, 6, 2},
{2000000, 0, 1, 29, 10, 2},
{5000000, 0, 1, 11, 4, 2},
};
我的习惯:波特率表里多留几行空位,方便后期加新速率。另外,Data 段的时序参数我单独放一个表,不和 Nominal 混在一起,避免配错。
4.6 本章知识体系图
下面这张图把 Nominal 和 Data 的时序关系、采样点、SJW 串起来了。你看一眼就能明白整个配置流程。
这张图从左到右展示了配置流程:时钟 → 分频 → 两路时序 → 采样点 + SJW → 最终输出到波特率表。你写代码时,按这个顺序一步步来,基本不会出错。
最后提醒一句:寄存器配置完成后,一定要用示波器或逻辑分析仪抓一下 CAN FD 的波形。我见过太多“理论计算正确,实际波形一塌糊涂”的案例。尤其是 Data 段的高速模式,稍微有点容性负载,边沿就变缓了。实测才是硬道理。