# 引言 STM32H7 系列凭借 Cortex-M7 内核和高达 480MHz 的主频,在工业控制、汽车电子等领域大放异彩。其内置的 FDCAN 模块(兼容 Bosch M_CAN)支持 CAN 2.0 和 CAN FD 两种模式,但在实际项目中,FDCAN 与经典 CAN 节点共存时,时序配置不当会引发通信异常。本文聚焦 480MHz 时钟下的位时序配置陷阱,提供可落地的解决方案。 # FDCAN 与经典 CAN 的时序差异 经典 CAN(ISO 11898-1:2003)采用固定 1 Mbps 速率,位时序由同步段(SYNC_SEG)、传播段(PROP_SEG)、相位缓冲段 1(PHASE_SEG1)和相位缓冲段 2(PHASE_SEG2)组成。FDCAN(ISO 11898-1:2015)在仲裁段保持相同结构,但数据段支持可变速率(最高 8 Mbps),且引入了额外的同步机制。 关键差异点: - **位时间量化(TQ)**:经典 CAN 要求 TQ 数在 8~25 之间,而 FDCAN 数据段允许更小的 TQ 数(如 4~25),但仲裁段仍遵循经典规则。 - **采样点**:经典 CAN 推荐采样点在 75%~80%,FDCAN 仲裁段相同,但数据段可调整至 70%~90%。 - **同步跳转宽度(SJW)**:FDCAN 支持 1~4 TQ,经典 CAN 通常为 1~2 TQ,配置不当会降低抗干扰能力。 # 480MHz 下的位时序计算陷阱 STM32H7 的 FDCAN 内核时钟(FDCAN_KER_CK)通常由 PLL1Q 提供,典型值为 80MHz(480MHz / 6)。位时间计算如下: \[ \text{位时间} = \frac{1}{\text{波特率}} \] \[ \text{TQ} = \frac{\text{FDCAN_KER_CK}}{\text{波特率}} \] 例如,经典 CAN 1 Mbps 时,TQ = 80MHz / 1Mbps = 80。然而,80 超出了经典 CAN 的 25 TQ 上限!这是第一个陷阱:**直接使用 80MHz 内核时钟无法配置 1 Mbps 经典 CAN**。 解决方案:通过 FDCAN 的时序预分频器(BRP)降低 TQ 数。例如,设置 BRP = 4,则 TQ = 80 / 4 = 20,满足要求。但 BRP 配置不当会导致采样点偏移,尤其在混合网络中。 # 配置步骤(基于 STM32CubeMX) 1. **时钟配置**:在 RCC 中启用 PLL1,设置 FDCAN_KER_CK 为 80MHz(确保不超过 100MHz 上限)。 2. **FDCAN 参数设置**: - 模式:经典 CAN(或 CAN FD 兼容) - 波特率:1 Mbps(仲裁段) - 数据段波特率(若启用 FD):5 Mbps - 采样点:75%(经典) - 同步跳转宽度:2 TQ 3. **计算预分频器**:使用 CubeMX 的自动计算功能,但需手动验证 TQ 数。例如,1 Mbps 时,BRP = 4,TQ = 20,位时间分配:SYNC=1, PROP=2, PHASE1=7, PHASE2=10(采样点 = (1+2+7)/20 = 50%?错误!)。 **陷阱二**:CubeMX 默认分配可能不满足采样点要求,需手动调整。正确分配:SYNC=1, PROP=3, PHASE1=8, PHASE2=8,采样点 = (1+3+8)/20 = 60%,仍偏低。应改为 SYNC=1, PROP=2, PHASE1=9, PHASE2=8,采样点 = (1+2+9)/20 = 60%?不对,需重新计算。 实际推荐:SYNC=1, PROP=1, PHASE1=6, PHASE2=12,采样点 = (1+1+6)/20 = 40%,更差。正确做法:采样点 = (SYNC + PROP + PHASE1) / TQ,目标 75%,则 (1 + PROP + PHASE1) / 20 = 0.75,得 PROP + PHASE1 = 14,可取 PROP=2, PHASE1=12,但 PHASE1 最大为 16,可行。最终:SYNC=1, PROP=2, PHASE1=12, PHASE2=5,采样点 = (1+2+12)/20 = 75%,且 SJW=2。 # 完整代码示例(HAL 库) ```c #include "stm32h7xx_hal.h" FDCAN_HandleTypeDef hfdcan1; FDCAN_FilterTypeDef sFilterConfig; void FDCAN1_Init(void) { hfdcan1.Instance = FDCAN1; hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1; hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC; hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; hfdcan1.Init.AutoRetransmission = ENABLE; hfdcan1.Init.TransmitPause = DISABLE; hfdcan1.Init.ProtocolException = DISABLE; // 经典 CAN 1 Mbps,内核时钟 80MHz,BRP=4,TQ=20 hfdcan1.Init.NominalPrescaler = 4; hfdcan1.Init.NominalSyncJumpWidth = 2; hfdcan1.Init.NominalTimeSeg1 = 12; // PROP + PHASE1 hfdcan1.Init.NominalTimeSeg2 = 5; // PHASE2 // 若启用 FD,数据段配置(此处省略) if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) { Error_Handler(); } // 配置过滤器,接收所有 ID sFilterConfig.IdType = FDCAN_STANDARD_ID; sFilterConfig.FilterIndex = 0; sFilterConfig.FilterType = FDCAN_FILTER_MASK; sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; sFilterConfig.FilterID1 = 0x000; sFilterConfig.FilterID2 = 0x7FF; // 掩码全 1,匹配所有 HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig); // 启动 FDCAN HAL_FDCAN_Start(&hfdcan1); HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); } // 发送经典 CAN 帧 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 字节为 0x00080000 txHeader.BitRateSwitch = DISABLE; // 经典 CAN 无 BRS txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; txHeader.BitRateSwitch = FDCAN_BRS_OFF; txHeader.FDFormat = FDCAN_CLASSIC_CAN; HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, data); } // 中断回调 void HAL_FDCAN_RxFifo0MsgPendingCallback(FDCAN_HandleTypeDef *hfdcan) { FDCAN_RxHeaderTypeDef rxHeader; uint8_t rxData[8]; if (hfdcan->Instance == FDCAN1) { HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &rxHeader, rxData); // 处理数据 } } ``` # 混合网络兼容性调试技巧 - **使用示波器测量实际波形**:对比发送节点的 TX 引脚和接收节点的 RX 引脚,检查位宽度是否一致。经典 CAN 的位时间应为 1μs(1 Mbps),若偏差超过 2%,则需调整预分频器。 - **检查错误计数器**:通过 HAL_FDCAN_GetError() 读取协议错误和总线错误计数,若持续增加,说明时序不匹配。 - **利用 FDCAN 的延迟补偿**:在 FD 模式下,数据段速率切换时,FDCAN 会自动插入延迟补偿(SSP),但经典 CAN 无此功能,需确保仲裁段时序严格。 - **避免使用自动重传**:在调试阶段,关闭自动重传(AutoRetransmission = DISABLE),便于观察错误帧。 # 注意事项 1. **内核时钟选择**:FDCAN_KER_CK 必须小于 100MHz,且最好为波特率的整数倍,以减少 TQ 误差。 2. **采样点范围**:经典 CAN 采样点应在 75%~80%,若低于 70%,在长总线(>10m)上易受信号反射影响。 3. **SJW 设置**:SJW 不宜过大(建议 2 TQ),否则在重同步时可能引入抖动。 4. **FD 与经典混合**:若网络中同时存在 FD 和经典节点,必须确保仲裁段波特率一致,且 FD 节点在发送时使用 BRS=0(不切换速率),否则经典节点会报错。 5. **CubeMX 自动计算陷阱**:CubeMX 的位时间计算器可能不适用于 480MHz 主频,务必手动验证 TQ 数和采样点。 # 结语 STM32H7 的 FDCAN 在 480MHz 下提供了强大性能,但时序配置需谨慎。通过理解位时间结构、手动计算预分频器,并利用调试工具验证,可轻松实现与经典 CAN 的兼容。希望本文能帮助你避开常见陷阱,构建稳定的混合网络。