文章目錄
- 前言
- 一、bsp
- bsp_can.h
- bsp_can.c
- 二、如何使用
- 總結
前言
stm32 cubemx can通訊(1)回環模式
stm32 cubemx can通訊(2)過濾器設置說明代碼分析
根據前兩篇文章已經能夠實現can標準幀的收發,但是調用的函數沒有標準化和可擴展性。
所以本文講解bsp,在bsp中已經有了發送函數和接受回調函數的任務映射處理回調函數。
暫時(2023.8.10)還未加入過濾器配置,所以過濾器還是需要在can_init中進行配置。
文件
一、bsp
bsp_can.h
#ifndef __BSP_CAN_H
#define __BSP_CAN_H
#include "main.h"#include "can.h"uint8_t CANSend(CAN_HandleTypeDef *hcan,uint32_t Source_ID,uint32_t IDE,uint32_t RTR,uint8_t* Datum,uint8_t DataLength);typedef struct {uint32_t id;uint32_t idType; // CAN_ID_STD or CAN_ID_EXTvoid (*callback)(uint8_t* data);
} CAN_CallbackMapType;#endif
bsp_can.c
#include "bsp_can.h"/*** 發送CAN數據* @param hcan: 使用的CAN句柄* @param Source_ID: 消息ID* @param IDE: 標識符類型 (CAN_ID_STD 或 CAN_ID_EXT)* @param RTR: 消息類型 (CAN_RTR_DATA 或 CAN_RTR_REMOTE)* @param Datum: 要發送的數據* @param DataLength: 數據長度* @return: HAL的狀態 ( 1 成功 0 失敗 )*/
#define CAN_MAX_DATA_LENGTH 8
uint8_t CANSend(CAN_HandleTypeDef *hcan,uint32_t Source_ID,uint32_t IDE,uint32_t RTR,uint8_t* Datum,uint8_t DataLength)
{// 參數驗證if (!hcan || !Datum || (IDE != CAN_ID_STD && IDE != CAN_ID_EXT) || DataLength > CAN_MAX_DATA_LENGTH) {return 0;}CAN_TxHeaderTypeDef TXHeader; uint32_t pTxMailbox = 0;if (IDE == CAN_ID_STD) {TXHeader.StdId = Source_ID;} else {TXHeader.ExtId = Source_ID; }TXHeader.IDE = IDE;TXHeader.DLC = DataLength;TXHeader.RTR = RTR;TXHeader.TransmitGlobalTime = DISABLE;HAL_StatusTypeDef status = HAL_CAN_AddTxMessage(hcan, &TXHeader, Datum, &pTxMailbox);if (status == HAL_OK) {return 1; // 返回1表示成功} else {return 0; // 返回0表示失敗}
}/* USER CODE BEGIN mapping_function */
int cc =0;
// 示例的回調函數
void handle_ID_0x01(uint8_t *data) {// 對于ID 0x01的處理代碼cc=1;
}void handle_ID_0x02(uint8_t *data) {// 對于ID 0x02的處理代碼cc=2;
}
void handle_ID_0x12345678(uint8_t *data) {// 對于ID 0x02的處理代碼cc=4;
}
// 初始化映射表
CAN_CallbackMapType callbackMap[] = {{0x01, CAN_ID_STD, handle_ID_0x01},{0x02, CAN_ID_STD, handle_ID_0x02},// 添加一個擴展ID的例子{0x12345678, CAN_ID_EXT, handle_ID_0x12345678}
};/* USER CODE mapping_function */
const uint8_t mapSize = sizeof(callbackMap) / sizeof(CAN_CallbackMapType);void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{if(hcan->Instance == CAN1) {// 獲取數據CAN_RxHeaderTypeDef RXHeader;uint8_t RXmessage[8]; // 確保這里的數組大小正確if(HAL_CAN_GetRxMessage(hcan, CAN_FILTER_FIFO0, &RXHeader, RXmessage) == HAL_OK) {for(uint8_t i = 0; i < mapSize; i++) {if(RXHeader.IDE == callbackMap[i].idType && (RXHeader.IDE == CAN_ID_STD && RXHeader.StdId == callbackMap[i].id || RXHeader.IDE == CAN_ID_EXT && RXHeader.ExtId == callbackMap[i].id) && callbackMap[i].callback) {callbackMap[i].callback(RXmessage);break;}}}}
}
二、如何使用
發送函數可以直接調用。
uint8_t TXmessage[8] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
CANSend(&hcan,0x12,CAN_ID_STD,CAN_RTR_DATA,TXmessage,8);
接收函數的回調函數不需要進行修改,當有任務需要處理的時候先寫任務處理的回調函數也就是示例代碼中的void handle_ID_0x01(uint8_t *data)
之類的。
然后再進行初始化映射CAN_CallbackMapType callbackMap[]
所以只需要在/* USER CODE BEGIN mapping_function */
之間修改函數即可。其他的不需要更改。