# 引言 在工业自动化与车载以太网融合场景中,FDCAN(Flexible Data-rate CAN)与 TSN(Time-Sensitive Networking)常共存于同一网关。FDCAN 提供确定性实时控制,TSN 则保证以太网流量调度。两者时间同步的精度直接决定系统协同性。STM32H7 系列以 480MHz Cortex-M7 内核、内置 FDCAN 控制器和 IEEE 1588 硬件时间戳单元,为硬件级抖动补偿提供了理想平台。 # 原理:时间同步与抖动来源 ## 1. 同步机制 - FDCAN 支持 CAN FD 协议,其时间戳单元(TSU)可捕获消息发送/接收的精确时刻,分辨率达 1ns(基于 480MHz 时钟)。 - TSN 依赖 IEEE 802.1AS(gPTP),通过硬件时间戳在以太网 MAC 层打点,同步精度可达亚微秒。 - 两者需共享统一时基(如系统时钟或外部 PPS),才能实现跨网络同步。 ## 2. 抖动来源 - 软件中断延迟:中断响应时间受缓存、分支预测影响,通常 100ns~1μs。 - 总线仲裁延迟:FDCAN 多节点竞争时,消息发送时刻不确定。 - 时钟漂移:晶振温漂导致时基偏差,需周期性校正。 - 硬件路径差异:FDCAN 收发器、以太网 PHY 的传播延迟不同。 硬件级补偿的核心是:利用 STM32H7 的硬件时间戳在物理层捕获事件,避免软件介入,从而消除大部分抖动。 # 硬件架构与配置步骤 ## 1. 时钟树配置 - 使用 HSE 外部晶振(25MHz),通过 PLL1 倍频至 480MHz 系统时钟。 - 配置 FDCAN 时钟源为 PLL2(如 80MHz),确保 TSU 计数频率与系统时钟独立,便于校准。 - 使能 IEEE 1588 时间戳时钟(如 200MHz),用于以太网 MAC。 ## 2. FDCAN 时间戳单元配置 - 在 STM32CubeMX 中启用 FDCAN1,选择硬件时间戳模式。 - 设置 TSU 为外部时钟输入(如 TIM1 的 TRGO),实现与 TSN 时基同步。 - 配置消息 RAM 中的时间戳缓冲区,用于存储捕获时刻。 ## 3. TSN 以太网配置 - 使用 STM32H7 的 Ethernet MAC(支持 1588v2),启用硬件时间戳。 - 配置 PTP 时钟源为系统时钟,并设置时钟校正寄存器。 - 通过 MDIO 配置外部 PHY(如 KSZ9031)的 1588 功能。 ## 4. 同步校准流程 - 启动时,通过 GPIO 输出 PPS 信号,同时捕获 FDCAN 和 TSN 时间戳,计算初始偏移。 - 周期(如 1s)通过 TSN 的 Sync 消息更新主时钟,并调整 FDCAN TSU 的补偿值。 # 代码实现 以下代码基于 STM32H743,使用 HAL 库,展示 FDCAN 时间戳捕获与 TSN 同步补偿的核心逻辑。 ```c // FDCAN 时间戳捕获配置 void FDCAN_Timestamp_Init(void) { FDCAN_HandleTypeDef hfdcan1; hfdcan1.Instance = FDCAN1; hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1; hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; hfdcan1.Init.AutoRetransmission = DISABLE; hfdcan1.Init.TimestampConfig = FDCAN_TIMESTAMP_INTERNAL; // 使用内部 TSU hfdcan1.Init.TimestampPrescaler = 1; // 1ns 分辨率(480MHz) HAL_FDCAN_Init(&hfdcan1); // 配置 TSU 外部同步输入(如 TIM1_TRGO) HAL_FDCAN_EnableTimestampUnit(&hfdcan1, FDCAN_TIMESTAMP_UNIT_EXTERNAL); } // 捕获 FDCAN 消息时间戳(中断回调) void HAL_FDCAN_RxFifo0MsgPendingCallback(FDCAN_HandleTypeDef *hfdcan) { FDCAN_RxHeaderTypeDef rxHeader; uint8_t data[8]; HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rxHeader, data); uint64_t fdcan_timestamp = rxHeader.Timestamp; // 硬件捕获时刻 // 与 TSN 时钟比较,计算偏移 uint64_t tsn_timestamp = Get_TSN_Time(); // 从以太网 PTP 获取 int64_t offset = (int64_t)tsn_timestamp - (int64_t)fdcan_timestamp; // 补偿:调整 TSU 的偏移寄存器(假设有) HAL_FDCAN_SetTimestampOffset(&hfdcan1, offset); } // TSN 时钟读取(简化) uint64_t Get_TSN_Time(void) { // 读取以太网 MAC 的 1588 时间戳寄存器 return (uint64_t)ETH->PTPTSHR << 32 | ETH->PTPTSLR; } ``` # 抖动补偿算法 ## 1. 静态补偿 - 测量 FDCAN 收发器(如 TJA1044)的环路延迟(典型 200ns),在 TSU 中预设偏置。 - 以太网 PHY 的延迟(如 150ns)在 MAC 时间戳中修正。 ## 2. 动态补偿 - 使用 PI 控制器:根据偏移量调整 TSU 的时钟频率(通过预分频器),实现闭环同步。 - 示例:每收到一次 Sync 消息,计算偏移误差,更新预分频值。 ```c // PI 控制器调整 TSU 预分频 void PI_Compensate(int64_t offset) { static float integral = 0; float kp = 0.1, ki = 0.01; integral += offset * ki; int32_t adjust = (int32_t)(offset * kp + integral); // 限制调整范围 if (adjust > 100) adjust = 100; if (adjust < -100) adjust = -100; HAL_FDCAN_SetTimestampPrescaler(&hfdcan1, 1 + adjust); // 调整计数频率 } ``` # 注意事项 - **时钟源选择**:FDCAN TSU 和 TSN 必须使用同一时基,否则无法同步。建议使用外部高精度时钟(如 OCXO)。 - **中断优先级**:FDCAN 时间戳中断应设为最高优先级,避免被其他中断延迟。 - **消息 RAM 溢出**:高频消息下,时间戳缓冲区可能溢出,需及时读取或使用 DMA。 - **硬件版本**:部分 STM32H7 型号的 TSU 不支持外部同步,需查阅数据手册(如 H743 支持,H750 可能受限)。 - **调试技巧**:通过 GPIO 输出同步脉冲,用示波器测量 FDCAN 和 TSN 的 PPS 信号,验证补偿效果。 # 总结 通过 STM32H7 的硬件时间戳单元,FDCAN 与 TSN 的同步抖动可从微秒级降至纳秒级。本文提供的配置与代码可作为基础框架,实际工程中需根据具体 PHY 和收发器调整延迟参数。硬件级补偿是嵌入式实时通信的基石,掌握后能显著提升系统确定性。