STM32H7 400MHz 下 FDCAN 与经典 CAN 的时序兼容性陷阱及规避

1. 背景与问题本质

STM32H7 系列内置的 FDCAN 模块(基于 Bosch M_CAN)支持 CAN 2.0 和 CAN FD 协议。当系统主频高达 400MHz 时,FDCAN 的位时序计算极易出现量化误差,尤其在混合网络中与经典 CAN(1.0/2.0)节点共存时,会引发间歇性错误帧、总线关闭甚至完全无法通信。

核心陷阱:FDCAN 的位时间由 TQ(Time Quantum)组成,而 TQ 长度 = 1 / (FDCAN_KER_CLK / Prescaler)。当内核时钟为 400MHz 时,若直接套用低主频下的分频策略,TQ 数量可能不足,导致采样点位置偏离理想值(通常 75%~80%),进而破坏与经典 CAN 节点的同步。

2. 时序基础与差异分析

2.1 位时间结构

CAN 协议中,一个位时间分为四段:

  • 同步段(SYNC_SEG):固定 1 TQ
  • 传播段(PROP_SEG):补偿物理延迟
  • 相位缓冲段 1(PHASE_SEG1):采样点前
  • 相位缓冲段 2(PHASE_SEG2):采样点后

采样点位置 = (SYNC_SEG + PROP_SEG + PHASE_SEG1) / 总 TQ 数。

2.2 FDCAN 与经典 CAN 的差异

| 特性 | FDCAN(CAN FD) | 经典 CAN | |------|----------------|----------| | 最大速率 | 8 Mbps(数据段) | 1 Mbps | | 位时间最小 TQ 数 | 8(仲裁段) | 8(但通常要求 ≥10) | | 同步跳转宽度(SJW) | 1~4 TQ | 1~4 TQ | | 采样点推荐 | 75%~80% | 75%~87.5% |

关键陷阱:在 400MHz 下,若设置 Prescaler=1,则 TQ=2.5ns,对于 500kbps 的经典 CAN,位时间需 2000ns,即 800 TQ——这远超 FDCAN 硬件限制(通常最大 256 TQ)。因此必须增大 Prescaler,但 Prescaler 增大后 TQ 数量减少,若配置不当,采样点偏移超过 5% 就会导致错误。

3. 具体陷阱场景

3.1 陷阱一:TQ 数量不足导致采样点偏移

假设 FDCAN_KER_CLK = 400MHz,目标速率 500kbps。

  • 若 Prescaler = 8,则 TQ = 8/400MHz = 20ns,位时间 = 2000ns / 20ns = 100 TQ。
  • 若按默认配置(如 16 TQ 位时间),则实际速率 = 400MHz / (8 * 16) = 3.125Mbps,完全错误。

后果:总线上的经典 CAN 节点无法识别帧起始,持续报错。

3.2 陷阱二:SJW 设置过小导致同步失败

经典 CAN 节点在总线空闲后发送帧时,FDCAN 需要重新同步。若 SJW 小于网络中的最大相位误差(由时钟漂移和线缆延迟引起),同步失败,产生错误帧。

3.3 陷阱三:数据段与仲裁段不同步

在 CAN FD 模式下,数据段速率可高于仲裁段,但经典 CAN 节点不支持 FD 帧。若 FDCAN 配置为 FD 模式且未启用“FD 帧自动拒绝”,则经典 CAN 节点会因无法识别 FD 帧而报错。

4. 配置步骤与规避方案

4.1 使用 STM32CubeMX 精确配置

  1. 打开 STM32CubeMX,选择 STM32H7 系列芯片(如 STM32H743)。
  2. 配置时钟树:确保 FDCAN_KER_CLK 为 400MHz(通常由 PLL1Q 提供)。
  3. 启用 FDCAN1,模式选择“CAN 2.0”或“CAN FD”(若需兼容经典 CAN,选择“CAN 2.0”)。
  4. 设置位时序参数:
    • 仲裁段波特率:500kbps
    • 数据段波特率(若 FD):2Mbps(可选)
    • Prescaler:根据公式计算,确保 TQ 数在 8~25 之间。
    • 采样点:设置为 80%(经典 CAN 推荐)。
    • SJW:设置为 2~4 TQ。

