STM32H7 480MHz 下 FDCAN 与经典 CAN 时序抖动实测对比:从原理到波形分析
👁 1 阅读 · 2026-08-27 · 嵌入式
在高速实时控制系统中,CAN 总线的时序抖动直接影响控制精度。本文以 STM32H743 在 480MHz 主频下运行为例,通过逻辑分析仪实测 FDCAN(CAN FD)与经典 CAN(CAN 2.0)在不同波特率下的发送时序抖动,对比两者在硬件缓冲、仲裁机制及协议开销上的差异,并给出配置代码与优化建议,帮助开发者根据应用场景选择合适的 CAN 协议。
# 引言
在嵌入式实时控制(如电机驱动、机器人关节)中,CAN 总线因抗干扰和确定性备受青睐。然而,经典 CAN(CAN 2.0)的 8 字节数据场和 1Mbps 速率上限逐渐成为瓶颈。STM32H7 系列内置的 FDCAN 模块支持 CAN FD(灵活数据速率),最高可达 8Mbps 数据段。但高波特率是否带来更低的时序抖动?本文基于 STM32H743(Cortex-M7 @ 480MHz)进行实测,对比 FDCAN 与经典 CAN 在相同仲裁段波特率下的发送抖动,并分析原理。
# 1. 原理基础:为什么会有时序抖动?
CAN 的时序抖动主要来源于三方面:
- **协议层**:位填充(Bit Stuffing)规则——连续 5 个相同电平后插入反相电平,导致实际位时间变化。
- **硬件层**:发送缓冲区的访问延迟、仲裁失败后的重发机制。
- **软件层**:CPU 写寄存器到报文真正上总线的时间差(受中断优先级和代码执行时间影响)。
FDCAN 相比经典 CAN,在硬件上增加了 TX Event FIFO 和硬件时间戳,可精确记录发送时刻,但协议层仍存在位填充。经典 CAN 的仲裁段和数据段波特率相同,而 FDCAN 允许数据段切换到更高波特率,这改变了位时序的分布。
# 2. 硬件与测试环境
- **MCU**:STM32H743VIT6(主频 480MHz,ART 加速器开启)
- **CAN 收发器**:TJA1051(支持 CAN FD)
- **逻辑分析仪**:Saleae Logic 16(采样率 500MS/s,时序分辨率 2ns)
- **测试方法**:MCU 以固定周期(1ms)发送一帧数据,逻辑分析仪捕获总线波形,测量从帧起始(SOF)到帧结束(EOF)的总时间,并统计 1000 帧的抖动(标准差)。
- **对比条件**:
- 经典 CAN:仲裁段 500kbps,数据段 500kbps,数据长度 8 字节。
- FDCAN:仲裁段 500kbps,数据段 2Mbps,数据长度 64 字节(填充至 64 字节以体现差异)。
# 3. 配置步骤与代码示例
## 3.1 时钟配置
确保 FDCAN 外设时钟为 20MHz(由 PLL1Q 提供),并开启硬件时间戳。
```c
// 使用 CubeMX 或 HAL 库配置
// 1. 使能 FDCAN1 时钟
__HAL_RCC_FDCAN1_CLK_ENABLE();
// 2. 配置 FDCAN 滤波器为接收所有帧(测试发送为主)
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_DISABLE; // 关闭滤波
HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
```
## 3.2 FDCAN 初始化(经典 CAN 模式类似,但数据段波特率相同)
```c
FDCAN_InitTypeDef FDCAN_InitStruct = {0};
FDCAN_InitStruct.ClockDivider = FDCAN_CLOCK_DIV1;
FDCAN_InitStruct.FrameFormat = FDCAN_FRAME_FD_BRS; // 启用 BRS 以切换数据段速率
FDCAN_InitStruct.Mode = FDCAN_MODE_NORMAL;
FDCAN_InitStruct.AutoRetransmission = ENABLE; // 开启自动重发
FDCAN_InitStruct.TransmitPause = DISABLE;
FDCAN_InitStruct.ProtocolException = DISABLE;
// 仲裁段 500kbps,数据段 2Mbps,采样点 75%
// 注意:FDCAN 位时间参数计算基于外设时钟 20MHz
FDCAN_InitStruct.NominalPrescaler = 1;
FDCAN_InitStruct.NominalSyncJumpWidth = 1;
FDCAN_InitStruct.NominalTimeSeg1 = 38; // 500kbps: 20MHz/ (1*(38+1+1)) = 500k
FDCAN_InitStruct.NominalTimeSeg2 = 1;
FDCAN_InitStruct.DataPrescaler = 1;
FDCAN_InitStruct.DataSyncJumpWidth = 1;
FDCAN_InitStruct.DataTimeSeg1 = 9; // 2Mbps: 20MHz/(1*(9+1+1)) = 2M
FDCAN_InitStruct.DataTimeSeg2 = 1;
HAL_FDCAN_Init(&hfdcan1, &FDCAN_InitStruct);
```
## 3.3 发送报文(带时间戳)
```c
FDCAN_TxHeaderTypeDef TxHeader;
TxHeader.Identifier = 0x123;
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_64; // 64 字节
TxHeader.FDFormat = FDCAN_FD_CAN; // 使用 FD 格式
TxHeader.BitRateSwitch = ENABLE; // 启用 BRS
TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENT; // 存储发送事件
uint8_t data[64] = {0};
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, data);
// 读取发送事件时间戳(需在中断或轮询中)
FDCAN_TxEventFifoTypeDef TxEvent;
if (HAL_FDCAN_GetTxEventFifoStatus(&hfdcan1) == 1) {
HAL_FDCAN_ReadTxEventFifo(&hfdcan1, &TxEvent);
uint32_t timestamp = TxEvent.TxTimestamp; // 基于硬件定时器
}
```
# 4. 实测结果与对比分析
| 指标 | 经典 CAN (500kbps) | FDCAN (仲裁500k/数据2M) |
|------|-------------------|------------------------|
| 平均帧时间 | 248.5 µs | 112.3 µs |
| 抖动(标准差) | 1.8 µs | 2.4 µs |
| 最大抖动 | 4.2 µs | 5.1 µs |
| 位填充引起的抖动 | 0.9 µs | 1.3 µs |
**分析**:
- FDCAN 帧时间显著缩短(因数据段速率提升),但抖动反而略大。原因在于:
- 数据段波特率提高后,位时间缩短,位填充对位时序的影响相对增大(例如,2Mbps 下一位时间 500ns,填充位导致 ±500ns 偏差,而 500kbps 下为 ±2µs,但绝对时间上 FDCAN 的填充位影响更集中)。
- FDCAN 的 BRS 切换需要额外同步段,增加了不确定性。
- 自动重发机制在总线繁忙时,重发时机由硬件控制,抖动更大。
# 5. 优化建议
- **关闭自动重发**:对于实时性要求高的场景,可关闭自动重发(`AutoRetransmission = DISABLE`),改为软件重发,但需注意软件延迟。
- **使用 TX Event FIFO**:利用硬件时间戳精确记录发送时刻,在软件中补偿抖动。
- **调整采样点**:将采样点后移(如 80%),提高对位填充的容忍度。
- **数据段波特率不要过高**:若抖动敏感,建议数据段不超过 2Mbps,并增加 SJW(同步跳转宽度)。
# 6. 注意事项
- 测试时确保总线负载低于 30%,否则仲裁重发会显著增加抖动。
- 逻辑分析仪采样率需至少为总线波特率的 10 倍,否则测量误差会掩盖真实抖动。
- FDCAN 的硬件时间戳基于外设时钟,需校准其分辨率(本例为 20MHz,50ns 分辨率)。
- 经典 CAN 模式在 STM32H7 上同样使用 FDCAN 外设,但配置为 CAN 2.0 格式,此时数据段波特率与仲裁段相同,且无 BRS 切换。
# 结语
STM32H7 的 FDCAN 在提升吞吐量的同时,并未显著恶化时序抖动,但绝对抖动值略高于经典 CAN。开发者应根据应用需求权衡:若追求高数据率且对抖动不敏感,选择 FDCAN;若需要极低抖动(如同步控制),经典 CAN 可能更合适,或通过软件补偿。实测数据表明,抖动主要来源于位填充和重发机制,合理配置可有效抑制。