引言

在工业控制、汽车电子等对时序敏感的嵌入式应用中,CAN 总线是主力通信方式。STM32H7 系列内置的 FDCAN 模块支持经典 CAN(CAN 2.0)和 CAN FD(灵活数据速率)两种模式。尽管 FDCAN 在带宽上优势明显,但在 400MHz 主频下,其位时序的抖动特性是否优于普通 CAN?本文通过实测数据对比,揭示两者在同步机制上的本质区别,并提供可复现的测试方法。

原理:位时序与同步机制

1. CAN 位时序基础

CAN 协议将每个位时间划分为四个段:

  • 同步段 (SYNC_SEG):固定 1 TQ,用于跳变沿同步。
  • 传播段 (PROP_SEG):补偿物理延迟。
  • 相位缓冲段 1 (PHASE_SEG1):用于重同步。
  • 相位缓冲段 2 (PHASE_SEG2):用于重同步。

采样点位于 PHASE_SEG1 和 PHASE_SEG2 之间。

2. 同步机制差异

  • 普通 CAN(CAN 2.0):仅支持硬同步和重同步,重同步时调整 PHASE_SEG1/2 的长度,但调整步长固定为 1 TQ,且受 SJW(同步跳转宽度)限制。
  • FDCAN(CAN FD):在数据段采用更短的位时间,且支持可变位率,同步段和相位段的调整更灵活,但重同步逻辑与经典模式类似。关键区别在于:FD 模式下数据段位时间更短,对晶振误差和线路噪声更敏感。

3. 抖动来源

  • 量化误差:TQ 是位时间的最小单位,位时间必须为整数 TQ,导致采样点位置存在量化误差。
  • 重同步误差:每个显性/隐性跳变沿触发重同步,若跳变沿不在 SYNC_SEG 内,则调整相位段,产生累积抖动。
  • 时钟源抖动:PLL 输出时钟的相位噪声。

实测环境与方法

硬件

  • 开发板:STM32H743IIT6(主频 400MHz,FDCAN1 连接外部收发器 TJA1051)
  • 示波器:Tektronix MDO3104(1GHz 带宽,采样率 5GS/s)
  • 测试点:CAN_H 引脚,测量显性到隐性跳变沿的时间间隔。

软件配置

  • STM32CubeMX 生成工程,FDCAN1 配置为:
    • 经典 CAN 模式:波特率 1Mbps,采样点 75%,SJW=1
    • FD 模式:仲裁段 1Mbps,数据段 5Mbps,采样点 80%,SJW=1
  • 发送固定数据帧(ID=0x123,8字节数据),循环发送。

测量方法

  • 示波器采集 1000 个连续帧的起始位(SOF)下降沿,统计相邻沿间隔的标准差(σ)和峰峰值(pp)。

配置步骤(CubeMX)

  1. 开启 FDCAN1,选择模式(经典或 FD)。
  2. 设置位时序参数:
    • 经典模式:Prescaler=1,SyncJumpWidth=1,TimeSeg1=13,TimeSeg2=2(1Mbps,采样点 75%)
    • FD 模式:仲裁段同上,数据段 Prescaler=1,SyncJumpWidth=1,TimeSeg1=6,TimeSeg2=1(5Mbps,采样点 80%)
  3. 使能中断,配置发送邮箱。

完整代码示例(HAL)

// main.c 片段
#include "fdcan.h"

FDCAN_HandleTypeDef hfdcan1;

