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
相关产品推荐
相关产品推荐

