共计 1671 个字符,预计需要花费 5 分钟才能阅读完成。
从故障波形看时间参数的重要性
上周调试一台工业控制器时,用示波器抓到了这样的 CAN 总线波形(图 1):显性电平的下降沿出现明显振铃,导致接收节点采样点位置偏移,最终引发 CRC 错误。根本原因是波特率 1Mbps 下,传播段 (PROP_SEG) 设置过短,无法抵消物理层信号畸变。

图示:黄色为 CAN_H 信号,蓝色为 CAN_L 信号,红色箭头标记振铃导致的采样偏移
CAN 2.0B 时间参数解剖
-
时间份额 (Tq) 基础:每个 CAN 位时间被划分为 4 -25 个 Tq(Time Quantum),STM32 通常用 8 -12Tq。例如 1Mbps 时,1Tq=1μs/(1+PROP_SEG+PHASE_SEG1+PHASE_SEG2)
-
四段式结构:
- SYNC_SEG(固定 1Tq):用于硬同步
- PROP_SEG(1-8Tq):补偿物理延迟
- PHASE_SEG1(1-8Tq):软同步调整区
-
PHASE_SEG2(2-8Tq):相位缓冲
-
黄金采样点:推荐在 75%-80% 位时间处采样,即满足:SYNC_SEG + PROP_SEG + PHASE_SEG1 ≈ 总 Tq 的 3 /4
STM32 配置实战对比
CubeMX 自动配置
// CubeMX 生成的初始化片段
hcan.Instance = CAN1;
hcan.Init.Prescaler = 1;
hcan.Init.TimeSeg1 = CAN_BS1_5TQ; // PROP+PHASE1
hcan.Init.TimeSeg2 = CAN_BS2_3TQ; // PHASE2
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
优点:快速验证,适合原型阶段
缺点:无法精细调整 PROP_SEG,且 SyncJumpWidth 固定为 1Tq
手动寄存器配置
// 精准控制位时序(1Mbps @ 48MHz APB1)
CAN1->BTR &= ~(CAN_BTR_TS1 | CAN_BTR_TS2 | CAN_BTR_SJW);
CAN1->BTR |= (5U << 16) | // TS1=6Tq (PROP+PHASE1)
(2U << 20) | // TS2=3Tq (PHASE2)
(1U << 24); // SJW=2Tq
// 计算公式:// BaudRate = APB1_CLK / (Prescaler * (1 + TS1 + TS2))
// 本例:48MHz/(1*(1+6+3))=4.8MHz → 实际需要分频调整
关键技巧:通过 LL_CAN_Init()覆盖 HAL 默认配置
实测数据分析
使用 CANalyzer 对比两组参数(500kbps):
| 参数组合 | 负载率 @100 帧 /ms | 错误帧率 |
|---|---|---|
| TS1=8,TS2=3,SJW=1 | 32% | 0.01% |
| TS1=5,TS2=2,SJW=1 | 28% | 1.2% |
发现:缩短 PHASE_SEG1 虽提升吞吐量,但采样点前移导致错误率飙升
汽车电子特殊应对
- 冷启动补偿:
- 在 -40℃时,晶振频率可能漂移±0.2%
-
对策:通过 CAN 收发器 TXD 下降沿反馈动态调整 SYNC_SEG
-
参数存储方案:
// Flash 模拟 EEPROM 存储结构体 #pragma pack(push, 1) typedef struct { uint32_t crc32; uint8_t ts1; uint8_t ts2; uint8_t sjw; } CanConfig; #pragma pack(pop) // CRC 校验示例 uint32_t calc_crc(const CanConfig* cfg) { return HAL_CRC_Calculate( &hcrc, (uint32_t*)&cfg->ts1, sizeof(CanConfig)-4); }注意:存储前需擦除整个扇区,避免 bit 错误
延伸思考
当系统需要同时支持 CAN 2.0B 和 CAN FD 时,如何设计时间参数满足:
– 传统模式 1Mbps 下保持 ISO 11898- 1 合规
– FD 模式下实现 5Mbps 数据段速率?
(提示:考虑动态切换 Prescaler 和二次采样机制)
调试心得
- 用逻辑分析仪抓取 TXD/RXD 比对,比单纯看 CAN_H/ L 更直观
- 在 PCB 布局时,保持 CAN 收发器靠近 MCU,减少 PROP_SEG 需求
- 量产前务必做 -40℃~85℃的全温测试,观察同步稳定性
