STM32H7 FDCAN与CAN 2.0混合组网:波特率容错与仲裁时序实测

1. 背景与挑战

经典CAN 2.0(最高1Mbps)与CAN FD(最高8Mbps数据段)在物理层兼容,但仲裁段(Arbitration Phase)和数据段(Data Phase)采用不同位时序。当混合组网时,所有节点必须共享相同的仲裁段波特率(通常为500kbps),而数据段波特率可独立配置。

核心风险

  • 若FDCAN节点配置的仲裁段波特率与CAN 2.0节点存在微小偏差(如±0.5%),在总线负载高时可能导致仲裁错误或位填充违规。
  • 经典CAN节点无法识别FD帧格式,若FDCAN节点发送FD帧,CAN 2.0节点会报错,因此必须使用经典帧格式(FDF=0)进行混合通信。

2. 波特率容错原理

CAN协议规定,每位时间由同步段(SYNC_SEG)、传播段(PROP_SEG)、相位缓冲段1(PHASE_SEG1)和相位缓冲段2(PHASE_SEG2)组成。接收方通过同步跳转宽度(SJW)补偿发送方时钟偏差。

容错公式

  • 最大容忍偏差 = SJW / (10 × 位时间)(经典CAN)
  • 例如:500kbps,位时间=2μs,SJW=1Tq(Tq=125ns,则位时间=16Tq),最大偏差 = 1/(10×16) = 0.625%

FDCAN增强:STM32H7的FDCAN支持双时钟域,仲裁段和数据段独立配置。但混合组网时,数据段波特率仅影响FD帧传输,仲裁段偏差才是关键。

3. 实测环境与方法

  • 主控:STM32H750VBT6(FDCAN1)
  • 从机:经典CAN收发器TJA1050 + 另一块STM32F103(CAN2.0)
  • 工具:CANoe(监控总线)
  • 配置:仲裁段500kbps,数据段2Mbps(仅用于FD帧测试,混合组网时禁用FD)

测试步骤

  1. 将FDCAN配置为经典模式(FDF=0),发送标准帧,逐步调整仲裁段波特率(从495k到505k,步进1k)。
  2. 记录CANoe中错误帧数量和仲裁丢失次数。
  3. 重复测试,改变总线负载(10%、50%、90%)。

4. 实测数据与结论

| 实际波特率(kbps) | 偏差(%) | 错误帧(负载10%) | 错误帧(负载90%) | 仲裁丢失次数 | |---|---|---|---|---| | 495 | -1.0 | 0 | 3 | 2 | | 497 | -0.6 | 0 | 0 | 0 | | 498 | -0.4 | 0 | 0 | 0 | | 500 | 0 | 0 | 0 | 0 | | 502 | +0.4 | 0 | 0 | 0 | | 503 | +0.6 | 0 | 0 | 0 | | 505 | +1.0 | 0 | 5 | 4 |

关键发现

  • 偏差在±0.6%以内时,总线完全稳定,即使高负载也无错误。
  • 偏差超过±0.8%时,高负载下出现位错误和仲裁丢失,低负载时仍能工作,但存在隐性风险。
  • 经典CAN节点(F103)的时钟源为内部RC,偏差约±0.5%,与FDCAN外部晶振(20ppm)组合,系统总偏差可能超过1%,必须校准。

5. STM32H7 FDCAN配置代码

以下代码配置FDCAN1为经典模式,仲裁段500kbps,使用外部晶振(25MHz)。

#include "stm32h7xx_hal.h"

FDCAN_HandleTypeDef hfdcan1;

void FDCAN1_Init(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,时钟40MHz(PLL1Q),预分频=4,位时间=20Tq
    hfdcan1.Init.NominalPrescaler = 4;
    hfdcan1.Init.NominalSyncJumpWidth = 1;
    hfdcan1.Init.NominalTimeSeg1 = 13;  // 传播段+相位段1
    hfdcan1.Init.NominalTimeSeg2 = 6;   // 相位段2

    // 数据段不用于经典模式,但需配置以避免错误
    hfdcan1.Init.DataPrescaler = 1;
    hfdcan1.Init.DataSyncJumpWidth = 1;
    hfdcan1.Init.DataTimeSeg1 = 1;
    hfdcan1.Init.DataTimeSeg2 = 1;

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

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

// 发送经典帧
void FDCAN_SendClassicFrame(uint32_t id, uint8_t *data, uint8_t len) {
    FDCAN_TxHeaderTypeDef txHeader;
    txHeader.Identifier = id;
    txHeader.IdType = FDCAN_STANDARD_ID;
    txHeader.TxFrameType = FDCAN_DATA_FRAME;
    txHeader.DataLength = len << 16;  // 经典帧长度编码
    txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    txHeader.BitRateSwitch = FDCAN_BRS_OFF;
    txHeader.FDFormat = FDCAN_CLASSIC_CAN;  // 关键:经典帧
    txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    txHeader.MessageMarker = 0;

    if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, data) != HAL_OK) {
        // 处理错误
    }
}

配置要点

  • FrameFormat设为FDCAN_FRAME_CLASSIC,确保只发送经典帧。
  • 位时间计算:Tq = (Prescaler+1)/FDCAN_Clock = 4/40MHz = 100ns,位时间 = (1+13+6)*100ns = 2μs,对应500kbps。
  • SJW设为1Tq,容错范围±0.625%,实测安全。

6. 仲裁时序实测分析

使用逻辑分析仪抓取总线波形,对比FDCAN与CAN2.0节点的SOF(帧起始)到仲裁场结束的时序。

  • 正常情况:两个节点同时发送ID=0x123和0x124,FDCAN在ID位0x123的第2位(0)与0x124的第2位(1)发生冲突,FDCAN检测到显性位(0)而自己发送隐性位(1),立即退出仲裁,转为接收。
  • 偏差影响:当FDCAN波特率偏快(+1%),其位时间缩短,导致采样点提前。在仲裁场,FDCAN可能提前采样到显性位,误判自己赢得仲裁,而实际对方ID更优,造成总线冲突和错误帧。

实测波形:在偏差+1%时,仲裁场出现约200ns的毛刺,CANoe报“Bit Error”。

7. 注意事项与优化建议

  • 时钟源选择:优先使用外部晶振(HSE)或高精度PLL,避免内部RC(精度±1%)。若必须用内部RC,需在初始化时校准(使用HAL_RCC_GetSystemClockFreq)。
  • SJW设置:在混合组网中,SJW可设为2Tq以增加容错,但会降低最大可容忍偏差(因为SJW越大,采样点调整范围越大,但同步越频繁)。实测SJW=2时,偏差±1%仍稳定,但仲裁延迟增加。
  • 位时序重算:若总线长度超过10m,需增加传播段(PROP_SEG)以补偿线路延迟。
  • FD帧禁用:混合组网中,必须确保所有FDCAN节点发送经典帧,否则CAN2.0节点会因格式错误而干扰总线。
  • 错误处理:启用FDCAN的协议异常处理(ProtocolException),当检测到FD帧时自动切换为经典帧接收,避免总线关闭。

8. 总结

STM32H7 FDCAN在混合组网中,只要仲裁段波特率偏差控制在±0.6%以内,即可保证稳定通信。实测表明,高负载下偏差容限更小,建议使用外部晶振并合理配置SJW。通过上述代码和配置,开发者可快速实现可靠混合网络。

延伸思考:若需支持FD帧,可考虑使用“FDF=1,BRS=0”的FD帧(数据段与仲裁段同速),这样CAN2.0节点仍能识别,但无法利用高速数据段。权衡后,经典模式仍是混合组网的首选。