引言

在汽车电子与工业控制中,CAN 总线仍是可靠性之王。STM32H7 内置的 FDCAN 支持 CAN FD(灵活数据速率),最高 8Mbps 数据段,而经典 CAN 仅 1Mbps。但高速带来的是更严苛的时序容差要求——尤其在 400MHz 主频下,外设时钟分频、同步跳变宽度(SJW)与采样点位置稍有偏差,就会导致错误帧频发。本文从底层时序模型出发,对比两者容差,并给出可落地的错误帧定位方案。

一、时序容差的理论基础

CAN 位时间由四段组成:同步段(SYNC_SEG)、传播段(PROP_SEG)、相位缓冲段 1(PHASE_SEG1)和相位缓冲段 2(PHASE_SEG2)。采样点位于 PHASE_SEG1 与 PHASE_SEG2 交界处。

  • 经典 CAN:位时间固定,波特率最高 1Mbps,位时间最小 1μs。容差主要来自振荡器漂移(典型 ±0.5%)和总线传播延迟。
  • FDCAN:支持仲裁段(≤1Mbps)与数据段(最高 8Mbps)分离,数据段位时间可短至 125ns。此时,传播延迟(收发器+线缆)占位时间比例急剧上升,容差窗口被压缩。

关键公式

  • 位时间 = (SYNC_SEG + PROP_SEG + PHASE_SEG1 + PHASE_SEG2) × 时间量子(tq)
  • 采样点 = (SYNC_SEG + PROP_SEG + PHASE_SEG1) / 总位时间 × 100%
  • 容差极限 = SJW / 位时间(SJW 最大为 4 tq)

在 400MHz 主频下,若使用 20MHz 外设时钟(PCLK1),则 tq = 50ns。对于 1Mbps 经典 CAN,位时间 = 20 tq,SJW=4 tq 时容差为 20%;但对于 8Mbps FDCAN 数据段,位时间仅 2.5 tq(125ns),SJW 最大 4 tq 已无意义,实际容差由 PHASE_SEG1 长度决定,通常仅 1-2 tq,即 12.5%-25% 的位时间,远小于经典 CAN。

二、STM32H7 FDCAN 配置实战

2.1 CubeMX 配置步骤

  1. 使能 FDCAN1,选择 FDCAN 模式(经典 CAN 或 CAN FD)。
  2. 设置 Bit Timings
    • 仲裁段:Prescaler=2(20MHz/2=10MHz),Time Quanta=10,则波特率=1MHz,采样点=80%(SYNC=1, PROP=2, PHASE1=5, PHASE2=2)。
    • 数据段(CAN FD):Prescaler=1(20MHz),Time Quanta=5,则数据段波特率=4MHz,采样点=75%(SYNC=1, PROP=1, PHASE1=2, PHASE2=1)。
  3. 使能 Protocol Exception Handling(用于处理错误帧)。
  4. 开启 Bus Monitoring 模式(调试用)。

2.2 关键寄存器配置代码

/* FDCAN 初始化结构体 */
FDCAN_InitTypeDef hfdcan1_init = {0};
hfdcan1_init.ClockDivider = FDCAN_CLOCK_DIV1;  // 20MHz
hfdcan1_init.FrameFormat = FDCAN_FRAME_FD_BRS; // 启用 BRS
hfdcan1_init.Mode = FDCAN_MODE_NORMAL;

/* 仲裁段:1Mbps,采样点 80% */
hfdcan1_init.NominalPrescaler = 2;
hfdcan1_init.NominalSyncJumpWidth = 4;
hfdcan1_init.NominalTimeSeg1 = 7;  // PROP+PHASE1 = 2+5
hfdcan1_init.NominalTimeSeg2 = 2;

/* 数据段:4Mbps,采样点 75% */
hfdcan1_init.DataPrescaler = 1;
hfdcan1_init.DataSyncJumpWidth = 2;
hfdcan1_init.DataTimeSeg1 = 3;  // PROP+PHASE1 = 1+2
hfdcan1_init.DataTimeSeg2 = 1;

HAL_FDCAN_Init(&hfdcan1_init);

三、错误帧定位技巧

3.1 硬件级定位:总线分析仪 + 寄存器快照

当总线出现错误帧时,首先用 CAN 分析仪(如 PCAN-USB)抓取波形,观察错误帧类型(位错误、填充错误、CRC 错误)。然后读取 STM32H7 的 FDCAN 错误计数器:

/* 读取错误状态 */
uint8_t tx_err_cnt, rx_err_cnt;
HAL_FDCAN_GetErrorCount(&hfdcan1, &tx_err_cnt, &rx_err_cnt);

/* 读取协议状态寄存器 */
FDCAN_ProtocolStatusTypeDef pstat;
HAL_FDCAN_GetProtocolStatus(&hfdcan1, &pstat);
printf("LastError: %d, BusOff: %d\n", pstat.LastErrorCode, pstat.BusOff);
  • LastErrorCode 可区分:0x1=位错误,0x2=填充错误,0x3=CRC 错误,0x4=格式错误。
  • 结合分析仪波形,若位错误发生在数据段,优先检查数据段波特率与采样点;若在仲裁段,则检查总线终端电阻或节点数。

3.2 软件技巧:错误帧计数与触发中断

利用 FDCAN 的 Error InterruptBus Off Interrupt,在中断中记录时间戳和错误计数器快照,便于事后分析。

void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan) {
    FDCAN_ProtocolStatusTypeDef pstat;
    HAL_FDCAN_GetProtocolStatus(hfdcan, &pstat);
    uint32_t ts = HAL_GetTick();
    // 存储到环形缓冲区
    log_error_frame(ts, pstat.LastErrorCode, hfdcan->Instance->ECR);
}

四、容差优化技巧

  1. 增大 SJW:在经典 CAN 中,SJW 可设为 4 tq,提升抗干扰能力;但在 FDCAN 数据段,SJW 受限于位时间,建议设为 1-2 tq。
  2. 调整采样点:若总线长度 >10m,将采样点后移至 85% 左右,以容忍传播延迟。
  3. 使用 BRS 位速率切换:仲裁段保持 1Mbps 保证兼容,数据段提速至 4-8Mbps,但需确保所有节点支持 FD。
  4. 时钟同步:使用外部晶振(如 25MHz)而非内部 HSI,减少振荡器漂移。

五、注意事项

  • FDCAN 时钟源:STM32H7 的 FDCAN 内核时钟可选 PCLK1 或 PLL2,务必确认实际频率,否则位时序计算全错。
  • 收发器延迟:高速 FD 下,收发器环路延迟(如 TJA1044 约 200ns)不可忽略,需在传播段中预留。
  • 错误帧定位:不要只依赖软件,硬件分析仪是必须的,因为软件可能因中断延迟而丢失关键信息。
  • 兼容性:若总线上有经典 CAN 节点,FDCAN 必须配置为经典模式或 FD 兼容模式,否则会持续产生格式错误。

结语

STM32H7 的 FDCAN 在 400MHz 下提供了强大的性能,但时序容差比经典 CAN 更敏感。通过精确配置位时序、合理利用 SJW 和采样点,并配合硬件分析仪与寄存器快照,可以高效定位和解决错误帧问题。希望本文的技巧能帮助你在实际项目中少走弯路。