# 引言 在工业自动化、机器人协同和车载网络中,时间同步是确保数据一致性和动作协调的基石。传统软件同步(如 PTP 软件实现)受中断延迟和调度抖动影响,精度仅达微秒级。STM32H7 系列(如 H745/H747)内置 FDCAN 控制器和 TSN(时间敏感网络)以太网 MAC,支持硬件时间戳,可在 400MHz 主频下实现纳秒级同步。本文将聚焦 FDCAN 与 TSN 的硬件级时间对齐,提供从原理到落地的完整方案。 # 硬件时间同步原理 ## 1. 时间基准与时钟树 STM32H7 内部有一个 64 位自由运行定时器(如 TIM2/TIM5),可作为全局时间基准。FDCAN 和 TSN 外设均能捕获该定时器的值作为硬件时间戳。关键在于: - **FDCAN**:每个消息帧的 SOF(帧起始)和 EOF(帧结束)均产生时间戳,由硬件自动捕获,无需 CPU 干预。 - **TSN 以太网**:支持 IEEE 802.1AS(gPTP),MAC 在帧的特定位置(如 SFD 后)打时间戳,精度可达 10ns 级。 ## 2. 对齐策略 FDCAN 和 TSN 时间同步的核心是共享同一时间基准。STM32H7 允许将 TIM2 配置为“系统时间”源,FDCAN 和 TSN 均引用该定时器。通过软件校准,使两者时间戳偏差小于一个时钟周期(2.5ns @ 400MHz)。 # 硬件配置步骤 ## 1. 时钟树配置 - 使用 HSE(25MHz)经 PLL1 倍频至 400MHz 系统时钟。 - 配置 TIM2 时钟源为 APB1 定时器时钟(通常为 200MHz),并启用 64 位计数模式(通过级联 TIM2+TIM3 实现)。 ## 2. FDCAN 时间戳使能 - 在 FDCAN 初始化中,设置 `Timestamp` 选项,选择内部定时器作为时间戳源。 - 启用 `Timestamp` 捕获于 SOF 和 EOF。 ## 3. TSN 以太网配置 - 使用 STM32H7 的 Ethernet MAC(支持 TSN),启用 802.1AS 协议栈(如 FreeRTOS+TCP 或 lwIP 的 PTP 扩展)。 - 配置 MAC 的 `Timestamp` 寄存器,选择与 FDCAN 相同的 TIM2 作为时间源。 # 代码示例 以下代码基于 STM32H7 HAL 库,演示如何配置 TIM2 为时间基准,并同步 FDCAN 与 TSN 时间戳。 ```c // 1. 初始化 TIM2 为 64 位时间基准 void TIM2_TimeBase_Init(void) { TIM_HandleTypeDef htim2; htim2.Instance = TIM2; htim2.Init.Prescaler = 0; // 200MHz 直接计数 htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFFFFFF; // 32 位,配合 TIM3 级联 HAL_TIM_Base_Init(&htim2); HAL_TIM_Base_Start(&htim2); } // 2. FDCAN 时间戳配置 void FDCAN_Timestamp_Config(FDCAN_HandleTypeDef *hfdcan) { hfdcan->Init.TimestampConfig = FDCAN_TIMESTAMP_INTERNAL; hfdcan->Init.TimestampPrescaler = 1; // 每个 CAN 位时间计数一次 hfdcan->Init.TimestampSource = FDCAN_TIMESTAMP_SOURCE_TIM2; // 选择 TIM2 HAL_FDCAN_Init(hfdcan); HAL_FDCAN_Start(hfdcan); } // 3. TSN 以太网时间戳配置(简化) void TSN_Timestamp_Config(ETH_HandleTypeDef *heth) { // 启用 MAC 时间戳 heth->Init.TimestampConfig = ETH_TIMESTAMP_ENABLE; heth->Init.TimestampSource = ETH_TIMESTAMP_SOURCE_TIM2; // 与 FDCAN 同源 HAL_ETH_Init(heth); // 配置 PTP 消息过滤 HAL_ETH_PTP_Config(heth, ETH_PTP_MASTER_NODE); } // 4. 读取时间戳并计算偏差 uint64_t Get_FDCAN_Timestamp(FDCAN_HandleTypeDef *hfdcan, uint32_t fifo) { FDCAN_RxHeaderTypeDef rxHeader; uint8_t data[8]; HAL_FDCAN_GetRxMessage(hfdcan, fifo, &rxHeader, data); return rxHeader.Timestamp; // 硬件捕获的 TIM2 值 } uint64_t Get_TSN_Timestamp(ETH_HandleTypeDef *heth) { ETH_PTP_TimeStampTypeDef ts; HAL_ETH_GetRxTimestamp(heth, &ts); return ((uint64_t)ts.Seconds << 32) | ts.Nanoseconds; // 需转换为 TIM2 计数 } // 5. 对齐校准函数(示例) void Align_TimeSync(void) { uint64_t fdcan_ts = Get_FDCAN_Timestamp(&hfdcan1, FDCAN_RX_FIFO0); uint64_t tsn_ts = Get_TSN_Timestamp(&heth); int64_t delta = (int64_t)(fdcan_ts - tsn_ts); // 若 delta 大于阈值,则调整 TIM2 或软件补偿 if (delta > 10) { // 10 个计数约 50ns __HAL_TIM_SET_COUNTER(&htim2, (uint32_t)(tsn_ts + 5)); // 简单校正 } } ``` # 注意事项 - **时钟同步精度**:确保 TIM2 时钟源稳定(使用 HSE 而非 HSI),否则温度漂移会导致偏差累积。 - **中断优先级**:时间戳读取应在高优先级中断中完成,避免被其他中断延迟。 - **FDCAN 位时间**:FDCAN 的位时间需与 TIM2 计数周期匹配,否则时间戳分辨率不足。建议设置 `TimestampPrescaler=1`。 - **TSN 协议栈**:802.1AS 需要硬件辅助,若使用软件实现,精度会下降,务必启用 MAC 硬件时间戳。 - **调试技巧**:使用逻辑分析仪同时抓取 FDCAN 帧和以太网 PTP 帧,对比时间戳偏差,验证对齐效果。 # 总结 通过 STM32H7 的硬件时间戳机制,FDCAN 与 TSN 以太网可共享同一时间基准,实现纳秒级同步。本文提供的配置和代码可直接应用于工业控制或车载网关设计。实际项目中,建议结合 RTOS 和 PTP 协议栈进行动态校准,以应对环境变化。掌握这一技术,将显著提升系统的实时性和可靠性。