You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32G474E-EVAL1开发板FDCAN收发异常问题求助

STM32G474 FDCAN发送FIFO阻塞、接收中断无触发问题排查

项目背景

基于STM32G474处理器与STM32G474E-EVAL1开发板开发,使用125Kbps Classic CAN模式,遇到两个FDCAN核心问题:

  • 问题1:调用HAL_FDCAN_AddMessageToTxFifoQ后,3级发送FIFO很快填满,但CAN总线无数据输出(已确认物理连接、终端电阻正常)
  • 问题2:配置过滤器接收所有消息至RX FIFO0并激活FDCAN_IT_RX_FIFO0_NEW_MESSAGE中断,但主机发送消息时FDCAN1_IT0_IRQHandler从未触发(已用CAN分析仪确认消息发出)

相关代码

FDCAN初始化代码(CubeMX生成+自定义过滤器)

/**
  * @brief FDCAN1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_FDCAN1_Init(void)
{

  /* USER CODE BEGIN FDCAN1_Init 0 */

  /* USER CODE END FDCAN1_Init 0 */

  /* USER CODE BEGIN FDCAN1_Init 1 */

  /* USER CODE END FDCAN1_Init 1 */
  hfdcan1.Instance = FDCAN1;
  hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
  hfdcan1.Init.AutoRetransmission = DISABLE;
  hfdcan1.Init.TransmitPause = DISABLE;
  hfdcan1.Init.ProtocolException = DISABLE;
  hfdcan1.Init.NominalPrescaler = 160;
  hfdcan1.Init.NominalSyncJumpWidth = 1;
  hfdcan1.Init.NominalTimeSeg1 = 2;
  hfdcan1.Init.NominalTimeSeg2 = 2;
  hfdcan1.Init.DataPrescaler = 1;
  hfdcan1.Init.DataSyncJumpWidth = 16;
  hfdcan1.Init.DataTimeSeg1 = 15;
  hfdcan1.Init.DataTimeSeg2 = 5;
  hfdcan1.Init.StdFiltersNbr = 1;
  hfdcan1.Init.ExtFiltersNbr = 0;
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN FDCAN1_Init 2 */

  // Set up filters
  FDCAN_FilterTypeDef sFilterConfig;
  sFilterConfig.IdType = FDCAN_STANDARD_ID; // vs. Extended ID
  sFilterConfig.FilterIndex = 0; // the number of the filter we are using
  sFilterConfig.FilterType = FDCAN_FILTER_MASK;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; // what to do filter match
  sFilterConfig.FilterID1 = 0; // filter
  sFilterConfig.FilterID2 = 0; // mask: 0=>accept all messages
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  {
    // Filter configuration error
    Error_Handler();
  }
  // There will be no remote messages
  if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, 
                                   FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE END FDCAN_Init 2 */

}

后续初始化函数

void canfestival_CAN_Initialize(CO_Data* can_handle)
{
  // Set up the transmit header
  TxHeader.IdType = FDCAN_STANDARD_ID;
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;
  TxHeader.DataLength = FDCAN_DLC_BYTES_8;
  TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Error State Indicator for Tx errors
  TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
  TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
  TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
  TxHeader.MessageMarker = 0;

  // Start CAN timer for use by CANfestival
  if (HAL_TIM_Base_Start_IT(&hCAN_FESTIVAL_TIMER) != HAL_OK)
  {
    Error_Handler();
  }

  // Start FDCAN module
  if (HAL_FDCAN_Start(&hFDCAN_MODULE) != HAL_OK)
  {
    Error_Handler();
  }

  // Set up to interrupt when a new message arrives in the RX Fifo 0
  if (HAL_FDCAN_ActivateNotification(&hFDCAN_MODULE, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
  {
    Error_Handler();
  }
}

发送任务代码

void canxmit_Task(void)
{
  Message message;
  osStatus_t status;

  while(true)
  {
    // Check to see if the Tx FIFO is full.
    if ((hFDCAN_MODULE.Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0)
    {
      break; // Tx FIFO is full.
    }

    // Check for any messages in the RTOS queue.
    status = osMessageQueueGet(CanXmitQueueHandle, &message, NULL, 0);
    if (status == osErrorTimeout)
    {
      break; // No new messages to send.
    }
    if (status != osOK)
    {
      Error_Handler();
    }

    // Copy message from data structure used by CANfestival into that required for HAL.
    TxHeader.Identifier = message.cob_id;
    TxHeader.TxFrameType = (message.rtr != 0) ? FDCAN_REMOTE_FRAME : FDCAN_DATA_FRAME;
    TxHeader.DataLength = message.len;
    for (uint32_t i = 0; i < message.len; i++)
    {
      TxData[i] = message.data[i];
    }

    // Add message to CAN Fifo queue for transmission.
    if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
    {
      Error_Handler();
    }
  }
}

问题分析与解决方案

问题1:发送FIFO阻塞无传输的修复

  1. 波特率配置不匹配
    当前标称位时间参数计算出的波特率为100Kbps(假设FDCAN时钟为80MHz),与目标125Kbps不符,导致总线通信失败、消息滞留在FIFO。
    修复: 调整参数至正确的125Kbps配置:

    hfdcan1.Init.NominalPrescaler = 128;
    hfdcan1.Init.NominalSyncJumpWidth = 1;
    hfdcan1.Init.NominalTimeSeg1 = 2;
    hfdcan1.Init.NominalTimeSeg2 = 2;
    

    计算:80MHz / (128 * (1+2+2)) = 125Kbps

  2. 关闭自动重传导致失败无重试
    配置AutoRetransmission = DISABLE,若首次发送因总线错误失败,FDCAN不会重试,消息会填满FIFO。
    修复: 开启自动重传:

    hfdcan1.Init.AutoRetransmission = ENABLE;
    
  3. 句柄不一致
    初始化使用hfdcan1,但启动和FIFO检查使用hFDCAN_MODULE,需统一句柄。
    修复: 将所有FDCAN操作改为使用同一个句柄(如全部用hfdcan1)。

问题2:接收中断无触发的修复

  1. NVIC中断未配置
    CubeMX若未开启FDCAN1_IT0中断或未设置优先级,中断无法触发。
    修复: 在CubeMX的NVIC设置中勾选FDCAN1_IT0并配置优先级,或手动添加:

    HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
    
  2. 全局过滤器拒绝消息
    当前全局过滤器配置为FDCAN_REJECT非匹配消息,若主机发送的消息未被过滤器匹配(如扩展ID)会被丢弃。
    修复: 修改全局过滤器,接受所有标准ID消息至RX FIFO0:

    HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_REJECT, 
                                 FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);
    
  3. 中断激活与启动顺序错误
    先启动FDCAN再激活中断可能导致中断未正确注册。
    修复: 调整顺序为先激活中断再启动FDCAN:

    // 先激活中断
    if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
    {
      Error_Handler();
    }
    // 再启动FDCAN
    if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
    {
      Error_Handler();
    }
    

额外检查点

  • 确认FDCAN引脚配置为正确复用功能:STM32G474E-EVAL1的FDCAN1通常为PA11(RX)、PA12(TX),需配置为AF9
  • 读取hfdcan1.Instance->ESR寄存器检查错误状态,若总线关闭需调用HAL_FDCAN_ResetError(&hfdcan1)恢复

内容的提问来源于stack exchange,提问作者Rick N.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:38:12