STM32H7 400MHz 下 FDCAN 仲裁段与数据段波特率不一致的配置陷阱与实测

引言

STM32H7 系列凭借 400MHz 主频和双 FDCAN 控制器,成为车载和工业通信的首选。然而,FDCAN 支持仲裁段(Arbitration Phase)与数据段(Data Phase)不同波特率的特性,在高速时钟下极易因位时间参数计算错误导致通信失败。本文基于实际项目,剖析配置陷阱,提供可复现的解决方案。

FDCAN 位时间结构

FDCAN 的位时间由四段组成:同步段(SYNC_SEG)、传播段(PROP_SEG)、相位缓冲段1(PHASE_SEG1)和相位缓冲段2(PHASE_SEG2)。每个段的时间量子(Time Quantum, TQ)数可独立配置,而 TQ 长度由分频后的时钟决定。

关键点:仲裁段和数据段使用不同的位时间寄存器(NBTP 和 DBTP),但共享同一个时钟源。在 STM32H7 中,FDCAN 内核时钟通常来自 FDCAN 总线时钟(如 APB1 或 APB2),最高可达 100MHz(H7 系列中 FDCAN 时钟源可选 PLL1Q 或 PLL2Q)。

配置陷阱分析

陷阱1:忽略时钟分频器差异

STM32H7 的 FDCAN 时钟源可配置为 FDCAN1fdcan_ker_ck,该时钟经过预分频器(BRP)后产生 TQ。许多开发者误以为仲裁段和数据段共用同一个 BRP,但实际上 NBTP 和 DBTP 各自包含独立的 BRP 字段。若未分别设置,会导致波特率完全错误。

陷阱2:位时间参数超出范围

在 400MHz 主频下,若 FDCAN 内核时钟选择 100MHz,仲裁段波特率设为 1Mbps,数据段设为 5Mbps,则:

  • 仲裁段:TQ = 100MHz / BRP,若 BRP=1,则 TQ=10ns,位时间需 100 个 TQ(1μs),但 FDCAN 位时间最大仅 129 TQ(NBTP 中 TSEG1 最大 128,TSEG2 最大 128),看似可行,但实际中 SYNC_SEG 固定为 1 TQ,且 TSEG1 和 TSEG2 需满足采样点要求。
  • 数据段:TQ 相同,但位时间仅需 20 个 TQ(200ns),此时 TSEG1 和 TSEG2 的分配极易超出硬件限制。

陷阱3:采样点设置不当

标准 CAN 推荐采样点 75%~80%,FDCAN 数据段因速率高,建议采样点 70%~75%。若沿用默认值,可能因采样点偏移导致位错误。

配置步骤(基于 STM32CubeMX + HAL)

1. 时钟树配置

在 STM32CubeMX 中,设置主频 400MHz,并将 FDCAN 内核时钟选择为 PLL1Q,输出 100MHz(可通过 RCC->FDCAN 时钟源选择)。

2. FDCAN 参数设置

以仲裁段 1Mbps、数据段 5Mbps 为例:

  • 仲裁段:BRP=1,TSEG1=79,TSEG2=20,SJW=4,采样点 = (1+79)/(1+79+20) = 80/100 = 80%
  • 数据段:BRP=1,TSEG1=13,TSEG2=6,SJW=2,采样点 = (1+13)/(1+13+6) = 14/20 = 70%

注意:数据段位时间共 20 TQ,符合 FDCAN 规范(最小 8 TQ)。

3. 代码实现

