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

NUCLEO-L432K2的CAN总线无法被应用识别问题排查

问题:NUCLEO-L432K2 CAN总线无法被DroneCAN/MissionPlanner识别,中断未触发

基于STM32CubeMX配置的NUCLEO-L432K2(STM32L4)开发板CAN总线无法被DroneCAN、MissionPlanner等应用识别,按照STM32L4手册UM1884编写了如下main()代码后,设备无法在CAN总线上被检测到,中断服务函数(ISR)也从未触发,需要补充哪些配置才能解决?

/* USER CODE BEGIN PTD */
#define NOJI_DEFAULT_ID 102

/* USER CODE END PTD */
/* USER CODE BEGIN 0 */
uint8_t currentID = NOJI_DEFAULT_ID;
CAN_TxHeaderTypeDef txHeader;
CAN_RxHeaderTypeDef rxHeader;
uint8_t txData[8];
uint8_t rxData[8];
uint32_t txMailbox;
int dataCheck = 0;

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *Nhcan)
{
    static uint32_t count = 0;
    count++;
    memset((void *) &rxHeader, 0, sizeof(CAN_RxHeaderTypeDef));
    memset((void *) rxData, 0, 8);
    HAL_CAN_GetRxMessage(Nhcan, CAN_RX_FIFO0, &rxHeader, rxData);
    if (rxHeader.DLC == 2)
    {
        dataCheck = 1;
    }
}
/* USER CODE END 0 */
  /* USER CODE BEGIN 2 */
  HAL_StatusTypeDef status = HAL_OK;
  CAN_FilterTypeDef canFilter;
  memset((void *) &canFilter, 0, sizeof(CAN_FilterTypeDef));
  canFilter.FilterActivation = CAN_FILTER_ENABLE;
  canFilter.FilterBank = 10;
  canFilter.FilterFIFOAssignment = CAN_RX_FIFO0;
  canFilter.FilterIdHigh = currentID << 5;
  canFilter.FilterMaskIdHigh = 0xFFE0;
  canFilter.FilterMode = CAN_FILTERMODE_IDMASK;
  canFilter.FilterScale = CAN_FILTERSCALE_32BIT;
  canFilter.SlaveStartFilterBank = 18;
  status = HAL_CAN_ConfigFilter(&hcan1, &canFilter);
  status |= HAL_CAN_Start(&hcan1);
  status |= HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
  memset((void *) &txHeader, 0, sizeof(CAN_TxHeaderTypeDef));
  txHeader.IDE = CAN_ID_STD;
  txHeader.RTR = CAN_RTR_DATA;
  txHeader.StdId = currentID;   // 0x66
  txHeader.DLC = 2;
  txHeader.TransmitGlobalTime = DISABLE;
  memset((void *) txData, 0, 8);
  txData[0] = 0xD7;
  txData[1] = 0xC3;
  status |= HAL_CAN_AddTxMessage(&hcan1, &txHeader, txData, &txMailbox);
  /* USER CODE END 2 */

解决方案

1. 匹配CAN总线波特率

  • DroneCAN默认波特率为1Mbps,需确保STM32CubeMX中CAN的波特率配置与总线完全一致。根据STM32L432的APB1时钟频率(最大80MHz),计算正确的分频系数、时间段1/2参数,避免波特率偏差导致通信失败。

2. 修正CAN滤波器配置

当前滤波器仅接收ID为102的报文,但DroneCAN设备会发送广播帧(如节点发现请求),需调整滤波器以捕获这些通用报文:

canFilter.FilterMode = CAN_FILTERMODE_IDMASK;
canFilter.FilterScale = CAN_FILTERSCALE_32BIT;
// 配置为接收所有标准ID报文
canFilter.FilterIdHigh = 0x0000;
canFilter.FilterIdLow = 0x0000;
canFilter.FilterMaskIdHigh = 0x0000;
canFilter.FilterMaskIdLow = 0x0000;

若需保留特定ID过滤,需额外添加DroneCAN相关ID的过滤规则(如节点发现ID 0x000)。

3. 适配DroneCAN协议规范

DroneCAN基于CAN但有专属协议,仅发送自定义2字节数据无法被识别,需实现基础协议逻辑:

  • 定期发送节点心跳报文:标准ID为0x001,数据包含节点状态、模式等字段,维持在线状态
  • 响应节点发现请求:监听ID为0x000的广播帧,返回节点信息报文

4. 硬件与引脚配置检查

  • NUCLEO-L432K2未集成CAN收发器,需外接TJA1050等收发器,正确连接:
    • PA11(CAN_RX)接收发器RX引脚,PA12(CAN_TX)接收发器TX引脚
    • 收发器的CAN_H、CAN_L接入总线,总线两端需各接120Ω终端电阻
  • 在CubeMX中确认CAN引脚已配置为复用功能AF9,且引脚电气属性设置正确(如推挽输出、按需配置上下拉)

5. 中断与回调函数验证

  • 在CubeMX中开启CAN_RX_FIFO0中断,并配置合理的中断优先级(避免被高优先级中断抢占)
  • 修正回调函数的句柄匹配逻辑,确保仅处理hcan1的中断:
    void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
    {
        if(hcan != &hcan1) return;
        static uint32_t count = 0;
        count++;
        memset((void *) &rxHeader, 0, sizeof(CAN_RxHeaderTypeDef));
        memset((void *) rxData, 0, 8);
        HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxHeader, rxData);
        if (rxHeader.DLC == 2)
        {
            dataCheck = 1;
        }
    }
    
  • 可在回调函数中添加调试动作(如LED翻转),直观确认中断是否触发

6. 优化发送逻辑

当前仅初始化时发送一次数据,DroneCAN需要持续通信保持在线,建议在主循环中定期发送心跳报文:

while (1)
{
    if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) > 0)
    {
        // 更新心跳报文数据后发送
        HAL_CAN_AddTxMessage(&hcan1, &txHeader, txData, &txMailbox);
    }
    HAL_Delay(1000); // 每秒发送一次心跳
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
}

内容的提问来源于stack exchange,提问作者Noji

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:48:40