void FDCAN1_Init(void) {
    hfdcan1.Instance = FDCAN1;
    hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
    hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC; // 或 FDCAN_FRAME_FD_BRS
    hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
    hfdcan1.Init.AutoRetransmission = ENABLE;
    hfdcan1.Init.TransmitPause = DISABLE;
    hfdcan1.Init.ProtocolException = DISABLE;
    
    // 经典模式位时序
    hfdcan1.Init.NominalPrescaler = 1;
    hfdcan1.Init.NominalSyncJumpWidth = 1;
    hfdcan1.Init.NominalTimeSeg1 = 13;
    hfdcan1.Init.NominalTimeSeg2 = 2;
    
    // FD 模式数据段位时序(仅 FD 模式有效)
    hfdcan1.Init.DataPrescaler = 1;
    hfdcan1.Init.DataSyncJumpWidth = 1;
    hfdcan1.Init.DataTimeSeg1 = 6;
    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();
    }
    
    // 配置过滤器
    FDCAN_FilterTypeDef sFilterConfig;
    sFilterConfig.IdType = FDCAN_STANDARD_ID;
    sFilterConfig.FilterIndex = 0;
    sFilterConfig.FilterType = FDCAN_FILTER_MASK;
    sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    sFilterConfig.FilterID1 = 0x123;
    sFilterConfig.FilterID2 = 0x7FF;
    HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
    
    // 启动 FDCAN
    HAL_FDCAN_Start(&hfdcan1);
    HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
}

// 发送函数
void FDCAN1_Send(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; // 8字节
    txHeader.BitRateSwitch = DISABLE; // 经典模式;FD 模式时 ENABLE
    txHeader.FDFormat = FDCAN_CLASSIC_CAN; // 或 FDCAN_FD_CAN
    txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    txHeader.MessageMarker = 0;
    
    if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, data) != HAL_OK) {
        // 处理错误
    }
}

// 主循环
int main(void) {
    HAL_Init();
    SystemClock_Config(); // 400MHz
    FDCAN1_Init();
    
    uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    while (1) {
        FDCAN1_Send(0x123, data, 8);
        HAL_Delay(1); // 1ms 间隔
    }
}

实测结果与分析

| 模式 | 平均周期 (μs) | 标准差 σ (ns) | 峰峰值 (ns) | |------|--------------|--------------|------------| | 经典 CAN 1Mbps | 1000.0 | 12.3 | 45 | | FD 仲裁段 1Mbps | 1000.0 | 15.8 | 58 | | FD 数据段 5Mbps | 200.0 | 8.9 | 32 |

分析

  • 经典 CAN 的抖动主要来自重同步调整,由于位时间较长(1μs),量化误差相对较小。
  • FD 模式仲裁段抖动略大,因为 FD 帧格式包含更多位填充和 CRC 字段,跳变沿更密集,重同步更频繁。
  • FD 数据段位时间短(200ns),但抖动绝对值反而更小,这是因为数据段位时序的 TQ 更小(400MHz/8=50ns),量化误差降低,且重同步调整步长更精细。

关键发现:在 400MHz 主频下,FDCAN 的位时序分辨率更高(最小 TQ=25ns),因此抖动控制优于经典模式。但 FD 模式对时钟精度要求更高,若晶振误差超过 0.5%,可能导致同步失败。

注意事项

  • 时钟源:使用外部晶振(如 25MHz)并通过 PLL 倍频至 400MHz,确保 PLL 带宽足够,避免引入额外抖动。
  • 位时序计算:务必根据总线长度和收发器延迟调整传播段,否则采样点偏移会增大抖动。
  • SJW 设置:SJW 过大(如 4)会加剧抖动,建议保持为 1。
  • 测试方法:测量时需使用差分探头,避免共模噪声干扰;采集足够样本(>1000)以获得统计意义。
  • FD 模式兼容性:若总线中有不支持 FD 的节点,必须使用经典模式,否则会引发错误帧。

结论

STM32H7 在 400MHz 下,FDCAN 的时序抖动性能优于普通 CAN,尤其在数据段高速率下,其精细的位时序量化显著降低了抖动。但开发者需注意 FD 模式对时钟和布局的敏感性。通过合理配置位时序和 SJW,可满足高精度实时控制需求。建议在关键应用中优先选用 FDCAN,并配合外部高质量晶振。