/* FDCAN1 初始化函数 */
void FDCAN1_Init(void)
{
    FDCAN_FilterTypeDef sFilterConfig;
    FDCAN_RxHeaderTypeDef RxHeader;

    /* 使能 FDCAN1 时钟 */
    __HAL_RCC_FDCAN1_CLK_ENABLE();

    /* 配置 FDCAN1 参数 */
    hfdcan1.Instance = FDCAN1;
    hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;  // 时钟不分频,使用 100MHz
    hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; // 允许 BRS,数据段可变波特率
    hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
    hfdcan1.Init.AutoRetransmission = DISABLE;
    hfdcan1.Init.TransmitPause = DISABLE;
    hfdcan1.Init.ProtocolException = DISABLE;

    /* 仲裁段波特率 1Mbps */
    hfdcan1.Init.NominalPrescaler = 1;   // BRP=1
    hfdcan1.Init.NominalSyncJumpWidth = 4; // SJW=4
    hfdcan1.Init.NominalTimeSeg1 = 79;    // TSEG1=79
    hfdcan1.Init.NominalTimeSeg2 = 20;    // TSEG2=20

    /* 数据段波特率 5Mbps */
    hfdcan1.Init.DataPrescaler = 1;      // BRP=1
    hfdcan1.Init.DataSyncJumpWidth = 2;  // SJW=2
    hfdcan1.Init.DataTimeSeg1 = 13;      // TSEG1=13
    hfdcan1.Init.DataTimeSeg2 = 6;       // TSEG2=6

    hfdcan1.Init.StdFiltersNbr = 1;
    hfdcan1.Init.ExtFiltersNbr = 0;
    hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;

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

    /* 配置过滤器 */
    sFilterConfig.IdType = FDCAN_STANDARD_ID;
    sFilterConfig.FilterIndex = 0;
    sFilterConfig.FilterType = FDCAN_FILTER_MASK;
    sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    sFilterConfig.FilterID1 = 0x123;
    sFilterConfig.FilterMask = 0x7FF;
    HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);

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

4. 发送与接收示例

/* 发送 FD 帧,使用 BRS */
void FDCAN_SendFD(void)
{
    FDCAN_TxHeaderTypeDef TxHeader;
    uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};

    TxHeader.Identifier = 0x123;
    TxHeader.IdType = FDCAN_STANDARD_ID;
    TxHeader.TxFrameType = FDCAN_DATA_FRAME;
    TxHeader.DataLength = FDCAN_DLC_BYTES_8;
    TxHeader.FDFormat = FDCAN_FD_CAN;  // FD 格式
    TxHeader.BitRateSwitch = FDCAN_BRS_ON; // 启用 BRS
    TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;

    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, data);
}

实测结果与问题排查

在 STM32H750 开发板上,使用逻辑分析仪抓取总线波形,实测结果:

  • 仲裁段波形位宽 1μs,符合 1Mbps;
  • 数据段位宽 200ns,符合 5Mbps;
  • 采样点稳定,无位错误。

常见问题:

  • 若数据段波特率设置过高(如 8Mbps),位时间仅 12.5 TQ,此时 TSEG1 和 TSEG2 的分配必须精确,否则同步失败。建议数据段波特率不超过 5Mbps,以保证足够的 TQ 数。
  • 若使用外部收发器,需注意其支持的数据速率(如 TJA1044 支持 5Mbps)。

注意事项

  • 时钟源选择:确保 FDCAN 内核时钟不超过 100MHz,否则需调整分频器。
  • 位时间计算:建议使用 STM32CubeMX 的图形化工具自动计算,但需手动验证采样点。
  • BRS 使能:只有在 FDFormat 为 FD 且 BitRateSwitch 开启时,数据段波特率才生效。
  • 中断优先级:FDCAN 中断优先级应高于其他非实时中断,避免丢帧。
  • 硬件设计:CAN 总线终端电阻必须正确,否则高速率下信号反射严重。

总结

STM32H7 的 FDCAN 在 400MHz 下实现仲裁段与数据段不同波特率,关键在于理解位时间结构并分别配置 NBTP 和 DBTP。通过合理计算 TQ 分配和采样点,可稳定实现 1Mbps/5Mbps 的混合速率通信。希望本文的实测经验和代码能帮助开发者少走弯路。