关键公式

  • 位时间 TQ 数 = (FDCAN_KER_CLK / Prescaler) / 波特率
  • 采样点百分比 = (1 + PropSeg + PhaseSeg1) / (1 + PropSeg + PhaseSeg1 + PhaseSeg2) * 100%

4.2 代码级配置示例

以下代码基于 STM32 HAL 库,展示如何手动配置 FDCAN 位时序,确保与经典 CAN 兼容。

#include "stm32h7xx_hal.h"

FDCAN_HandleTypeDef hfdcan1;

void FDCAN1_Config(void)
{
    hfdcan1.Instance = FDCAN1;
    hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;  // 时钟不分频
    hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC; // 经典 CAN 模式
    hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
    hfdcan1.Init.AutoRetransmission = ENABLE;
    hfdcan1.Init.TransmitPause = DISABLE;
    hfdcan1.Init.ProtocolException = DISABLE;

    // 位时序配置:500kbps,采样点 80%,SJW=4
    hfdcan1.Init.NominalPrescaler = 8;   // TQ = 8/400MHz = 20ns
    hfdcan1.Init.NominalSyncJumpWidth = 4; // SJW = 4 TQ
    hfdcan1.Init.NominalTimeSeg1 = 13;   // PropSeg + PhaseSeg1 = 13 TQ
    hfdcan1.Init.NominalTimeSeg2 = 2;    // PhaseSeg2 = 2 TQ
    // 总 TQ = 1 + 13 + 2 = 16,位时间 = 16 * 20ns = 320ns?错误!
    // 实际应为 100 TQ,这里需要重新计算。

    // 正确计算:500kbps 位时间 = 2000ns,TQ = 20ns,需要 100 TQ。
    // 但 FDCAN 硬件限制 TQ 数最大 256,可以。
    // 设置:Prescaler=8,TimeSeg1=79,TimeSeg2=20,SJW=4
    // 采样点 = (1+79)/(1+79+20) = 80/100 = 80%
    hfdcan1.Init.NominalPrescaler = 8;
    hfdcan1.Init.NominalSyncJumpWidth = 4;
    hfdcan1.Init.NominalTimeSeg1 = 79;
    hfdcan1.Init.NominalTimeSeg2 = 20;

    if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
    {
        Error_Handler();
    }

    // 启动 FDCAN
    HAL_FDCAN_Start(&hfdcan1);
    HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
}

注意:上述代码中注释部分展示了常见错误,正确配置需根据实际时钟计算。建议使用 CubeMX 自动生成,避免手算错误。

4.3 规避策略汇总

  • 策略一:始终使用 CubeMX 的“Bit Timing”计算器,输入目标波特率和时钟,自动生成参数。
  • 策略二:在混合网络中,强制 FDCAN 使用经典 CAN 模式(FDCAN_FRAME_CLASSIC),避免 FD 帧干扰。
  • 策略三:增大 SJW 至 4 TQ,以容忍时钟漂移和线缆延迟。
  • 策略四:采样点设置在 75%~80% 之间,经典 CAN 节点通常能容忍此范围。
  • 策略五:若必须使用 CAN FD,启用“FDCAN 自动拒绝 FD 帧”功能(FDCAN_PROTOCOL_EXCEPTION_DISABLE),并确保数据段速率不超过 2Mbps(经典 CAN 节点无法处理)。

5. 注意事项与调试技巧

  • 时钟源选择:FDCAN 内核时钟可选 PLL1Q 或 PLL2Q,务必确认其频率。若使用 HSI(64MHz),则 TQ 计算不同。
  • 总线终端电阻:高速下(>1Mbps)必须使用 120Ω 终端电阻,否则信号反射导致位错误。
  • 调试工具:使用示波器测量 CAN_H/CAN_L 差分信号,观察位宽度和采样点位置。
  • 错误分析:利用 FDCAN 的错误计数器(ECR)和协议状态寄存器,判断错误类型(位错误、填充错误等)。
  • 软件滤波:在接收中断中,检查帧 ID 和 DLC,避免误处理错误帧。

6. 总结

STM32H7 在 400MHz 下运行 FDCAN 时,时序兼容性问题的根源在于 TQ 量化误差和采样点偏移。通过精确配置位时序参数、合理选择 SJW 和采样点,并严格使用经典 CAN 模式(或正确管理 FD 帧),可以完全规避这些陷阱。建议开发者始终借助 CubeMX 工具,并在实际硬件上验证时序,以确保混合网络的健壮性。