From d626e4e6561d82bef94a802320fce9233a72b867 Mon Sep 17 00:00:00 2001 From: Robofish <1683502971@qq.com> Date: Sat, 6 Sep 2025 12:42:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86can?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code_page/bsp_interface.py | 99 +++++++++++++++++--- assets/User_code/bsp/can.c | 145 +++++++++++++++++++++++------- assets/User_code/bsp/can.h | 4 +- assets/User_code/bsp/describe.csv | 16 ++-- assets/User_code/bsp/pwm.c | 2 +- assets/User_code/device/vofa.c | 77 ++++++++++++++++ assets/User_code/device/vofa.h | 39 ++++++++ 7 files changed, 326 insertions(+), 56 deletions(-) create mode 100644 assets/User_code/device/vofa.c create mode 100644 assets/User_code/device/vofa.h diff --git a/app/code_page/bsp_interface.py b/app/code_page/bsp_interface.py index 6b84b8b..82c5b19 100644 --- a/app/code_page/bsp_interface.py +++ b/app/code_page/bsp_interface.py @@ -433,6 +433,27 @@ class bsp_can(BspPeripheralBase): # 生成CAN初始化代码 init_lines = [] + # 初始化发送信号量 + init_lines.append(" // 创建发送信号量,每个CAN通道有3个发送邮箱") + init_lines.append(" for (int i = 0; i < BSP_CAN_NUM; i++) {") + init_lines.append(" tx_semaphore[i] = osSemaphoreNew(CAN_TX_MAILBOX_NUM, CAN_TX_MAILBOX_NUM, NULL);") + init_lines.append(" if (tx_semaphore[i] == NULL) {") + init_lines.append(" // 清理已创建的信号量") + init_lines.append(" for (int j = 0; j < i; j++) {") + init_lines.append(" if (tx_semaphore[j] != NULL) {") + init_lines.append(" osSemaphoreDelete(tx_semaphore[j]);") + init_lines.append(" tx_semaphore[j] = NULL;") + init_lines.append(" }") + init_lines.append(" }") + init_lines.append(" if (queue_mutex != NULL) {") + init_lines.append(" osMutexDelete(queue_mutex);") + init_lines.append(" queue_mutex = NULL;") + init_lines.append(" }") + init_lines.append(" return BSP_ERR;") + init_lines.append(" }") + init_lines.append(" }") + init_lines.append("") + # 先设置初始化标志 init_lines.append(" // 先设置初始化标志,以便后续回调注册能通过检查") init_lines.append(" inited = true;") @@ -482,10 +503,19 @@ class bsp_can(BspPeripheralBase): f" HAL_CAN_ConfigFilter(&hcan{can_num}, &can{can_num}_filter);", f" HAL_CAN_Start(&hcan{can_num});", "", - f" // 注册{instance}回调函数", + f" // 注册{instance}发送完成回调(用于释放信号量)", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_ABORT_CB, BSP_CAN_TxAbortCallback);", + "", + f" // 注册{instance}接收回调函数", f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_RX_FIFO0_MSG_PENDING_CB, BSP_CAN_RxFifo0Callback);", "", - f" HAL_CAN_ActivateNotification(&hcan{can_num}, CAN_IT_RX_FIFO0_MSG_PENDING);", + f" HAL_CAN_ActivateNotification(&hcan{can_num}, CAN_IT_RX_FIFO0_MSG_PENDING | ", + f" CAN_IT_TX_MAILBOX_EMPTY); // 激活发送邮箱空中断", "" ]) @@ -513,10 +543,19 @@ class bsp_can(BspPeripheralBase): f" HAL_CAN_ConfigFilter(&hcan1, &can1_filter);", f" HAL_CAN_Start(&hcan1);", "", - f" // 注册CAN1回调函数", + f" // 注册CAN1发送完成回调(用于释放信号量)", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_ABORT_CB, BSP_CAN_TxAbortCallback);", + "", + f" // 注册CAN1接收回调函数", f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_RX_FIFO0_MSG_PENDING_CB, BSP_CAN_RxFifo0Callback);", "", - f" HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);", + f" HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | ", + f" CAN_IT_TX_MAILBOX_EMPTY); // 激活发送邮箱空中断", "" ]) @@ -529,9 +568,18 @@ class bsp_can(BspPeripheralBase): f" HAL_CAN_ConfigFilter(&hcan2, &can1_filter); // 通过 CAN1 配置", f" HAL_CAN_Start(&hcan2);", "", - f" // 注册CAN2回调函数", + f" // 注册CAN2发送完成回调(用于释放信号量)", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_ABORT_CB, BSP_CAN_TxAbortCallback);", + "", + f" // 注册CAN2接收回调函数", f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_RX_FIFO1_MSG_PENDING_CB, BSP_CAN_RxFifo1Callback);", - f" HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO1_MSG_PENDING);", + f" HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO1_MSG_PENDING | ", + f" CAN_IT_TX_MAILBOX_EMPTY); // 激活发送邮箱空中断", "" ]) @@ -560,10 +608,19 @@ class bsp_can(BspPeripheralBase): f" HAL_CAN_ConfigFilter(&hcan1, &can1_filter);", f" HAL_CAN_Start(&hcan1);", "", - f" // 注册CAN1回调函数", + f" // 注册CAN1发送完成回调(用于释放信号量)", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_ABORT_CB, BSP_CAN_TxAbortCallback);", + "", + f" // 注册CAN1接收回调函数", f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_RX_FIFO0_MSG_PENDING_CB, BSP_CAN_RxFifo0Callback);", "", - f" HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);", + f" HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | ", + f" CAN_IT_TX_MAILBOX_EMPTY); // 激活发送邮箱空中断", "" ]) @@ -577,9 +634,18 @@ class bsp_can(BspPeripheralBase): f" HAL_CAN_ConfigFilter(&hcan2, &can1_filter); // 通过 CAN1 配置", f" HAL_CAN_Start(&hcan2);", "", - f" // 注册CAN2回调函数", + f" // 注册CAN2发送完成回调(用于释放信号量)", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_ABORT_CB, BSP_CAN_TxAbortCallback);", + "", + f" // 注册CAN2接收回调函数", f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_RX_FIFO0_MSG_PENDING_CB, BSP_CAN_RxFifo0Callback);", - f" HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);", + f" HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING | ", + f" CAN_IT_TX_MAILBOX_EMPTY); // 激活发送邮箱空中断", "" ]) @@ -595,9 +661,18 @@ class bsp_can(BspPeripheralBase): f" HAL_CAN_ConfigFilter(&hcan1, &can1_filter); // 通过 CAN1 配置", f" HAL_CAN_Start(&hcan{can_num});", "", - f" // 注册{instance}回调函数", + f" // 注册{instance}发送完成回调(用于释放信号量)", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX0_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX1_ABORT_CB, BSP_CAN_TxAbortCallback);", + f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_TX_MAILBOX2_ABORT_CB, BSP_CAN_TxAbortCallback);", + "", + f" // 注册{instance}接收回调函数", f" BSP_CAN_RegisterCallback({self.enum_prefix}_{name}, HAL_CAN_RX_FIFO1_MSG_PENDING_CB, BSP_CAN_RxFifo1Callback);", - f" HAL_CAN_ActivateNotification(&hcan{can_num}, CAN_IT_RX_FIFO1_MSG_PENDING);", + f" HAL_CAN_ActivateNotification(&hcan{can_num}, CAN_IT_RX_FIFO1_MSG_PENDING | ", + f" CAN_IT_TX_MAILBOX_EMPTY); // 激活发送邮箱空中断", "" ]) filter_bank += 1 # 为下一个CAN分配不同的过滤器组 diff --git a/assets/User_code/bsp/can.c b/assets/User_code/bsp/can.c index 91cf3a3..5083893 100644 --- a/assets/User_code/bsp/can.c +++ b/assets/User_code/bsp/can.c @@ -7,6 +7,8 @@ /* Private define ----------------------------------------------------------- */ #define CAN_QUEUE_MUTEX_TIMEOUT 100 /* 队列互斥锁超时时间(ms) */ +#define CAN_TX_SEMAPHORE_TIMEOUT 1000 /* 发送信号量超时时间(ms) */ +#define CAN_TX_MAILBOX_NUM 3 /* CAN发送邮箱数量 */ /* Private macro ------------------------------------------------------------ */ /* Private typedef ---------------------------------------------------------- */ @@ -21,6 +23,7 @@ typedef struct BSP_CAN_QueueNode { /* Private variables -------------------------------------------------------- */ static BSP_CAN_QueueNode_t *queue_list = NULL; static osMutexId_t queue_mutex = NULL; +static osSemaphoreId_t tx_semaphore[BSP_CAN_NUM] = {NULL}; /* 发送信号量,用于控制发送邮箱访问 */ static void (*CAN_Callback[BSP_CAN_NUM][BSP_CAN_CB_NUM])(void); static bool inited = false; static BSP_CAN_IdParser_t id_parser = NULL; /* ID解析器 */ @@ -32,6 +35,8 @@ static int8_t BSP_CAN_CreateIdQueue(BSP_CAN_t can, uint32_t can_id, uint8_t queu static int8_t BSP_CAN_DeleteIdQueue(BSP_CAN_t can, uint32_t can_id); static void BSP_CAN_RxFifo0Callback(void); static void BSP_CAN_RxFifo1Callback(void); +static void BSP_CAN_TxCompleteCallback(CAN_HandleTypeDef *hcan); +static void BSP_CAN_TxAbortCallback(CAN_HandleTypeDef *hcan); static BSP_CAN_FrameType_t BSP_CAN_GetFrameType(CAN_RxHeaderTypeDef *header); static uint32_t BSP_CAN_DefaultIdParser(uint32_t original_id, BSP_CAN_FrameType_t frame_type); @@ -208,53 +213,79 @@ static void BSP_CAN_RxFifo1Callback(void) { } } +/** + * @brief 发送完成回调统一处理函数 + */ +static void BSP_CAN_TxCompleteCallback(CAN_HandleTypeDef *hcan) { + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + // 释放发送信号量 + if (tx_semaphore[bsp_can] != NULL) { + osSemaphoreRelease(tx_semaphore[bsp_can]); + } + } +} + +/** + * @brief 发送中止回调统一处理函数 + */ +static void BSP_CAN_TxAbortCallback(CAN_HandleTypeDef *hcan) { + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + // 释放发送信号量(发送中止也要释放) + if (tx_semaphore[bsp_can] != NULL) { + osSemaphoreRelease(tx_semaphore[bsp_can]); + } + } +} + /* HAL Callback Functions --------------------------------------------------- */ void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB](); - } + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB]) + CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_CPLT_CB](); + } } void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB](); - } + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB]) + CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_CPLT_CB](); + } } void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB](); - } + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB]) + CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_CPLT_CB](); + } } void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB](); - } + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB]) + CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX0_ABORT_CB](); + } } void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB](); - } + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB]) + CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX1_ABORT_CB](); + } } void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { - BSP_CAN_t bsp_can = CAN_Get(hcan); - if (bsp_can != BSP_CAN_ERR) { - if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB]) - CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB](); - } + BSP_CAN_t bsp_can = CAN_Get(hcan); + if (bsp_can != BSP_CAN_ERR) { + if (CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB]) + CAN_Callback[bsp_can][HAL_CAN_TX_MAILBOX2_ABORT_CB](); + } } void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { @@ -332,6 +363,25 @@ int8_t BSP_CAN_Init(void) { return BSP_ERR; } + // 创建发送信号量,每个CAN通道有3个发送邮箱 + for (int i = 0; i < BSP_CAN_NUM; i++) { + tx_semaphore[i] = osSemaphoreNew(CAN_TX_MAILBOX_NUM, CAN_TX_MAILBOX_NUM, NULL); + if (tx_semaphore[i] == NULL) { + // 清理已创建的信号量 + for (int j = 0; j < i; j++) { + if (tx_semaphore[j] != NULL) { + osSemaphoreDelete(tx_semaphore[j]); + tx_semaphore[j] = NULL; + } + } + if (queue_mutex != NULL) { + osMutexDelete(queue_mutex); + queue_mutex = NULL; + } + return BSP_ERR; + } + } + /* AUTO GENERATED CAN_INIT */ inited = true; @@ -356,6 +406,14 @@ int8_t BSP_CAN_DeInit(void) { osMutexRelease(queue_mutex); } + // 删除发送信号量 + for (int i = 0; i < BSP_CAN_NUM; i++) { + if (tx_semaphore[i] != NULL) { + osSemaphoreDelete(tx_semaphore[i]); + tx_semaphore[i] = NULL; + } + } + // 删除互斥锁 if (queue_mutex != NULL) { osMutexDelete(queue_mutex); @@ -418,8 +476,20 @@ int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format, return BSP_ERR; } + // 获取发送信号量,确保有可用的发送邮箱 + if (tx_semaphore[can] == NULL) { + return BSP_ERR; + } + + osStatus_t sem_status = osSemaphoreAcquire(tx_semaphore[can], CAN_TX_SEMAPHORE_TIMEOUT); + if (sem_status != osOK) { + return BSP_ERR_TIMEOUT; // 获取信号量超时,表示发送邮箱已满 + } + CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle(can); if (hcan == NULL) { + // 如果获取句柄失败,需要释放信号量 + osSemaphoreRelease(tx_semaphore[can]); return BSP_ERR_NULL; } @@ -448,6 +518,8 @@ int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format, header.RTR = CAN_RTR_REMOTE; break; default: + // 如果格式错误,需要释放信号量 + osSemaphoreRelease(tx_semaphore[can]); return BSP_ERR; } @@ -455,7 +527,15 @@ int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format, header.TransmitGlobalTime = DISABLE; HAL_StatusTypeDef result = HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox); - return (result == HAL_OK) ? BSP_OK : BSP_ERR; + + if (result != HAL_OK) { + // 如果发送失败,需要释放信号量 + osSemaphoreRelease(tx_semaphore[can]); + return BSP_ERR; + } + + // 发送成功,信号量将在发送完成回调中释放 + return BSP_OK; } int8_t BSP_CAN_TransmitStdDataFrame(BSP_CAN_t can, BSP_CAN_StdDataFrame_t *frame) { @@ -574,6 +654,3 @@ uint32_t BSP_CAN_ParseId(uint32_t original_id, BSP_CAN_FrameType_t frame_type) { } return BSP_CAN_DefaultIdParser(original_id, frame_type); } - -/* USER CAN FUNCTIONS BEGIN */ -/* USER CAN FUNCTIONS END */ \ No newline at end of file diff --git a/assets/User_code/bsp/can.h b/assets/User_code/bsp/can.h index d348131..c1bc147 100644 --- a/assets/User_code/bsp/can.h +++ b/assets/User_code/bsp/can.h @@ -17,6 +17,7 @@ extern "C" { #define BSP_CAN_DEFAULT_QUEUE_SIZE 10 #define BSP_CAN_TIMEOUT_IMMEDIATE 0 #define BSP_CAN_TIMEOUT_FOREVER osWaitForever +#define CAN_TX_SEMAPHORE_TIMEOUT 1000 /* 发送信号量超时时间(ms) */ /* Exported macro ----------------------------------------------------------- */ /* Exported types ----------------------------------------------------------- */ @@ -224,9 +225,6 @@ int8_t BSP_CAN_UnregisterIdParser(void); */ uint32_t BSP_CAN_ParseId(uint32_t original_id, BSP_CAN_FrameType_t frame_type); -/* USER CAN FUNCTIONS BEGIN */ -/* USER CAN FUNCTIONS END */ - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/assets/User_code/bsp/describe.csv b/assets/User_code/bsp/describe.csv index e06407c..fd64d14 100644 --- a/assets/User_code/bsp/describe.csv +++ b/assets/User_code/bsp/describe.csv @@ -1,7 +1,11 @@ -uart,要求开启dma和中断 -can,2222 -gpio,要求设置label开启中断 -spi,要求开启spi中断 +uart,请开启uart的dma和中断 +can,请开启can中断,使用函数前请确保can已经初始化。 +gpio,会自动读取cubemx中配置为gpio的引脚,并自动区分输入输出和中断。 +spi,请开启spi的dma和中断 i2c,要求开始spi中断 -mm,这是套了一层的内存 -time,需要使用开启freerots \ No newline at end of file +mm,这是套了一层的动态内存分配 +time,获取时间戳函数,需要开启freerots +dwt,需要开启dwt,获取时间 +i2c,请开启i2c的dma和中断 +pwm,用于选择那些勇于输出pwm + diff --git a/assets/User_code/bsp/pwm.c b/assets/User_code/bsp/pwm.c index 6838d74..34e9893 100644 --- a/assets/User_code/bsp/pwm.c +++ b/assets/User_code/bsp/pwm.c @@ -35,7 +35,6 @@ int8_t BSP_PWM_SetComp(BSP_PWM_Channel_t ch, float duty_cycle) { if (duty_cycle < 0.0f) { duty_cycle = 0.0f; } - // 获取ARR值(周期值) uint32_t arr = __HAL_TIM_GET_AUTORELOAD(PWM_Map[ch].tim); @@ -43,6 +42,7 @@ int8_t BSP_PWM_SetComp(BSP_PWM_Channel_t ch, float duty_cycle) { uint32_t ccr = (uint32_t)(duty_cycle * (arr + 1)); __HAL_TIM_SET_COMPARE(PWM_Map[ch].tim, PWM_Map[ch].channel, ccr); + return BSP_OK; } diff --git a/assets/User_code/device/vofa.c b/assets/User_code/device/vofa.c new file mode 100644 index 0000000..662a406 --- /dev/null +++ b/assets/User_code/device/vofa.c @@ -0,0 +1,77 @@ +/* Includes ----------------------------------------------------------------- */ +#include +#include +#include "vofa.h" +#include "bsp/uart.h" +/* Private define ----------------------------------------------------------- */ + +//#define PROTOCOL_RAWDATA +#define PROTOCOL_FIREWATER +//#define PROTOCOL_JUSTFLOAT + +#define MAX_CHANNEL 64u // ʵͨ + +#define JUSTFLOAT_TAIL 0x7F800000 +/* Private macro ------------------------------------------------------------ */ +/* Private typedef ---------------------------------------------------------- */ +/* Private variables -------------------------------------------------------- */ +static uint8_t vofa_tx_buf[sizeof(float) * MAX_CHANNEL + sizeof(uint32_t)]; + +/* Private function -------------------------------------------------------- */ + +/************************ RawData *************************/ +void VOFA_RawData_Send(const char* data, bool dma) { + BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t*)data, strlen(data), dma); +} + +/************************ FireWater *************************/ +void VOFA_FireWater_Send(float *channels, uint8_t channel_count, bool dma) +{ + if (channel_count == 0 || channel_count > MAX_CHANNEL) + return; + + char *buf = (char *)vofa_tx_buf; + size_t len = 0; + + for (uint8_t i = 0; i < channel_count; ++i) { + len += snprintf(buf + len, + sizeof(vofa_tx_buf) - len, + "%s%.2f", + (i ? "," : ""), + channels[i]); + } + snprintf(buf + len, sizeof(vofa_tx_buf) - len, "\n"); + + BSP_UART_Transmit(BSP_UART_VOFA, vofa_tx_buf, strlen(buf), dma); +} + +/************************ JustFloat *************************/ +void VOFA_JustFloat_Send(float *channels, uint8_t channel_count, bool dma) +{ + if (channel_count == 0 || channel_count > MAX_CHANNEL) + return; + memcpy(vofa_tx_buf, channels, channel_count * sizeof(float)); + + uint32_t tail = JUSTFLOAT_TAIL; // 0x7F800000 + memcpy(vofa_tx_buf + channel_count * sizeof(float), &tail, sizeof(tail)); + + BSP_UART_Transmit(BSP_UART_VOFA, vofa_tx_buf, channel_count * sizeof(float) + sizeof(tail), dma); +} + +/* Exported functions ------------------------------------------------------- */ +init8_t VOFA_Send(float* channels, uint8_t channel_count, bool dma) { +#ifdef PROTOCOL_RAWDATA + sprintf(vofa_tx_buf, "Channel1:%.2f,Channel2:%.2f\n", channels[0],channels[1]); + VOFA_RawData_Send(vofa_tx_buf, dma); +#elif defined(PROTOCOL_FIREWATER) + VOFA_FireWater_Send(channels, channel_count, dma); +#elif defined(PROTOCOL_JUSTFLOAT) + VOFA_JustFloat_Send(channels, channel_count, dma); +#else + // ĬʹRawDataЭ + char data[256]; + sprintf(data, "Channel1: %.2f, Channel2: %.2f\n", channels[0], channels[1]); + VOFA_RawData_Send(data, dma); +#endif + return DEVICE_OK; +} diff --git a/assets/User_code/device/vofa.h b/assets/User_code/device/vofa.h new file mode 100644 index 0000000..7eda280 --- /dev/null +++ b/assets/User_code/device/vofa.h @@ -0,0 +1,39 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ----------------------------------------------------------------- */ +#include "bsp/uart.h" +#include ”device/device.h“ +/* Exported constants ------------------------------------------------------- */ +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ +/* Exported functions prototypes -------------------------------------------- */ + +typedef enum { + VOFA_PROTOCOL_RAWDATA, + VOFA_PROTOCOL_FIREWATER, + VOFA_PROTOCOL_JUSTFLOAT, +} VOFA_Protocol_t; + +/** + * @brief 初始化VOFA设备 + * @param protocol 设置通信协议 + * @return + */ +int8_t VOFA_init(VOFA_Protocol_t protocol); + +/** + * @brief 发送数据到VOFA + * @param channels 要发送的通道数据 + * @param channel_count 通道数量 + * @param dma 是否使用DMA发送 + * @return + */ +int8_t VOFA_Send(float* channels, uint8_t channel_count, bool dma); + +#ifdef __cplusplus +} +#endif \ No newline at end of file