From 92a75811ae5b02395f533dcb7edc78d780bcf533 Mon Sep 17 00:00:00 2001
From: Robofish <1683502971@qq.com>
Date: Mon, 6 Oct 2025 21:58:56 +0800
Subject: [PATCH 1/4] =?UTF-8?q?=E6=AF=94=E8=BE=83=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
User/module/balance_chassis.c | 10 +++++-----
User/task/rc.c | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/User/module/balance_chassis.c b/User/module/balance_chassis.c
index e38bad6..ae7ff50 100644
--- a/User/module/balance_chassis.c
+++ b/User/module/balance_chassis.c
@@ -457,13 +457,13 @@ int8_t Chassis_LQRControl(Chassis_t *c, const Chassis_CMD_t *c_cmd) {
// }
// c->yaw_control.yaw_force = PID_Calc(&c->pid.yaw, c->yaw_control.target_yaw, c->feedback.imu.euler.yaw, c->feedback.imu.gyro.z, c->dt);
- c->yaw_control.current_yaw = c->feedback.yaw.rotor_abs_angle;
- c->yaw_control.target_yaw = c->param->mech_zero_yaw;
- c->yaw_control.yaw_force = PID_Calc(&c->pid.yaw, c->yaw_control.target_yaw, c->feedback.yaw.rotor_abs_angle, 0.0f, c->dt);
+ // c->yaw_control.current_yaw = c->feedback.yaw.rotor_abs_angle;
+ // c->yaw_control.target_yaw = c->param->mech_zero_yaw;
+ // c->yaw_control.yaw_force = PID_Calc(&c->pid.yaw, c->yaw_control.target_yaw, c->feedback.yaw.rotor_abs_angle, 0.0f, c->dt);
/* 轮毂力矩输出(参考C++版本的减速比) */
- c->output.wheel[0] = Tw[0] / 4.5f + c->yaw_control.yaw_force;
- c->output.wheel[1] = Tw[1] / 4.5f - c->yaw_control.yaw_force;
+ c->output.wheel[0] = Tw[0] / 4.5f;
+ c->output.wheel[1] = Tw[1] / 4.5f;
/* 腿长控制和VMC逆解算(使用PID控制) */
float virtual_force[2];
float target_L0[2];
diff --git a/User/task/rc.c b/User/task/rc.c
index 53430a6..36843e8 100644
--- a/User/task/rc.c
+++ b/User/task/rc.c
@@ -21,7 +21,7 @@
DR16_t dr16;
RC_CAN_t rc_can;
Chassis_CMD_t cmd_to_chassis;
-#define USE_RC_CAN
+#define USE_DR16
/* USER STRUCT END */
/* Private function --------------------------------------------------------- */
From 96b6389a46c8f3fee2d9fbf446e06a0809bb1fdc Mon Sep 17 00:00:00 2001
From: Robofish <1683502971@qq.com>
Date: Tue, 7 Oct 2025 02:41:01 +0800
Subject: [PATCH 2/4] =?UTF-8?q?=E5=B0=8F=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Core/Src/stm32f4xx_it.c | 1026 +++++++++++++++++++--------------------
User/bsp/can.c | 291 ++++++-----
User/bsp/can.h | 46 +-
User/device/dm_imu.c | 4 +-
User/device/dr16.c | 6 +-
User/device/dr16.h | 49 +-
User/device/motor_lk.c | 3 -
User/device/motor_lz.c | 11 -
User/device/motor_lz.h | 6 -
User/device/motor_rm.c | 22 +-
User/task/rc.c | 6 +-
11 files changed, 742 insertions(+), 728 deletions(-)
diff --git a/Core/Src/stm32f4xx_it.c b/Core/Src/stm32f4xx_it.c
index 97aabfe..abebd0f 100644
--- a/Core/Src/stm32f4xx_it.c
+++ b/Core/Src/stm32f4xx_it.c
@@ -1,513 +1,513 @@
-/* USER CODE BEGIN Header */
-/**
- ******************************************************************************
- * @file stm32f4xx_it.c
- * @brief Interrupt Service Routines.
- ******************************************************************************
- * @attention
- *
- *
© Copyright (c) 2025 STMicroelectronics.
- * All rights reserved.
- *
- * This software component is licensed by ST under Ultimate Liberty license
- * SLA0044, the "License"; You may not use this file except in compliance with
- * the License. You may obtain a copy of the License at:
- * www.st.com/SLA0044
- *
- ******************************************************************************
- */
-/* USER CODE END Header */
-
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-#include "stm32f4xx_it.h"
-#include "FreeRTOS.h"
-#include "task.h"
-/* Private includes ----------------------------------------------------------*/
-/* USER CODE BEGIN Includes */
-#include "bsp/uart.h"
-/* USER CODE END Includes */
-
-/* Private typedef -----------------------------------------------------------*/
-/* USER CODE BEGIN TD */
-
-/* USER CODE END TD */
-
-/* Private define ------------------------------------------------------------*/
-/* USER CODE BEGIN PD */
-
-/* USER CODE END PD */
-
-/* Private macro -------------------------------------------------------------*/
-/* USER CODE BEGIN PM */
-
-/* USER CODE END PM */
-
-/* Private variables ---------------------------------------------------------*/
-/* USER CODE BEGIN PV */
-
-/* USER CODE END PV */
-
-/* Private function prototypes -----------------------------------------------*/
-/* USER CODE BEGIN PFP */
-
-/* USER CODE END PFP */
-
-/* Private user code ---------------------------------------------------------*/
-/* USER CODE BEGIN 0 */
-
-/* USER CODE END 0 */
-
-/* External variables --------------------------------------------------------*/
-extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
-extern CAN_HandleTypeDef hcan1;
-extern CAN_HandleTypeDef hcan2;
-extern DMA_HandleTypeDef hdma_i2c2_tx;
-extern DMA_HandleTypeDef hdma_i2c3_rx;
-extern DMA_HandleTypeDef hdma_spi1_rx;
-extern DMA_HandleTypeDef hdma_spi1_tx;
-extern TIM_HandleTypeDef htim1;
-extern TIM_HandleTypeDef htim7;
-extern DMA_HandleTypeDef hdma_usart1_tx;
-extern DMA_HandleTypeDef hdma_usart1_rx;
-extern DMA_HandleTypeDef hdma_usart3_rx;
-extern DMA_HandleTypeDef hdma_usart6_rx;
-extern DMA_HandleTypeDef hdma_usart6_tx;
-extern UART_HandleTypeDef huart1;
-extern UART_HandleTypeDef huart6;
-/* USER CODE BEGIN EV */
-
-/* USER CODE END EV */
-
-/******************************************************************************/
-/* Cortex-M4 Processor Interruption and Exception Handlers */
-/******************************************************************************/
-/**
- * @brief This function handles Non maskable interrupt.
- */
-void NMI_Handler(void)
-{
- /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
-
- /* USER CODE END NonMaskableInt_IRQn 0 */
- /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
- while (1)
- {
- }
- /* USER CODE END NonMaskableInt_IRQn 1 */
-}
-
-/**
- * @brief This function handles Hard fault interrupt.
- */
-void HardFault_Handler(void)
-{
- /* USER CODE BEGIN HardFault_IRQn 0 */
-
- /* USER CODE END HardFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_HardFault_IRQn 0 */
- /* USER CODE END W1_HardFault_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles Memory management fault.
- */
-void MemManage_Handler(void)
-{
- /* USER CODE BEGIN MemoryManagement_IRQn 0 */
-
- /* USER CODE END MemoryManagement_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
- /* USER CODE END W1_MemoryManagement_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles Pre-fetch fault, memory access fault.
- */
-void BusFault_Handler(void)
-{
- /* USER CODE BEGIN BusFault_IRQn 0 */
-
- /* USER CODE END BusFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_BusFault_IRQn 0 */
- /* USER CODE END W1_BusFault_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles Undefined instruction or illegal state.
- */
-void UsageFault_Handler(void)
-{
- /* USER CODE BEGIN UsageFault_IRQn 0 */
-
- /* USER CODE END UsageFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
- /* USER CODE END W1_UsageFault_IRQn 0 */
- }
-}
-
-/**
- * @brief This function handles Debug monitor.
- */
-void DebugMon_Handler(void)
-{
- /* USER CODE BEGIN DebugMonitor_IRQn 0 */
-
- /* USER CODE END DebugMonitor_IRQn 0 */
- /* USER CODE BEGIN DebugMonitor_IRQn 1 */
-
- /* USER CODE END DebugMonitor_IRQn 1 */
-}
-
-/**
- * @brief This function handles System tick timer.
- */
-void SysTick_Handler(void)
-{
- /* USER CODE BEGIN SysTick_IRQn 0 */
-
- /* USER CODE END SysTick_IRQn 0 */
- HAL_IncTick();
-#if (INCLUDE_xTaskGetSchedulerState == 1 )
- if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
- {
-#endif /* INCLUDE_xTaskGetSchedulerState */
- xPortSysTickHandler();
-#if (INCLUDE_xTaskGetSchedulerState == 1 )
- }
-#endif /* INCLUDE_xTaskGetSchedulerState */
- /* USER CODE BEGIN SysTick_IRQn 1 */
-
- /* USER CODE END SysTick_IRQn 1 */
-}
-
-/******************************************************************************/
-/* STM32F4xx Peripheral Interrupt Handlers */
-/* Add here the Interrupt Handlers for the used peripherals. */
-/* For the available peripheral interrupt handler names, */
-/* please refer to the startup file (startup_stm32f4xx.s). */
-/******************************************************************************/
-
-/**
- * @brief This function handles EXTI line0 interrupt.
- */
-void EXTI0_IRQHandler(void)
-{
- /* USER CODE BEGIN EXTI0_IRQn 0 */
-
- /* USER CODE END EXTI0_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(USER_KEY_Pin);
- /* USER CODE BEGIN EXTI0_IRQn 1 */
-
- /* USER CODE END EXTI0_IRQn 1 */
-}
-
-/**
- * @brief This function handles EXTI line3 interrupt.
- */
-void EXTI3_IRQHandler(void)
-{
- /* USER CODE BEGIN EXTI3_IRQn 0 */
-
- /* USER CODE END EXTI3_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(CMPS_INT_Pin);
- /* USER CODE BEGIN EXTI3_IRQn 1 */
-
- /* USER CODE END EXTI3_IRQn 1 */
-}
-
-/**
- * @brief This function handles EXTI line4 interrupt.
- */
-void EXTI4_IRQHandler(void)
-{
- /* USER CODE BEGIN EXTI4_IRQn 0 */
-
- /* USER CODE END EXTI4_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(ACCL_INT_Pin);
- /* USER CODE BEGIN EXTI4_IRQn 1 */
-
- /* USER CODE END EXTI4_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA1 stream1 global interrupt.
- */
-void DMA1_Stream1_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA1_Stream1_IRQn 0 */
-
- /* USER CODE END DMA1_Stream1_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_usart3_rx);
- /* USER CODE BEGIN DMA1_Stream1_IRQn 1 */
-
- /* USER CODE END DMA1_Stream1_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA1 stream2 global interrupt.
- */
-void DMA1_Stream2_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA1_Stream2_IRQn 0 */
-
- /* USER CODE END DMA1_Stream2_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_i2c3_rx);
- /* USER CODE BEGIN DMA1_Stream2_IRQn 1 */
-
- /* USER CODE END DMA1_Stream2_IRQn 1 */
-}
-
-/**
- * @brief This function handles CAN1 RX0 interrupts.
- */
-void CAN1_RX0_IRQHandler(void)
-{
- /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
-
- /* USER CODE END CAN1_RX0_IRQn 0 */
- HAL_CAN_IRQHandler(&hcan1);
- /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
-
- /* USER CODE END CAN1_RX0_IRQn 1 */
-}
-
-/**
- * @brief This function handles CAN1 RX1 interrupt.
- */
-void CAN1_RX1_IRQHandler(void)
-{
- /* USER CODE BEGIN CAN1_RX1_IRQn 0 */
-
- /* USER CODE END CAN1_RX1_IRQn 0 */
- HAL_CAN_IRQHandler(&hcan1);
- /* USER CODE BEGIN CAN1_RX1_IRQn 1 */
-
- /* USER CODE END CAN1_RX1_IRQn 1 */
-}
-
-/**
- * @brief This function handles EXTI line[9:5] interrupts.
- */
-void EXTI9_5_IRQHandler(void)
-{
- /* USER CODE BEGIN EXTI9_5_IRQn 0 */
-
- /* USER CODE END EXTI9_5_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GYRO_INT_Pin);
- /* USER CODE BEGIN EXTI9_5_IRQn 1 */
-
- /* USER CODE END EXTI9_5_IRQn 1 */
-}
-
-/**
- * @brief This function handles TIM1 break interrupt and TIM9 global interrupt.
- */
-void TIM1_BRK_TIM9_IRQHandler(void)
-{
- /* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 0 */
-
- /* USER CODE END TIM1_BRK_TIM9_IRQn 0 */
- HAL_TIM_IRQHandler(&htim1);
- /* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 1 */
-
- /* USER CODE END TIM1_BRK_TIM9_IRQn 1 */
-}
-
-/**
- * @brief This function handles USART1 global interrupt.
- */
-void USART1_IRQHandler(void)
-{
- /* USER CODE BEGIN USART1_IRQn 0 */
-
- /* USER CODE END USART1_IRQn 0 */
- HAL_UART_IRQHandler(&huart1);
- /* USER CODE BEGIN USART1_IRQn 1 */
-
- /* USER CODE END USART1_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA1 stream7 global interrupt.
- */
-void DMA1_Stream7_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA1_Stream7_IRQn 0 */
-
- /* USER CODE END DMA1_Stream7_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_i2c2_tx);
- /* USER CODE BEGIN DMA1_Stream7_IRQn 1 */
-
- /* USER CODE END DMA1_Stream7_IRQn 1 */
-}
-
-/**
- * @brief This function handles TIM7 global interrupt.
- */
-void TIM7_IRQHandler(void)
-{
- /* USER CODE BEGIN TIM7_IRQn 0 */
-
- /* USER CODE END TIM7_IRQn 0 */
- HAL_TIM_IRQHandler(&htim7);
- /* USER CODE BEGIN TIM7_IRQn 1 */
-
- /* USER CODE END TIM7_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA2 stream1 global interrupt.
- */
-void DMA2_Stream1_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA2_Stream1_IRQn 0 */
-
- /* USER CODE END DMA2_Stream1_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_usart6_rx);
- /* USER CODE BEGIN DMA2_Stream1_IRQn 1 */
-
- /* USER CODE END DMA2_Stream1_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA2 stream2 global interrupt.
- */
-void DMA2_Stream2_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA2_Stream2_IRQn 0 */
-
- /* USER CODE END DMA2_Stream2_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_spi1_rx);
- /* USER CODE BEGIN DMA2_Stream2_IRQn 1 */
-
- /* USER CODE END DMA2_Stream2_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA2 stream3 global interrupt.
- */
-void DMA2_Stream3_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA2_Stream3_IRQn 0 */
-
- /* USER CODE END DMA2_Stream3_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_spi1_tx);
- /* USER CODE BEGIN DMA2_Stream3_IRQn 1 */
-
- /* USER CODE END DMA2_Stream3_IRQn 1 */
-}
-
-/**
- * @brief This function handles CAN2 RX0 interrupts.
- */
-void CAN2_RX0_IRQHandler(void)
-{
- /* USER CODE BEGIN CAN2_RX0_IRQn 0 */
-
- /* USER CODE END CAN2_RX0_IRQn 0 */
- HAL_CAN_IRQHandler(&hcan2);
- /* USER CODE BEGIN CAN2_RX0_IRQn 1 */
-
- /* USER CODE END CAN2_RX0_IRQn 1 */
-}
-
-/**
- * @brief This function handles CAN2 RX1 interrupt.
- */
-void CAN2_RX1_IRQHandler(void)
-{
- /* USER CODE BEGIN CAN2_RX1_IRQn 0 */
-
- /* USER CODE END CAN2_RX1_IRQn 0 */
- HAL_CAN_IRQHandler(&hcan2);
- /* USER CODE BEGIN CAN2_RX1_IRQn 1 */
-
- /* USER CODE END CAN2_RX1_IRQn 1 */
-}
-
-/**
- * @brief This function handles USB On The Go FS global interrupt.
- */
-void OTG_FS_IRQHandler(void)
-{
- /* USER CODE BEGIN OTG_FS_IRQn 0 */
-
- /* USER CODE END OTG_FS_IRQn 0 */
- HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
- /* USER CODE BEGIN OTG_FS_IRQn 1 */
-
- /* USER CODE END OTG_FS_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA2 stream5 global interrupt.
- */
-void DMA2_Stream5_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA2_Stream5_IRQn 0 */
-
- /* USER CODE END DMA2_Stream5_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_usart1_rx);
- /* USER CODE BEGIN DMA2_Stream5_IRQn 1 */
-
- /* USER CODE END DMA2_Stream5_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA2 stream6 global interrupt.
- */
-void DMA2_Stream6_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA2_Stream6_IRQn 0 */
-
- /* USER CODE END DMA2_Stream6_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_usart6_tx);
- /* USER CODE BEGIN DMA2_Stream6_IRQn 1 */
-
- /* USER CODE END DMA2_Stream6_IRQn 1 */
-}
-
-/**
- * @brief This function handles DMA2 stream7 global interrupt.
- */
-void DMA2_Stream7_IRQHandler(void)
-{
- /* USER CODE BEGIN DMA2_Stream7_IRQn 0 */
-
- /* USER CODE END DMA2_Stream7_IRQn 0 */
- HAL_DMA_IRQHandler(&hdma_usart1_tx);
- /* USER CODE BEGIN DMA2_Stream7_IRQn 1 */
-
- /* USER CODE END DMA2_Stream7_IRQn 1 */
-}
-
-/**
- * @brief This function handles USART6 global interrupt.
- */
-void USART6_IRQHandler(void)
-{
- /* USER CODE BEGIN USART6_IRQn 0 */
-
- /* USER CODE END USART6_IRQn 0 */
- HAL_UART_IRQHandler(&huart6);
- /* USER CODE BEGIN USART6_IRQn 1 */
- BSP_UART_IRQHandler(&huart6);
-
- /* USER CODE END USART6_IRQn 1 */
-}
-
-/* USER CODE BEGIN 1 */
-
-/* USER CODE END 1 */
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * @file stm32f4xx_it.c
+ * @brief Interrupt Service Routines.
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2025 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under Ultimate Liberty license
+ * SLA0044, the "License"; You may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * www.st.com/SLA0044
+ *
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+#include "stm32f4xx_it.h"
+#include "FreeRTOS.h"
+#include "task.h"
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+#include "bsp/uart.h"
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+/* USER CODE BEGIN TD */
+
+/* USER CODE END TD */
+
+/* Private define ------------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+
+/* USER CODE END PD */
+
+/* Private macro -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Private user code ---------------------------------------------------------*/
+/* USER CODE BEGIN 0 */
+
+/* USER CODE END 0 */
+
+/* External variables --------------------------------------------------------*/
+extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
+extern CAN_HandleTypeDef hcan1;
+extern CAN_HandleTypeDef hcan2;
+extern DMA_HandleTypeDef hdma_i2c2_tx;
+extern DMA_HandleTypeDef hdma_i2c3_rx;
+extern DMA_HandleTypeDef hdma_spi1_rx;
+extern DMA_HandleTypeDef hdma_spi1_tx;
+extern TIM_HandleTypeDef htim1;
+extern TIM_HandleTypeDef htim7;
+extern DMA_HandleTypeDef hdma_usart1_tx;
+extern DMA_HandleTypeDef hdma_usart1_rx;
+extern DMA_HandleTypeDef hdma_usart3_rx;
+extern DMA_HandleTypeDef hdma_usart6_rx;
+extern DMA_HandleTypeDef hdma_usart6_tx;
+extern UART_HandleTypeDef huart1;
+extern UART_HandleTypeDef huart6;
+/* USER CODE BEGIN EV */
+
+/* USER CODE END EV */
+
+/******************************************************************************/
+/* Cortex-M4 Processor Interruption and Exception Handlers */
+/******************************************************************************/
+/**
+ * @brief This function handles Non maskable interrupt.
+ */
+void NMI_Handler(void)
+{
+ /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
+
+ /* USER CODE END NonMaskableInt_IRQn 0 */
+ /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
+ while (1)
+ {
+ }
+ /* USER CODE END NonMaskableInt_IRQn 1 */
+}
+
+/**
+ * @brief This function handles Hard fault interrupt.
+ */
+void HardFault_Handler(void)
+{
+ /* USER CODE BEGIN HardFault_IRQn 0 */
+
+ /* USER CODE END HardFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_HardFault_IRQn 0 */
+ /* USER CODE END W1_HardFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Memory management fault.
+ */
+void MemManage_Handler(void)
+{
+ /* USER CODE BEGIN MemoryManagement_IRQn 0 */
+
+ /* USER CODE END MemoryManagement_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
+ /* USER CODE END W1_MemoryManagement_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Pre-fetch fault, memory access fault.
+ */
+void BusFault_Handler(void)
+{
+ /* USER CODE BEGIN BusFault_IRQn 0 */
+
+ /* USER CODE END BusFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_BusFault_IRQn 0 */
+ /* USER CODE END W1_BusFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Undefined instruction or illegal state.
+ */
+void UsageFault_Handler(void)
+{
+ /* USER CODE BEGIN UsageFault_IRQn 0 */
+
+ /* USER CODE END UsageFault_IRQn 0 */
+ while (1)
+ {
+ /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
+ /* USER CODE END W1_UsageFault_IRQn 0 */
+ }
+}
+
+/**
+ * @brief This function handles Debug monitor.
+ */
+void DebugMon_Handler(void)
+{
+ /* USER CODE BEGIN DebugMonitor_IRQn 0 */
+
+ /* USER CODE END DebugMonitor_IRQn 0 */
+ /* USER CODE BEGIN DebugMonitor_IRQn 1 */
+
+ /* USER CODE END DebugMonitor_IRQn 1 */
+}
+
+/**
+ * @brief This function handles System tick timer.
+ */
+void SysTick_Handler(void)
+{
+ /* USER CODE BEGIN SysTick_IRQn 0 */
+
+ /* USER CODE END SysTick_IRQn 0 */
+ HAL_IncTick();
+#if (INCLUDE_xTaskGetSchedulerState == 1 )
+ if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
+ {
+#endif /* INCLUDE_xTaskGetSchedulerState */
+ xPortSysTickHandler();
+#if (INCLUDE_xTaskGetSchedulerState == 1 )
+ }
+#endif /* INCLUDE_xTaskGetSchedulerState */
+ /* USER CODE BEGIN SysTick_IRQn 1 */
+
+ /* USER CODE END SysTick_IRQn 1 */
+}
+
+/******************************************************************************/
+/* STM32F4xx Peripheral Interrupt Handlers */
+/* Add here the Interrupt Handlers for the used peripherals. */
+/* For the available peripheral interrupt handler names, */
+/* please refer to the startup file (startup_stm32f4xx.s). */
+/******************************************************************************/
+
+/**
+ * @brief This function handles EXTI line0 interrupt.
+ */
+void EXTI0_IRQHandler(void)
+{
+ /* USER CODE BEGIN EXTI0_IRQn 0 */
+
+ /* USER CODE END EXTI0_IRQn 0 */
+ HAL_GPIO_EXTI_IRQHandler(USER_KEY_Pin);
+ /* USER CODE BEGIN EXTI0_IRQn 1 */
+
+ /* USER CODE END EXTI0_IRQn 1 */
+}
+
+/**
+ * @brief This function handles EXTI line3 interrupt.
+ */
+void EXTI3_IRQHandler(void)
+{
+ /* USER CODE BEGIN EXTI3_IRQn 0 */
+
+ /* USER CODE END EXTI3_IRQn 0 */
+ HAL_GPIO_EXTI_IRQHandler(CMPS_INT_Pin);
+ /* USER CODE BEGIN EXTI3_IRQn 1 */
+
+ /* USER CODE END EXTI3_IRQn 1 */
+}
+
+/**
+ * @brief This function handles EXTI line4 interrupt.
+ */
+void EXTI4_IRQHandler(void)
+{
+ /* USER CODE BEGIN EXTI4_IRQn 0 */
+
+ /* USER CODE END EXTI4_IRQn 0 */
+ HAL_GPIO_EXTI_IRQHandler(ACCL_INT_Pin);
+ /* USER CODE BEGIN EXTI4_IRQn 1 */
+
+ /* USER CODE END EXTI4_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA1 stream1 global interrupt.
+ */
+void DMA1_Stream1_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA1_Stream1_IRQn 0 */
+
+ /* USER CODE END DMA1_Stream1_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_usart3_rx);
+ /* USER CODE BEGIN DMA1_Stream1_IRQn 1 */
+
+ /* USER CODE END DMA1_Stream1_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA1 stream2 global interrupt.
+ */
+void DMA1_Stream2_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA1_Stream2_IRQn 0 */
+
+ /* USER CODE END DMA1_Stream2_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_i2c3_rx);
+ /* USER CODE BEGIN DMA1_Stream2_IRQn 1 */
+
+ /* USER CODE END DMA1_Stream2_IRQn 1 */
+}
+
+/**
+ * @brief This function handles CAN1 RX0 interrupts.
+ */
+void CAN1_RX0_IRQHandler(void)
+{
+ /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
+
+ /* USER CODE END CAN1_RX0_IRQn 0 */
+ HAL_CAN_IRQHandler(&hcan1);
+ /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
+
+ /* USER CODE END CAN1_RX0_IRQn 1 */
+}
+
+/**
+ * @brief This function handles CAN1 RX1 interrupt.
+ */
+void CAN1_RX1_IRQHandler(void)
+{
+ /* USER CODE BEGIN CAN1_RX1_IRQn 0 */
+
+ /* USER CODE END CAN1_RX1_IRQn 0 */
+ HAL_CAN_IRQHandler(&hcan1);
+ /* USER CODE BEGIN CAN1_RX1_IRQn 1 */
+
+ /* USER CODE END CAN1_RX1_IRQn 1 */
+}
+
+/**
+ * @brief This function handles EXTI line[9:5] interrupts.
+ */
+void EXTI9_5_IRQHandler(void)
+{
+ /* USER CODE BEGIN EXTI9_5_IRQn 0 */
+
+ /* USER CODE END EXTI9_5_IRQn 0 */
+ HAL_GPIO_EXTI_IRQHandler(GYRO_INT_Pin);
+ /* USER CODE BEGIN EXTI9_5_IRQn 1 */
+
+ /* USER CODE END EXTI9_5_IRQn 1 */
+}
+
+/**
+ * @brief This function handles TIM1 break interrupt and TIM9 global interrupt.
+ */
+void TIM1_BRK_TIM9_IRQHandler(void)
+{
+ /* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 0 */
+
+ /* USER CODE END TIM1_BRK_TIM9_IRQn 0 */
+ HAL_TIM_IRQHandler(&htim1);
+ /* USER CODE BEGIN TIM1_BRK_TIM9_IRQn 1 */
+
+ /* USER CODE END TIM1_BRK_TIM9_IRQn 1 */
+}
+
+/**
+ * @brief This function handles USART1 global interrupt.
+ */
+void USART1_IRQHandler(void)
+{
+ /* USER CODE BEGIN USART1_IRQn 0 */
+
+ /* USER CODE END USART1_IRQn 0 */
+ HAL_UART_IRQHandler(&huart1);
+ /* USER CODE BEGIN USART1_IRQn 1 */
+
+ /* USER CODE END USART1_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA1 stream7 global interrupt.
+ */
+void DMA1_Stream7_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA1_Stream7_IRQn 0 */
+
+ /* USER CODE END DMA1_Stream7_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_i2c2_tx);
+ /* USER CODE BEGIN DMA1_Stream7_IRQn 1 */
+
+ /* USER CODE END DMA1_Stream7_IRQn 1 */
+}
+
+/**
+ * @brief This function handles TIM7 global interrupt.
+ */
+void TIM7_IRQHandler(void)
+{
+ /* USER CODE BEGIN TIM7_IRQn 0 */
+
+ /* USER CODE END TIM7_IRQn 0 */
+ HAL_TIM_IRQHandler(&htim7);
+ /* USER CODE BEGIN TIM7_IRQn 1 */
+
+ /* USER CODE END TIM7_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA2 stream1 global interrupt.
+ */
+void DMA2_Stream1_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA2_Stream1_IRQn 0 */
+
+ /* USER CODE END DMA2_Stream1_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_usart6_rx);
+ /* USER CODE BEGIN DMA2_Stream1_IRQn 1 */
+
+ /* USER CODE END DMA2_Stream1_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA2 stream2 global interrupt.
+ */
+void DMA2_Stream2_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA2_Stream2_IRQn 0 */
+
+ /* USER CODE END DMA2_Stream2_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_spi1_rx);
+ /* USER CODE BEGIN DMA2_Stream2_IRQn 1 */
+
+ /* USER CODE END DMA2_Stream2_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA2 stream3 global interrupt.
+ */
+void DMA2_Stream3_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA2_Stream3_IRQn 0 */
+
+ /* USER CODE END DMA2_Stream3_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_spi1_tx);
+ /* USER CODE BEGIN DMA2_Stream3_IRQn 1 */
+
+ /* USER CODE END DMA2_Stream3_IRQn 1 */
+}
+
+/**
+ * @brief This function handles CAN2 RX0 interrupts.
+ */
+void CAN2_RX0_IRQHandler(void)
+{
+ /* USER CODE BEGIN CAN2_RX0_IRQn 0 */
+
+ /* USER CODE END CAN2_RX0_IRQn 0 */
+ HAL_CAN_IRQHandler(&hcan2);
+ /* USER CODE BEGIN CAN2_RX0_IRQn 1 */
+
+ /* USER CODE END CAN2_RX0_IRQn 1 */
+}
+
+/**
+ * @brief This function handles CAN2 RX1 interrupt.
+ */
+void CAN2_RX1_IRQHandler(void)
+{
+ /* USER CODE BEGIN CAN2_RX1_IRQn 0 */
+
+ /* USER CODE END CAN2_RX1_IRQn 0 */
+ HAL_CAN_IRQHandler(&hcan2);
+ /* USER CODE BEGIN CAN2_RX1_IRQn 1 */
+
+ /* USER CODE END CAN2_RX1_IRQn 1 */
+}
+
+/**
+ * @brief This function handles USB On The Go FS global interrupt.
+ */
+void OTG_FS_IRQHandler(void)
+{
+ /* USER CODE BEGIN OTG_FS_IRQn 0 */
+
+ /* USER CODE END OTG_FS_IRQn 0 */
+ HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
+ /* USER CODE BEGIN OTG_FS_IRQn 1 */
+
+ /* USER CODE END OTG_FS_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA2 stream5 global interrupt.
+ */
+void DMA2_Stream5_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA2_Stream5_IRQn 0 */
+
+ /* USER CODE END DMA2_Stream5_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_usart1_rx);
+ /* USER CODE BEGIN DMA2_Stream5_IRQn 1 */
+
+ /* USER CODE END DMA2_Stream5_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA2 stream6 global interrupt.
+ */
+void DMA2_Stream6_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA2_Stream6_IRQn 0 */
+
+ /* USER CODE END DMA2_Stream6_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_usart6_tx);
+ /* USER CODE BEGIN DMA2_Stream6_IRQn 1 */
+
+ /* USER CODE END DMA2_Stream6_IRQn 1 */
+}
+
+/**
+ * @brief This function handles DMA2 stream7 global interrupt.
+ */
+void DMA2_Stream7_IRQHandler(void)
+{
+ /* USER CODE BEGIN DMA2_Stream7_IRQn 0 */
+
+ /* USER CODE END DMA2_Stream7_IRQn 0 */
+ HAL_DMA_IRQHandler(&hdma_usart1_tx);
+ /* USER CODE BEGIN DMA2_Stream7_IRQn 1 */
+
+ /* USER CODE END DMA2_Stream7_IRQn 1 */
+}
+
+/**
+ * @brief This function handles USART6 global interrupt.
+ */
+void USART6_IRQHandler(void)
+{
+ /* USER CODE BEGIN USART6_IRQn 0 */
+
+ /* USER CODE END USART6_IRQn 0 */
+ HAL_UART_IRQHandler(&huart6);
+ /* USER CODE BEGIN USART6_IRQn 1 */
+ BSP_UART_IRQHandler(&huart6);
+
+ /* USER CODE END USART6_IRQn 1 */
+}
+
+/* USER CODE BEGIN 1 */
+
+/* USER CODE END 1 */
diff --git a/User/bsp/can.c b/User/bsp/can.c
index 193dd2d..e401cdd 100644
--- a/User/bsp/can.c
+++ b/User/bsp/can.c
@@ -37,16 +37,21 @@ static osMutexId_t queue_mutex = 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解析器 */
+static BSP_CAN_TxQueue_t tx_queues[BSP_CAN_NUM]; /* 每个CAN的发送队列 */
/* Private function prototypes ---------------------------------------------- */
static BSP_CAN_t CAN_Get(CAN_HandleTypeDef *hcan);
static osMessageQueueId_t BSP_CAN_FindQueue(BSP_CAN_t can, uint32_t can_id);
static int8_t BSP_CAN_CreateIdQueue(BSP_CAN_t can, uint32_t can_id, uint8_t queue_size);
-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(void);
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);
+static void BSP_CAN_TxQueueInit(BSP_CAN_t can);
+static bool BSP_CAN_TxQueuePush(BSP_CAN_t can, BSP_CAN_TxMessage_t *msg);
+static bool BSP_CAN_TxQueuePop(BSP_CAN_t can, BSP_CAN_TxMessage_t *msg);
+static bool BSP_CAN_TxQueueIsEmpty(BSP_CAN_t can);
/* Private functions -------------------------------------------------------- */
/* USER FUNCTION BEGIN */
@@ -121,29 +126,7 @@ static int8_t BSP_CAN_CreateIdQueue(BSP_CAN_t can, uint32_t can_id, uint8_t queu
return BSP_OK;
}
-/**
- * @brief 删除指定CAN ID的消息队列
- * @note 内部函数,已包含互斥锁保护
- */
-static int8_t BSP_CAN_DeleteIdQueue(BSP_CAN_t can, uint32_t can_id) {
- if (osMutexAcquire(queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) != osOK) {
- return BSP_ERR_TIMEOUT;
- }
- BSP_CAN_QueueNode_t **current = &queue_list;
- while (*current != NULL) {
- if ((*current)->can == can && (*current)->can_id == can_id) {
- BSP_CAN_QueueNode_t *to_delete = *current;
- *current = (*current)->next;
- osMessageQueueDelete(to_delete->queue);
- BSP_Free(to_delete);
- osMutexRelease(queue_mutex);
- return BSP_OK;
- }
- current = &(*current)->next;
- }
- osMutexRelease(queue_mutex);
- return BSP_ERR; // 未找到
-}
+
/**
* @brief 获取帧类型
*/
@@ -163,6 +146,106 @@ static uint32_t BSP_CAN_DefaultIdParser(uint32_t original_id, BSP_CAN_FrameType_
return original_id;
}
+/**
+ * @brief 初始化发送队列
+ */
+static void BSP_CAN_TxQueueInit(BSP_CAN_t can) {
+ if (can >= BSP_CAN_NUM) return;
+
+ tx_queues[can].head = 0;
+ tx_queues[can].tail = 0;
+}
+
+/**
+ * @brief 向发送队列添加消息(无锁)
+ */
+static bool BSP_CAN_TxQueuePush(BSP_CAN_t can, BSP_CAN_TxMessage_t *msg) {
+ if (can >= BSP_CAN_NUM || msg == NULL) return false;
+
+ BSP_CAN_TxQueue_t *queue = &tx_queues[can];
+ uint32_t next_head = (queue->head + 1) % BSP_CAN_TX_QUEUE_SIZE;
+
+ // 队列满
+ if (next_head == queue->tail) {
+ return false;
+ }
+
+ // 复制消息
+ queue->buffer[queue->head] = *msg;
+
+ // 更新头指针(原子操作)
+ queue->head = next_head;
+
+ return true;
+}
+
+
+/**
+ * @brief 从发送队列取出消息(无锁)
+ */
+static bool BSP_CAN_TxQueuePop(BSP_CAN_t can, BSP_CAN_TxMessage_t *msg) {
+ if (can >= BSP_CAN_NUM || msg == NULL) return false;
+
+ BSP_CAN_TxQueue_t *queue = &tx_queues[can];
+
+ // 队列空
+ if (queue->head == queue->tail) {
+ return false;
+ }
+
+ // 复制消息
+ *msg = queue->buffer[queue->tail];
+
+ // 更新尾指针(原子操作)
+ queue->tail = (queue->tail + 1) % BSP_CAN_TX_QUEUE_SIZE;
+
+ return true;
+}
+
+/**
+ * @brief 检查发送队列是否为空
+ */
+static bool BSP_CAN_TxQueueIsEmpty(BSP_CAN_t can) {
+ if (can >= BSP_CAN_NUM) return true;
+
+ return tx_queues[can].head == tx_queues[can].tail;
+}
+
+/**
+ * @brief 处理所有CAN实例的发送队列
+ */
+static void BSP_CAN_TxCompleteCallback(void) {
+ // 处理所有CAN实例的发送队列
+ for (int i = 0; i < BSP_CAN_NUM; i++) {
+ BSP_CAN_t can = (BSP_CAN_t)i;
+ CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle(can);
+ if (hcan == NULL) continue;
+
+ BSP_CAN_TxMessage_t msg;
+ uint32_t mailbox;
+
+ // 尝试发送队列中的消息
+ while (!BSP_CAN_TxQueueIsEmpty(can)) {
+ // 检查是否有空闲邮箱
+ if (HAL_CAN_GetTxMailboxesFreeLevel(hcan) == 0) {
+ break; // 没有空闲邮箱,等待下次中断
+ }
+
+ // 从队列中取出消息
+ if (!BSP_CAN_TxQueuePop(can, &msg)) {
+ break;
+ }
+
+ // 发送消息
+ if (HAL_CAN_AddTxMessage(hcan, &msg.header, msg.data, &mailbox) != HAL_OK) {
+ // 发送失败,消息已经从队列中移除,直接丢弃
+ break;
+ }
+ }
+ }
+}
+
+
/**
* @brief FIFO0接收处理函数
*/
@@ -347,7 +430,12 @@ int8_t BSP_CAN_Init(void) {
// 清零回调函数数组
memset(CAN_Callback, 0, sizeof(CAN_Callback));
-
+
+ // 初始化发送队列
+ for (int i = 0; i < BSP_CAN_NUM; i++) {
+ BSP_CAN_TxQueueInit((BSP_CAN_t)i);
+ }
+
// 初始化ID解析器为默认解析器
id_parser = BSP_CAN_DefaultIdParser;
@@ -377,6 +465,9 @@ int8_t BSP_CAN_Init(void) {
// 自动注册CAN1接收回调函数
BSP_CAN_RegisterCallback(BSP_CAN_1, HAL_CAN_RX_FIFO0_MSG_PENDING_CB, BSP_CAN_RxFifo0Callback);
+ BSP_CAN_RegisterCallback(BSP_CAN_1, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);
+ BSP_CAN_RegisterCallback(BSP_CAN_1, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);
+ BSP_CAN_RegisterCallback(BSP_CAN_1, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);
// 激活CAN1中断
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING |
@@ -390,48 +481,19 @@ int8_t BSP_CAN_Init(void) {
// 自动注册CAN2接收回调函数
BSP_CAN_RegisterCallback(BSP_CAN_2, HAL_CAN_RX_FIFO1_MSG_PENDING_CB, BSP_CAN_RxFifo1Callback);
+ BSP_CAN_RegisterCallback(BSP_CAN_2, HAL_CAN_TX_MAILBOX0_CPLT_CB, BSP_CAN_TxCompleteCallback);
+ BSP_CAN_RegisterCallback(BSP_CAN_2, HAL_CAN_TX_MAILBOX1_CPLT_CB, BSP_CAN_TxCompleteCallback);
+ BSP_CAN_RegisterCallback(BSP_CAN_2, HAL_CAN_TX_MAILBOX2_CPLT_CB, BSP_CAN_TxCompleteCallback);
// 激活CAN2中断
- HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO1_MSG_PENDING);
+ HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO1_MSG_PENDING |
+ CAN_IT_TX_MAILBOX_EMPTY); // 激活发送邮箱空中断
inited = true;
return BSP_OK;
}
-int8_t BSP_CAN_DeInit(void) {
- if (!inited) {
- return BSP_ERR;
- }
-
- // 删除所有队列
- if (osMutexAcquire(queue_mutex, CAN_QUEUE_MUTEX_TIMEOUT) == osOK) {
- BSP_CAN_QueueNode_t *current = queue_list;
- while (current != NULL) {
- BSP_CAN_QueueNode_t *next = current->next;
- osMessageQueueDelete(current->queue);
- BSP_Free(current);
- current = next;
- }
- queue_list = NULL;
- osMutexRelease(queue_mutex);
- }
-
- // 删除互斥锁
- if (queue_mutex != NULL) {
- osMutexDelete(queue_mutex);
- queue_mutex = NULL;
- }
-
- // 清零回调函数数组
- memset(CAN_Callback, 0, sizeof(CAN_Callback));
-
- // 重置ID解析器
- id_parser = NULL;
-
- inited = false;
- return BSP_OK;
-}
CAN_HandleTypeDef *BSP_CAN_GetHandle(BSP_CAN_t can) {
if (can >= BSP_CAN_NUM) {
@@ -487,44 +549,58 @@ int8_t BSP_CAN_Transmit(BSP_CAN_t can, BSP_CAN_Format_t format,
return BSP_ERR_NULL;
}
- CAN_TxHeaderTypeDef header = {0};
- uint32_t mailbox;
+ // 准备发送消息
+ BSP_CAN_TxMessage_t tx_msg = {0};
switch (format) {
case BSP_CAN_FORMAT_STD_DATA:
- header.StdId = id;
- header.IDE = CAN_ID_STD;
- header.RTR = CAN_RTR_DATA;
+ tx_msg.header.StdId = id;
+ tx_msg.header.IDE = CAN_ID_STD;
+ tx_msg.header.RTR = CAN_RTR_DATA;
break;
case BSP_CAN_FORMAT_EXT_DATA:
- header.ExtId = id;
- header.IDE = CAN_ID_EXT;
- header.RTR = CAN_RTR_DATA;
+ tx_msg.header.ExtId = id;
+ tx_msg.header.IDE = CAN_ID_EXT;
+ tx_msg.header.RTR = CAN_RTR_DATA;
break;
case BSP_CAN_FORMAT_STD_REMOTE:
- header.StdId = id;
- header.IDE = CAN_ID_STD;
- header.RTR = CAN_RTR_REMOTE;
+ tx_msg.header.StdId = id;
+ tx_msg.header.IDE = CAN_ID_STD;
+ tx_msg.header.RTR = CAN_RTR_REMOTE;
break;
case BSP_CAN_FORMAT_EXT_REMOTE:
- header.ExtId = id;
- header.IDE = CAN_ID_EXT;
- header.RTR = CAN_RTR_REMOTE;
+ tx_msg.header.ExtId = id;
+ tx_msg.header.IDE = CAN_ID_EXT;
+ tx_msg.header.RTR = CAN_RTR_REMOTE;
break;
default:
return BSP_ERR;
}
- header.DLC = dlc;
- header.TransmitGlobalTime = DISABLE;
+ tx_msg.header.DLC = dlc;
+ tx_msg.header.TransmitGlobalTime = DISABLE;
- HAL_StatusTypeDef result = HAL_CAN_AddTxMessage(hcan, &header, data, &mailbox);
-
- if (result != HAL_OK) {
- return BSP_ERR;
+ // 复制数据
+ if (data != NULL && dlc > 0) {
+ memcpy(tx_msg.data, data, dlc);
}
- return BSP_OK;
+ // 尝试直接发送到邮箱
+ uint32_t mailbox;
+ if (HAL_CAN_GetTxMailboxesFreeLevel(hcan) > 0) {
+ HAL_StatusTypeDef result = HAL_CAN_AddTxMessage(hcan, &tx_msg.header, tx_msg.data, &mailbox);
+ if (result == HAL_OK) {
+ return BSP_OK; // 发送成功
+ }
+ }
+
+ // 邮箱满,尝试放入队列
+ if (BSP_CAN_TxQueuePush(can, &tx_msg)) {
+ return BSP_OK; // 成功放入队列
+ }
+
+ // 队列也满,丢弃数据
+ return BSP_ERR; // 数据丢弃
}
int8_t BSP_CAN_TransmitStdDataFrame(BSP_CAN_t can, BSP_CAN_StdDataFrame_t *frame) {
@@ -556,12 +632,6 @@ int8_t BSP_CAN_RegisterId(BSP_CAN_t can, uint32_t can_id, uint8_t queue_size) {
return BSP_CAN_CreateIdQueue(can, can_id, queue_size);
}
-int8_t BSP_CAN_UnregisterIdQueue(BSP_CAN_t can, uint32_t can_id) {
- if (!inited) {
- return BSP_ERR_INITED;
- }
- return BSP_CAN_DeleteIdQueue(can, can_id);
-}
int8_t BSP_CAN_GetMessage(BSP_CAN_t can, uint32_t can_id, BSP_CAN_Message_t *msg, uint32_t timeout) {
if (!inited) {
@@ -628,15 +698,6 @@ int8_t BSP_CAN_RegisterIdParser(BSP_CAN_IdParser_t parser) {
return BSP_OK;
}
-int8_t BSP_CAN_UnregisterIdParser(void) {
- if (!inited) {
- return BSP_ERR_INITED;
- }
-
- id_parser = BSP_CAN_DefaultIdParser;
- return BSP_OK;
-}
-
uint32_t BSP_CAN_ParseId(uint32_t original_id, BSP_CAN_FrameType_t frame_type) {
if (id_parser != NULL) {
return id_parser(original_id, frame_type);
@@ -644,42 +705,4 @@ uint32_t BSP_CAN_ParseId(uint32_t original_id, BSP_CAN_FrameType_t frame_type) {
return BSP_CAN_DefaultIdParser(original_id, frame_type);
}
-int8_t BSP_CAN_WaitTxMailboxEmpty(BSP_CAN_t can, uint32_t timeout) {
- if (!inited) {
- return BSP_ERR_INITED;
- }
- if (can >= BSP_CAN_NUM) {
- return BSP_ERR;
- }
-
- CAN_HandleTypeDef *hcan = BSP_CAN_GetHandle(can);
- if (hcan == NULL) {
- return BSP_ERR_NULL;
- }
-
- uint32_t start_time = HAL_GetTick();
-
- // 如果超时时间为0,立即检查并返回
- if (timeout == 0) {
- uint32_t free_level = HAL_CAN_GetTxMailboxesFreeLevel(hcan);
- return (free_level > 0) ? BSP_OK : BSP_ERR_TIMEOUT;
- }
-
- // 等待至少有一个邮箱空闲
- while (true) {
- uint32_t free_level = HAL_CAN_GetTxMailboxesFreeLevel(hcan);
- if (free_level > 0) {
- return BSP_OK;
- }
-
- // 检查超时
- if (timeout != BSP_CAN_TIMEOUT_FOREVER) {
- uint32_t elapsed = HAL_GetTick() - start_time;
- if (elapsed >= timeout) {
- return BSP_ERR_TIMEOUT;
- }
- }
-
- osDelay(1);
- }
-}
+
diff --git a/User/bsp/can.h b/User/bsp/can.h
index 00b60fe..e6b5f71 100644
--- a/User/bsp/can.h
+++ b/User/bsp/can.h
@@ -21,6 +21,7 @@ extern "C" {
#define BSP_CAN_DEFAULT_QUEUE_SIZE 10
#define BSP_CAN_TIMEOUT_IMMEDIATE 0
#define BSP_CAN_TIMEOUT_FOREVER osWaitForever
+#define BSP_CAN_TX_QUEUE_SIZE 32 /* 发送队列大小 */
/* USER DEFINE BEGIN */
@@ -102,6 +103,19 @@ typedef struct {
/* ID解析回调函数类型 */
typedef uint32_t (*BSP_CAN_IdParser_t)(uint32_t original_id, BSP_CAN_FrameType_t frame_type);
+/* CAN发送消息结构体 */
+typedef struct {
+ CAN_TxHeaderTypeDef header; /* 发送头 */
+ uint8_t data[BSP_CAN_MAX_DLC]; /* 数据 */
+} BSP_CAN_TxMessage_t;
+
+/* 无锁环形队列结构体 */
+typedef struct {
+ BSP_CAN_TxMessage_t buffer[BSP_CAN_TX_QUEUE_SIZE]; /* 缓冲区 */
+ volatile uint32_t head; /* 队列头 */
+ volatile uint32_t tail; /* 队列尾 */
+} BSP_CAN_TxQueue_t;
+
/* USER STRUCT BEGIN */
/* USER STRUCT END */
@@ -114,12 +128,6 @@ typedef uint32_t (*BSP_CAN_IdParser_t)(uint32_t original_id, BSP_CAN_FrameType_t
*/
int8_t BSP_CAN_Init(void);
-/**
- * @brief 反初始化 CAN 模块
- * @return BSP_OK 成功,其他值失败
- */
-int8_t BSP_CAN_DeInit(void);
-
/**
* @brief 获取 CAN 句柄
* @param can CAN 枚举
@@ -173,13 +181,20 @@ int8_t BSP_CAN_TransmitExtDataFrame(BSP_CAN_t can, BSP_CAN_ExtDataFrame_t *frame
*/
int8_t BSP_CAN_TransmitRemoteFrame(BSP_CAN_t can, BSP_CAN_RemoteFrame_t *frame);
+
/**
- * @brief 等待CAN发送邮箱空闲
+ * @brief 获取发送队列中待发送消息数量
+ * @param can CAN 枚举
+ * @return 队列中消息数量,-1表示错误
+ */
+int32_t BSP_CAN_GetTxQueueCount(BSP_CAN_t can);
+
+/**
+ * @brief 清空发送队列
* @param can CAN 枚举
- * @param timeout 超时时间(毫秒),0为立即返回,osWaitForever为永久等待
* @return BSP_OK 成功,其他值失败
*/
-int8_t BSP_CAN_WaitTxMailboxEmpty(BSP_CAN_t can, uint32_t timeout);
+int8_t BSP_CAN_FlushTxQueue(BSP_CAN_t can);
/**
* @brief 注册 CAN ID 接收队列
@@ -190,13 +205,7 @@ int8_t BSP_CAN_WaitTxMailboxEmpty(BSP_CAN_t can, uint32_t timeout);
*/
int8_t BSP_CAN_RegisterId(BSP_CAN_t can, uint32_t can_id, uint8_t queue_size);
-/**
- * @brief 注销 CAN ID 接收队列
- * @param can CAN 枚举
- * @param can_id 解析后的CAN ID
- * @return BSP_OK 成功,其他值失败
- */
-int8_t BSP_CAN_UnregisterIdQueue(BSP_CAN_t can, uint32_t can_id);
+
/**
* @brief 获取 CAN 消息
@@ -231,11 +240,6 @@ int8_t BSP_CAN_FlushQueue(BSP_CAN_t can, uint32_t can_id);
*/
int8_t BSP_CAN_RegisterIdParser(BSP_CAN_IdParser_t parser);
-/**
- * @brief 注销ID解析器
- * @return BSP_OK 成功,其他值失败
- */
-int8_t BSP_CAN_UnregisterIdParser(void);
/**
* @brief 解析CAN ID
diff --git a/User/device/dm_imu.c b/User/device/dm_imu.c
index e05c1de..e5380d9 100644
--- a/User/device/dm_imu.c
+++ b/User/device/dm_imu.c
@@ -166,7 +166,6 @@ int8_t DM_IMU_Request(DM_IMU_t *imu, DM_IMU_RID_t rid) {
.dlc = 4,
};
memcpy(frame.data, tx_data, 4);
- BSP_CAN_WaitTxMailboxEmpty(imu->param.can, 1); // 等待发送邮箱空闲
int8_t result = BSP_CAN_TransmitStdDataFrame(imu->param.can, &frame);
return (result == BSP_OK) ? DEVICE_OK : DEVICE_ERR;
}
@@ -253,8 +252,9 @@ int8_t DM_IMU_AutoUpdateAll(DM_IMU_t *imu){
count++;
if (count >= 4) {
count = 0; // 重置计数器
+ return DEVICE_OK;
}
- return DEVICE_OK;
+ return DEVICE_ERR;
}
/**
diff --git a/User/device/dr16.c b/User/device/dr16.c
index 929e4b5..120997b 100644
--- a/User/device/dr16.c
+++ b/User/device/dr16.c
@@ -141,13 +141,13 @@ int8_t DR16_ParseData(DR16_t *dr16){
uint16_t key_value = dr16->raw_data.key;
// 解析键盘位映射(W-B键,位0-15)
- for (int i = CMD_KEY_W; i <= CMD_KEY_B; i++) {
+ for (int i = DR16_KEY_W; i <= DR16_KEY_B; i++) {
dr16->data.keyboard.key[i] = (key_value & (1 << i)) != 0;
}
// 解析鼠标点击
- dr16->data.keyboard.key[CMD_L_CLICK] = dr16->data.mouse.l_click;
- dr16->data.keyboard.key[CMD_R_CLICK] = dr16->data.mouse.r_click;
+ dr16->data.keyboard.key[DR16_L_CLICK] = dr16->data.mouse.l_click;
+ dr16->data.keyboard.key[DR16_R_CLICK] = dr16->data.mouse.r_click;
// 解析第五通道
dr16->data.ch_res = 2.0f * ((float)dr16->raw_data.res - DR16_CH_VALUE_MID) / full_range;
diff --git a/User/device/dr16.h b/User/device/dr16.h
index 73ebbf2..03fa526 100644
--- a/User/device/dr16.h
+++ b/User/device/dr16.h
@@ -38,33 +38,33 @@ typedef struct __packed {
} DR16_RawData_t;
typedef enum {
- CMD_SW_ERR = 0,
- CMD_SW_UP = 1,
- CMD_SW_MID = 3,
- CMD_SW_DOWN = 2,
+ DR16_SW_ERR = 0,
+ DR16_SW_UP = 1,
+ DR16_SW_MID = 3,
+ DR16_SW_DOWN = 2,
} DR16_SwitchPos_t;
/* 键盘按键值 */
typedef enum {
- CMD_KEY_W = 0,
- CMD_KEY_S,
- CMD_KEY_A,
- CMD_KEY_D,
- CMD_KEY_SHIFT,
- CMD_KEY_CTRL,
- CMD_KEY_Q,
- CMD_KEY_E,
- CMD_KEY_R,
- CMD_KEY_F,
- CMD_KEY_G,
- CMD_KEY_Z,
- CMD_KEY_X,
- CMD_KEY_C,
- CMD_KEY_V,
- CMD_KEY_B,
- CMD_L_CLICK,
- CMD_R_CLICK,
- CMD_KEY_NUM,
+ DR16_KEY_W = 0,
+ DR16_KEY_S,
+ DR16_KEY_A,
+ DR16_KEY_D,
+ DR16_KEY_SHIFT,
+ DR16_KEY_CTRL,
+ DR16_KEY_Q,
+ DR16_KEY_E,
+ DR16_KEY_R,
+ DR16_KEY_F,
+ DR16_KEY_G,
+ DR16_KEY_Z,
+ DR16_KEY_X,
+ DR16_KEY_C,
+ DR16_KEY_V,
+ DR16_KEY_B,
+ DR16_L_CLICK,
+ DR16_R_CLICK,
+ DR16_KEY_NUM,
} DR16_Key_t;
typedef struct {
@@ -87,14 +87,13 @@ typedef struct {
} mouse; /* 鼠标值 */
union {
- bool key[CMD_KEY_NUM]; /* 键盘按键值 */
+ bool key[DR16_KEY_NUM]; /* 键盘按键值 */
uint16_t value; /* 键盘按键值的位映射 */
} keyboard;
uint16_t res; /* 保留,未启用 */
} DR16_Data_t;
-
typedef struct {
DEVICE_Header_t header;
DR16_RawData_t raw_data;
diff --git a/User/device/motor_lk.c b/User/device/motor_lk.c
index c7911d6..c26878e 100644
--- a/User/device/motor_lk.c
+++ b/User/device/motor_lk.c
@@ -253,7 +253,6 @@ int8_t MOTOR_LK_SetOutput(MOTOR_LK_Param_t *param, float value) {
tx_frame.data[5] = (uint8_t)((torque_control >> 8) & 0xFF);
tx_frame.data[6] = 0x00;
tx_frame.data[7] = 0x00;
- BSP_CAN_WaitTxMailboxEmpty(param->can, 1); // 等待发送邮箱空闲
return BSP_CAN_TransmitStdDataFrame(param->can, &tx_frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
@@ -279,7 +278,6 @@ int8_t MOTOR_LK_MotorOn(MOTOR_LK_Param_t *param) {
tx_frame.data[5] = 0x00;
tx_frame.data[6] = 0x00;
tx_frame.data[7] = 0x00;
- BSP_CAN_WaitTxMailboxEmpty(param->can, 1); // 等待发送邮箱空闲
return BSP_CAN_TransmitStdDataFrame(param->can, &tx_frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
@@ -299,7 +297,6 @@ int8_t MOTOR_LK_MotorOff(MOTOR_LK_Param_t *param) {
tx_frame.data[5] = 0x00;
tx_frame.data[6] = 0x00;
tx_frame.data[7] = 0x00;
- BSP_CAN_WaitTxMailboxEmpty(param->can, 1); // 等待发送邮箱空闲
return BSP_CAN_TransmitStdDataFrame(param->can, &tx_frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
diff --git a/User/device/motor_lz.c b/User/device/motor_lz.c
index 59ba153..7ed7344 100644
--- a/User/device/motor_lz.c
+++ b/User/device/motor_lz.c
@@ -134,7 +134,6 @@ static int8_t MOTOR_LZ_SendExtFrame(BSP_CAN_t can, uint32_t ext_id, uint8_t *dat
} else {
memset(tx_frame.data, 0, dlc);
}
- BSP_CAN_WaitTxMailboxEmpty(can, 1); // 等待发送邮箱空闲
return BSP_CAN_TransmitExtDataFrame(can, &tx_frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
@@ -244,14 +243,6 @@ int8_t MOTOR_LZ_Init(void) {
return BSP_CAN_RegisterIdParser(MOTOR_LZ_IdParser) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
-/**
- * @brief 反初始化灵足电机驱动系统
- * @return 设备状态码
- */
-int8_t MOTOR_LZ_DeInit(void) {
- // 注销ID解析器
- return BSP_CAN_UnregisterIdParser() == BSP_OK ? DEVICE_OK : DEVICE_ERR;
-}
int8_t MOTOR_LZ_Register(MOTOR_LZ_Param_t *param) {
if (param == NULL) return DEVICE_ERR_NULL;
@@ -369,7 +360,6 @@ int8_t MOTOR_LZ_MotionControl(MOTOR_LZ_Param_t *param, MOTOR_LZ_MotionParam_t *m
uint16_t raw_kd = MOTOR_LZ_FloatToRawPositive(send_param.kd, LZ_KD_MAX);
data[6] = (raw_kd >> 8) & 0xFF;
data[7] = raw_kd & 0xFF;
- BSP_CAN_WaitTxMailboxEmpty(param->can, 1); // 等待发送邮箱空闲
return MOTOR_LZ_SendExtFrame(param->can, ext_id, data, 8);
}
@@ -378,7 +368,6 @@ int8_t MOTOR_LZ_Enable(MOTOR_LZ_Param_t *param) {
if (param == NULL) return DEVICE_ERR_NULL;
// 构建扩展ID - 使能命令
- // 格式: 0x300FF7X, 其中X是motor_id的低4位
uint32_t ext_id = MOTOR_LZ_BuildExtID(MOTOR_LZ_CMD_ENABLE, param->host_id, param->motor_id);
// 数据区清零
diff --git a/User/device/motor_lz.h b/User/device/motor_lz.h
index 76a72ae..d2a8002 100644
--- a/User/device/motor_lz.h
+++ b/User/device/motor_lz.h
@@ -111,12 +111,6 @@ typedef struct {
*/
int8_t MOTOR_LZ_Init(void);
-/**
- * @brief 反初始化灵足电机驱动系统
- * @return 设备状态码
- */
-int8_t MOTOR_LZ_DeInit(void);
-
/**
* @brief 注册一个灵足电机
* @param param 电机参数
diff --git a/User/device/motor_rm.c b/User/device/motor_rm.c
index b852c48..9b5ea44 100644
--- a/User/device/motor_rm.c
+++ b/User/device/motor_rm.c
@@ -138,17 +138,23 @@ static void Motor_RM_Decode(MOTOR_RM_t *motor, BSP_CAN_Message_t *msg) {
motor->feedback.rotor_abs_angle = rotor_angle;
motor->feedback.rotor_speed = rotor_speed;
motor->feedback.torque_current = torque_current;
+ }
+ while (motor->feedback.rotor_abs_angle < 0) {
+ motor->feedback.rotor_abs_angle += M_2PI;
+ }
+ while (motor->feedback.rotor_abs_angle >= M_2PI) {
+ motor->feedback.rotor_abs_angle -= M_2PI;
+ }
+ if (motor->motor.reverse) {
+ motor->feedback.rotor_abs_angle = M_2PI - motor->feedback.rotor_abs_angle;
+ motor->feedback.rotor_speed = -motor->feedback.rotor_speed;
+ motor->feedback.torque_current = -motor->feedback.torque_current;
}
motor->feedback.temp = msg->data[6];
- motor->motor.feedback.rotor_abs_angle = motor->feedback.rotor_abs_angle;
- motor->motor.feedback.rotor_speed = motor->feedback.rotor_speed;
- motor->motor.feedback.torque_current = motor->feedback.torque_current;
- motor->motor.feedback.temp = motor->feedback.temp;
}
/* Exported functions ------------------------------------------------------- */
-
int8_t MOTOR_RM_Register(MOTOR_RM_Param_t *param) {
if (param == NULL) return DEVICE_ERR_NULL;
if (MOTOR_RM_CreateCANManager(param->can) != DEVICE_OK) return DEVICE_ERR;
@@ -197,7 +203,7 @@ int8_t MOTOR_RM_Update(MOTOR_RM_Param_t *param) {
motor->motor.header.online = true;
motor->motor.header.last_online_time = BSP_TIME_Get();
Motor_RM_Decode(motor, &rx_msg);
-
+ motor->motor.feedback = motor->feedback;
return DEVICE_OK;
}
}
@@ -227,6 +233,9 @@ int8_t MOTOR_RM_SetOutput(MOTOR_RM_Param_t *param, float value) {
if (manager == NULL) return DEVICE_ERR_NO_DEV;
if (value > 1.0f) value = 1.0f;
if (value < -1.0f) value = -1.0f;
+ if (param->reverse){
+ value = -value;
+ }
MOTOR_RM_t *motor = MOTOR_RM_GetMotor(param);
if (motor == NULL) return DEVICE_ERR_NO_DEV;
int8_t logical_index = MOTOR_RM_GetLogicalIndex(param->id, param->module);
@@ -282,7 +291,6 @@ int8_t MOTOR_RM_Ctrl(MOTOR_RM_Param_t *param) {
default:
return DEVICE_ERR;
}
- BSP_CAN_WaitTxMailboxEmpty(param->can, 1); // 等待发送邮箱空闲
return BSP_CAN_TransmitStdDataFrame(param->can, &tx_frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
diff --git a/User/task/rc.c b/User/task/rc.c
index 36843e8..04223fe 100644
--- a/User/task/rc.c
+++ b/User/task/rc.c
@@ -50,13 +50,13 @@ void Task_rc(void *argument) {
if (DR16_WaitDmaCplt(20)) {
DR16_ParseData(&dr16);
switch (dr16.data.sw_l) {
- case CMD_SW_UP: // 上位
+ case DR16_SW_UP: // 上位
cmd_to_chassis.mode = CHASSIS_MODE_RELAX;
break;
- case CMD_SW_MID: // 中位
+ case DR16_SW_MID: // 中位
cmd_to_chassis.mode = CHASSIS_MODE_RECOVER;
break;
- case CMD_SW_DOWN: // 下位
+ case DR16_SW_DOWN: // 下位
cmd_to_chassis.mode = CHASSIS_MODE_WHELL_BALANCE;
break;
default:
From 83354623d1f56647937463979dd7393a11977193 Mon Sep 17 00:00:00 2001
From: Robofish <1683502971@qq.com>
Date: Tue, 7 Oct 2025 02:53:20 +0800
Subject: [PATCH 3/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0088?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
User/device/bmi088.c | 381 +++++++++++++++++++++++++++++++++
User/device/bmi088.h | 81 +++++++
User/device/device.h | 4 +
User/device/device_config.yaml | 8 +
User/task/config.yaml | 7 +
User/task/ctrl_gimbal.c | 5 +-
User/task/imu.c | 44 ++++
User/task/init.c | 1 +
User/task/user_task.c | 5 +
User/task/user_task.h | 8 +
10 files changed, 541 insertions(+), 3 deletions(-)
create mode 100644 User/device/bmi088.c
create mode 100644 User/device/bmi088.h
create mode 100644 User/task/imu.c
diff --git a/User/device/bmi088.c b/User/device/bmi088.c
new file mode 100644
index 0000000..0f4c154
--- /dev/null
+++ b/User/device/bmi088.c
@@ -0,0 +1,381 @@
+/*
+ BMI088 陀螺仪+加速度计传感器。
+*/
+
+/* Includes ----------------------------------------------------------------- */
+#include "bmi088.h"
+
+#include
+#include
+#include
+#include
+
+#include "bsp/time.h"
+#include "bsp/gpio.h"
+#include "bsp/spi.h"
+#include "component/user_math.h"
+
+/* USER INCLUDE BEGIN */
+
+/* USER INCLUDE END */
+
+/* Private define ----------------------------------------------------------- */
+/* Private define ----------------------------------------------------------- */
+#define BMI088_REG_ACCL_CHIP_ID (0x00)
+#define BMI088_REG_ACCL_ERR (0x02)
+#define BMI088_REG_ACCL_STATUS (0x03)
+#define BMI088_REG_ACCL_X_LSB (0x12)
+#define BMI088_REG_ACCL_X_MSB (0x13)
+#define BMI088_REG_ACCL_Y_LSB (0x14)
+#define BMI088_REG_ACCL_Y_MSB (0x15)
+#define BMI088_REG_ACCL_Z_LSB (0x16)
+#define BMI088_REG_ACCL_Z_MSB (0x17)
+#define BMI088_REG_ACCL_SENSORTIME_0 (0x18)
+#define BMI088_REG_ACCL_SENSORTIME_1 (0x19)
+#define BMI088_REG_ACCL_SENSORTIME_2 (0x1A)
+#define BMI088_REG_ACCL_INT_STAT_1 (0x1D)
+#define BMI088_REG_ACCL_TEMP_MSB (0x22)
+#define BMI088_REG_ACCL_TEMP_LSB (0x23)
+#define BMI088_REG_ACCL_CONF (0x40)
+#define BMI088_REG_ACCL_RANGE (0x41)
+#define BMI088_REG_ACCL_INT1_IO_CONF (0x53)
+#define BMI088_REG_ACCL_INT2_IO_CONF (0x54)
+#define BMI088_REG_ACCL_INT1_INT2_MAP_DATA (0x58)
+#define BMI088_REG_ACCL_SELF_TEST (0x6D)
+#define BMI088_REG_ACCL_PWR_CONF (0x7C)
+#define BMI088_REG_ACCL_PWR_CTRL (0x7D)
+#define BMI088_REG_ACCL_SOFTRESET (0x7E)
+
+#define BMI088_REG_GYRO_CHIP_ID (0x00)
+#define BMI088_REG_GYRO_X_LSB (0x02)
+#define BMI088_REG_GYRO_X_MSB (0x03)
+#define BMI088_REG_GYRO_Y_LSB (0x04)
+#define BMI088_REG_GYRO_Y_MSB (0x05)
+#define BMI088_REG_GYRO_Z_LSB (0x06)
+#define BMI088_REG_GYRO_Z_MSB (0x07)
+#define BMI088_REG_GYRO_INT_STAT_1 (0x0A)
+#define BMI088_REG_GYRO_RANGE (0x0F)
+#define BMI088_REG_GYRO_BANDWIDTH (0x10)
+#define BMI088_REG_GYRO_LPM1 (0x11)
+#define BMI088_REG_GYRO_SOFTRESET (0x14)
+#define BMI088_REG_GYRO_INT_CTRL (0x15)
+#define BMI088_REG_GYRO_INT3_INT4_IO_CONF (0x16)
+#define BMI088_REG_GYRO_INT3_INT4_IO_MAP (0x18)
+#define BMI088_REG_GYRO_SELF_TEST (0x3C)
+
+#define BMI088_CHIP_ID_ACCL (0x1E)
+#define BMI088_CHIP_ID_GYRO (0x0F)
+
+#define BMI088_LEN_RX_BUFF (19)
+/* Private macro ------------------------------------------------------------ */
+#define BMI088_ACCL_NSS_SET() \
+ BSP_GPIO_WritePin(BSP_GPIO_ACCL_CS, GPIO_PIN_SET)
+#define BMI088_ACCL_NSS_RESET() \
+ BSP_GPIO_WritePin(BSP_GPIO_ACCL_CS, GPIO_PIN_RESET)
+
+#define BMI088_GYRO_NSS_SET() \
+ BSP_GPIO_WritePin(BSP_GPIO_GYRO_CS, GPIO_PIN_SET)
+#define BMI088_GYRO_NSS_RESET() \
+ BSP_GPIO_WritePin(BSP_GPIO_GYRO_CS, GPIO_PIN_RESET)
+
+/* Private typedef ---------------------------------------------------------- */
+typedef enum {
+ BMI_ACCL,
+ BMI_GYRO,
+} BMI_Device_t;
+
+/* USER STRUCT BEGIN */
+
+/* USER STRUCT END */
+
+/* Private variables -------------------------------------------------------- */
+static uint8_t buffer[2];
+static uint8_t bmi088_rxbuf[BMI088_LEN_RX_BUFF];
+
+static osThreadId_t thread_alert;
+static bool inited = false;
+
+/* Private function -------------------------------------------------------- */
+/* USER FUNCTION BEGIN */
+
+/* USER FUNCTION END */
+
+static void BMI_WriteSingle(BMI_Device_t dv, uint8_t reg, uint8_t data) {
+ buffer[0] = (reg & 0x7f);
+ buffer[1] = data;
+
+ BSP_TIME_Delay(1);
+ switch (dv) {
+ case BMI_ACCL:
+ BMI088_ACCL_NSS_RESET();
+ break;
+
+ case BMI_GYRO:
+ BMI088_GYRO_NSS_RESET();
+ break;
+ }
+
+ BSP_SPI_Transmit(BSP_SPI_BMI088, buffer, 2u, false);
+
+ switch (dv) {
+ case BMI_ACCL:
+ BMI088_ACCL_NSS_SET();
+ break;
+
+ case BMI_GYRO:
+ BMI088_GYRO_NSS_SET();
+ break;
+ }
+}
+
+static uint8_t BMI_ReadSingle(BMI_Device_t dv, uint8_t reg) {
+ BSP_TIME_Delay(1);
+ switch (dv) {
+ case BMI_ACCL:
+ BMI088_ACCL_NSS_RESET();
+ break;
+
+ case BMI_GYRO:
+ BMI088_GYRO_NSS_RESET();
+ break;
+ }
+ buffer[0] = (uint8_t)(reg | 0x80);
+ BSP_SPI_Transmit(BSP_SPI_BMI088, buffer, 1u, false);
+ BSP_SPI_Receive(BSP_SPI_BMI088, buffer, 2u, false);
+
+ switch (dv) {
+ case BMI_ACCL:
+ BMI088_ACCL_NSS_SET();
+ return buffer[1];
+
+ case BMI_GYRO:
+ BMI088_GYRO_NSS_SET();
+ return buffer[0];
+ }
+}
+
+static void BMI_Read(BMI_Device_t dv, uint8_t reg, uint8_t *data, uint8_t len) {
+ if (data == NULL) return;
+
+ switch (dv) {
+ case BMI_ACCL:
+ BMI088_ACCL_NSS_RESET();
+ break;
+
+ case BMI_GYRO:
+ BMI088_GYRO_NSS_RESET();
+ break;
+ }
+ buffer[0] = (uint8_t)(reg | 0x80);
+ BSP_SPI_Transmit(BSP_SPI_BMI088, buffer, 1u, false);
+ BSP_SPI_Receive(BSP_SPI_BMI088, data, len, true);
+}
+
+static void BMI088_RxCpltCallback(void) {
+ if (BSP_GPIO_ReadPin(BSP_GPIO_ACCL_CS) == GPIO_PIN_RESET) {
+ BMI088_ACCL_NSS_SET();
+ osThreadFlagsSet(thread_alert, SIGNAL_BMI088_ACCL_RAW_REDY);
+ }
+ if (BSP_GPIO_ReadPin(BSP_GPIO_GYRO_CS) == GPIO_PIN_RESET) {
+ BMI088_GYRO_NSS_SET();
+ osThreadFlagsSet(thread_alert, SIGNAL_BMI088_GYRO_RAW_REDY);
+ }
+}
+
+static void BMI088_AcclIntCallback(void) {
+ osThreadFlagsSet(thread_alert, SIGNAL_BMI088_ACCL_NEW_DATA);
+}
+
+static void BMI088_GyroIntCallback(void) {
+ osThreadFlagsSet(thread_alert, SIGNAL_BMI088_GYRO_NEW_DATA);
+}
+
+/* Exported functions ------------------------------------------------------- */
+int8_t BMI088_Init(BMI088_t *bmi088, const BMI088_Cali_t *cali) {
+ if (bmi088 == NULL) return DEVICE_ERR_NULL;
+ if (cali == NULL) return DEVICE_ERR_NULL;
+ if (inited) return DEVICE_ERR_INITED;
+ if ((thread_alert = osThreadGetId()) == NULL) return DEVICE_ERR_NULL;
+
+ bmi088->cali = cali;
+
+ BMI_WriteSingle(BMI_ACCL, BMI088_REG_ACCL_SOFTRESET, 0xB6);
+ BMI_WriteSingle(BMI_GYRO, BMI088_REG_GYRO_SOFTRESET, 0xB6);
+ BSP_TIME_Delay(30);
+
+ /* Switch accl to SPI mode. */
+ BMI_ReadSingle(BMI_ACCL, BMI088_CHIP_ID_ACCL);
+
+ if (BMI_ReadSingle(BMI_ACCL, BMI088_REG_ACCL_CHIP_ID) != BMI088_CHIP_ID_ACCL)
+ return DEVICE_ERR_NO_DEV;
+
+ if (BMI_ReadSingle(BMI_GYRO, BMI088_REG_GYRO_CHIP_ID) != BMI088_CHIP_ID_GYRO)
+ return DEVICE_ERR_NO_DEV;
+
+ BSP_GPIO_DisableIRQ(BSP_GPIO_ACCL_INT);
+ BSP_GPIO_DisableIRQ(BSP_GPIO_GYRO_INT);
+
+ BSP_SPI_RegisterCallback(BSP_SPI_BMI088, BSP_SPI_RX_CPLT_CB,
+ BMI088_RxCpltCallback);
+ BSP_GPIO_RegisterCallback(BSP_GPIO_ACCL_INT, BMI088_AcclIntCallback);
+ BSP_GPIO_RegisterCallback(BSP_GPIO_GYRO_INT, BMI088_GyroIntCallback);
+
+ /* Accl init. */
+ /* Filter setting: Normal. */
+ /* ODR: 0xAB: 800Hz. 0xAA: 400Hz. 0xA9: 200Hz. 0xA8: 100Hz. 0xA6: 25Hz. */
+ BMI_WriteSingle(BMI_ACCL, BMI088_REG_ACCL_CONF, 0xAA);
+
+ /* 0x00: +-3G. 0x01: +-6G. 0x02: +-12G. 0x03: +-24G. */
+ BMI_WriteSingle(BMI_ACCL, BMI088_REG_ACCL_RANGE, 0x01);
+
+ /* INT1 as output. Push-pull. Active low. Output. */
+ BMI_WriteSingle(BMI_ACCL, BMI088_REG_ACCL_INT1_IO_CONF, 0x08);
+
+ /* Map data ready interrupt to INT1. */
+ BMI_WriteSingle(BMI_ACCL, BMI088_REG_ACCL_INT1_INT2_MAP_DATA, 0x04);
+
+ /* Turn on accl. Now we can read data. */
+ BMI_WriteSingle(BMI_ACCL, BMI088_REG_ACCL_PWR_CTRL, 0x04);
+ BSP_TIME_Delay(50);
+
+ /* Gyro init. */
+ /* 0x00: +-2000. 0x01: +-1000. 0x02: +-500. 0x03: +-250. 0x04: +-125. */
+ BMI_WriteSingle(BMI_GYRO, BMI088_REG_GYRO_RANGE, 0x01);
+
+ /* Filter bw: 47Hz. */
+ /* ODR: 0x02: 1000Hz. 0x03: 400Hz. 0x06: 200Hz. 0x07: 100Hz. */
+ BMI_WriteSingle(BMI_GYRO, BMI088_REG_GYRO_BANDWIDTH, 0x03);
+
+ /* INT3 and INT4 as output. Push-pull. Active low. */
+ BMI_WriteSingle(BMI_GYRO, BMI088_REG_GYRO_INT3_INT4_IO_CONF, 0x00);
+
+ /* Map data ready interrupt to INT3. */
+ BMI_WriteSingle(BMI_GYRO, BMI088_REG_GYRO_INT3_INT4_IO_MAP, 0x01);
+
+ /* Enable new data interrupt. */
+ BMI_WriteSingle(BMI_GYRO, BMI088_REG_GYRO_INT_CTRL, 0x80);
+
+ BSP_TIME_Delay(10);
+
+ inited = true;
+
+ BSP_GPIO_EnableIRQ(BSP_GPIO_ACCL_INT);
+ BSP_GPIO_EnableIRQ(BSP_GPIO_GYRO_INT);
+ return DEVICE_OK;
+}
+
+bool BMI088_GyroStable(AHRS_Gyro_t *gyro) {
+ return ((gyro->x < 0.03f) && (gyro->y < 0.03f) && (gyro->z < 0.03f));
+}
+
+uint32_t BMI088_WaitNew() {
+ return osThreadFlagsWait(
+ SIGNAL_BMI088_ACCL_NEW_DATA | SIGNAL_BMI088_GYRO_NEW_DATA, osFlagsWaitAll,
+ osWaitForever);
+}
+
+int8_t BMI088_AcclStartDmaRecv() {
+ BMI_Read(BMI_ACCL, BMI088_REG_ACCL_X_LSB, bmi088_rxbuf, BMI088_LEN_RX_BUFF);
+ return DEVICE_OK;
+}
+
+uint32_t BMI088_AcclWaitDmaCplt() {
+ return osThreadFlagsWait(SIGNAL_BMI088_ACCL_RAW_REDY, osFlagsWaitAll,
+ osWaitForever);
+}
+
+int8_t BMI088_GyroStartDmaRecv() {
+ BMI_Read(BMI_GYRO, BMI088_REG_GYRO_X_LSB, bmi088_rxbuf + 7, 6u);
+ return DEVICE_OK;
+}
+
+uint32_t BMI088_GyroWaitDmaCplt() {
+ return osThreadFlagsWait(SIGNAL_BMI088_GYRO_RAW_REDY, osFlagsWaitAll,
+ osWaitForever);
+}
+
+int8_t BMI088_ParseAccl(BMI088_t *bmi088) {
+ if (bmi088 == NULL) return DEVICE_ERR_NULL;
+
+#if 1
+ int16_t raw_x, raw_y, raw_z;
+ memcpy(&raw_x, bmi088_rxbuf + 1, sizeof(raw_x));
+ memcpy(&raw_y, bmi088_rxbuf + 3, sizeof(raw_y));
+ memcpy(&raw_z, bmi088_rxbuf + 5, sizeof(raw_z));
+
+ bmi088->accl.x = (float)raw_x;
+ bmi088->accl.y = (float)raw_y;
+ bmi088->accl.z = (float)raw_z;
+
+#else
+ const int16_t *praw_x = (int16_t *)(bmi088_rxbuf + 1);
+ const int16_t *praw_y = (int16_t *)(bmi088_rxbuf + 3);
+ const int16_t *praw_z = (int16_t *)(bmi088_rxbuf + 5);
+
+ bmi088->accl.x = (float)*praw_x;
+ bmi088->accl.y = (float)*praw_y;
+ bmi088->accl.z = (float)*praw_z;
+
+#endif
+
+ /* 3G: 10920. 6G: 5460. 12G: 2730. 24G: 1365. */
+ bmi088->accl.x /= 5460.0f;
+ bmi088->accl.y /= 5460.0f;
+ bmi088->accl.z /= 5460.0f;
+
+ int16_t raw_temp =
+ (uint16_t)((bmi088_rxbuf[17] << 3) | (bmi088_rxbuf[18] >> 5));
+
+ if (raw_temp > 1023) raw_temp -= 2048;
+
+ bmi088->temp = (float)raw_temp * 0.125f + 23.0f;
+
+ return DEVICE_OK;
+}
+
+int8_t BMI088_ParseGyro(BMI088_t *bmi088) {
+ if (bmi088 == NULL) return DEVICE_ERR_NULL;
+
+#if 1
+ /* Gyroscope imu_raw -> degrees/sec -> radians/sec */
+ int16_t raw_x, raw_y, raw_z;
+ memcpy(&raw_x, bmi088_rxbuf + 7, sizeof(raw_x));
+ memcpy(&raw_y, bmi088_rxbuf + 9, sizeof(raw_y));
+ memcpy(&raw_z, bmi088_rxbuf + 11, sizeof(raw_z));
+
+ bmi088->gyro.x = (float)raw_x;
+ bmi088->gyro.y = (float)raw_y;
+ bmi088->gyro.z = (float)raw_z;
+
+#else
+ /* Gyroscope imu_raw -> degrees/sec -> radians/sec */
+ const int16_t *raw_x = (int16_t *)(bmi088_rxbuf + 7);
+ const int16_t *raw_y = (int16_t *)(bmi088_rxbuf + 9);
+ const int16_t *raw_z = (int16_t *)(bmi088_rxbuf + 11);
+
+ bmi088->gyro.x = (float)*raw_x;
+ bmi088->gyro.y = (float)*raw_y;
+ bmi088->gyro.z = (float)*raw_z;
+#endif
+
+ /* FS125: 262.144. FS250: 131.072. FS500: 65.536. FS1000: 32.768.
+ * FS2000: 16.384.*/
+ bmi088->gyro.x /= 32.768f;
+ bmi088->gyro.y /= 32.768f;
+ bmi088->gyro.z /= 32.768f;
+
+ bmi088->gyro.x *= M_DEG2RAD_MULT;
+ bmi088->gyro.y *= M_DEG2RAD_MULT;
+ bmi088->gyro.z *= M_DEG2RAD_MULT;
+
+ bmi088->gyro.x -= bmi088->cali->gyro_offset.x;
+ bmi088->gyro.y -= bmi088->cali->gyro_offset.y;
+ bmi088->gyro.z -= bmi088->cali->gyro_offset.z;
+
+ return DEVICE_ERR_NULL;
+}
+
+float BMI088_GetUpdateFreq(BMI088_t *bmi088) {
+ (void)bmi088;
+ return 400.0f;
+}
diff --git a/User/device/bmi088.h b/User/device/bmi088.h
new file mode 100644
index 0000000..eb44e0c
--- /dev/null
+++ b/User/device/bmi088.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ----------------------------------------------------------------- */
+#include
+#include
+
+#include "component/ahrs.h"
+#include "device/device.h"
+
+/* USER INCLUDE BEGIN */
+
+/* USER INCLUDE END */
+
+/* USER DEFINE BEGIN */
+
+/* USER DEFINE END */
+
+/* Exported constants ------------------------------------------------------- */
+/* Exported macro ----------------------------------------------------------- */
+/* Exported types ----------------------------------------------------------- */
+typedef struct {
+ struct {
+ float x;
+ float y;
+ float z;
+ } gyro_offset; /* 陀螺仪偏置 */
+} BMI088_Cali_t; /* BMI088校准数据 */
+
+typedef struct {
+ DEVICE_Header_t header;
+ AHRS_Accl_t accl;
+ AHRS_Gyro_t gyro;
+
+ float temp; /* 温度 */
+
+ const BMI088_Cali_t *cali;
+} BMI088_t;
+
+/* USER STRUCT BEGIN */
+
+/* USER STRUCT END */
+
+/* Exported functions prototypes -------------------------------------------- */
+int8_t BMI088_Init(BMI088_t *bmi088, const BMI088_Cali_t *cali);
+int8_t BMI088_Restart(void);
+
+bool BMI088_GyroStable(AHRS_Gyro_t *gyro);
+
+/* Sensor use right-handed coordinate system. */
+/*
+ x < R(logo)
+ y
+ UP is z
+ All implementation should follow this rule.
+ */
+uint32_t BMI088_WaitNew();
+
+/*
+ BMI088的Accl和Gyro共用同一个DMA通道,所以一次只能读一个传感器。
+ 即BMI088_AcclStartDmaRecv() 和 BMI088_AcclWaitDmaCplt() 中间不能
+ 出现 BMI088_GyroStartDmaRecv()。
+*/
+int8_t BMI088_AcclStartDmaRecv();
+uint32_t BMI088_AcclWaitDmaCplt();
+int8_t BMI088_GyroStartDmaRecv();
+uint32_t BMI088_GyroWaitDmaCplt();
+int8_t BMI088_ParseAccl(BMI088_t *bmi088);
+int8_t BMI088_ParseGyro(BMI088_t *bmi088);
+float BMI088_GetUpdateFreq(BMI088_t *bmi088);
+
+/* USER FUNCTION BEGIN */
+
+/* USER FUNCTION END */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/User/device/device.h b/User/device/device.h
index 9230af5..18ffc73 100644
--- a/User/device/device.h
+++ b/User/device/device.h
@@ -23,6 +23,10 @@ extern "C" {
/* AUTO GENERATED SIGNALS BEGIN */
#define SIGNAL_DR16_RAW_REDY (1u << 0)
+#define SIGNAL_BMI088_ACCL_RAW_REDY (1u << 1)
+#define SIGNAL_BMI088_GYRO_RAW_REDY (1u << 2)
+#define SIGNAL_BMI088_ACCL_NEW_DATA (1u << 3)
+#define SIGNAL_BMI088_GYRO_NEW_DATA (1u << 4)
/* AUTO GENERATED SIGNALS END */
/* USER SIGNALS BEGIN */
diff --git a/User/device/device_config.yaml b/User/device/device_config.yaml
index 70844c0..7aaee45 100644
--- a/User/device/device_config.yaml
+++ b/User/device/device_config.yaml
@@ -1,3 +1,11 @@
+bmi088:
+ bsp_config:
+ BSP_GPIO_ACCL_CS: BSP_GPIO_ACCL_CS
+ BSP_GPIO_ACCL_INT: BSP_GPIO_ACCL_INT
+ BSP_GPIO_GYRO_CS: BSP_GPIO_GYRO_CS
+ BSP_GPIO_GYRO_INT: BSP_GPIO_GYRO_INT
+ BSP_SPI_BMI088: BSP_SPI_BMI088
+ enabled: true
buzzer:
bsp_config:
BSP_PWM_BUZZER: BSP_PWM_TIM8_CH1
diff --git a/User/task/config.yaml b/User/task/config.yaml
index 5d60486..9a45577 100644
--- a/User/task/config.yaml
+++ b/User/task/config.yaml
@@ -33,3 +33,10 @@
function: Task_ctrl_gimbal
name: ctrl_gimbal
stack: 256
+- delay: 0
+ description: ''
+ freq_control: true
+ frequency: 500.0
+ function: Task_imu
+ name: imu
+ stack: 256
diff --git a/User/task/ctrl_gimbal.c b/User/task/ctrl_gimbal.c
index 8054f87..f533078 100644
--- a/User/task/ctrl_gimbal.c
+++ b/User/task/ctrl_gimbal.c
@@ -4,7 +4,6 @@
*/
/* Includes ----------------------------------------------------------------- */
-#include "device/motor_rm.h"
#include "task/user_task.h"
/* USER INCLUDE BEGIN */
#include "bsp/can.h"
@@ -75,9 +74,9 @@ void Task_ctrl_gimbal(void *argument) {
uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
/* USER CODE INIT BEGIN */
- BSP_CAN_Init();
- // MOTOR_DM_Register(&dm_4310_param);
+ /* USER CODE INIT END */
+
while (1) {
tick += delay_tick; /* 计算下一个唤醒时刻 */
/* USER CODE BEGIN */
diff --git a/User/task/imu.c b/User/task/imu.c
new file mode 100644
index 0000000..25ac9de
--- /dev/null
+++ b/User/task/imu.c
@@ -0,0 +1,44 @@
+/*
+ imu Task
+
+*/
+
+/* Includes ----------------------------------------------------------------- */
+#include "task/user_task.h"
+/* USER INCLUDE BEGIN */
+
+/* USER INCLUDE END */
+
+/* Private typedef ---------------------------------------------------------- */
+/* Private define ----------------------------------------------------------- */
+/* Private macro ------------------------------------------------------------ */
+/* Private variables -------------------------------------------------------- */
+/* USER STRUCT BEGIN */
+
+/* USER STRUCT END */
+
+/* Private function --------------------------------------------------------- */
+/* Exported functions ------------------------------------------------------- */
+void Task_imu(void *argument) {
+ (void)argument; /* 未使用argument,消除警告 */
+
+
+ /* 计算任务运行到指定频率需要等待的tick数 */
+ const uint32_t delay_tick = osKernelGetTickFreq() / IMU_FREQ;
+
+ osDelay(IMU_INIT_DELAY); /* 延时一段时间再开启任务 */
+
+ uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
+ /* USER CODE INIT BEGIN */
+
+ /* USER CODE INIT END */
+
+ while (1) {
+ tick += delay_tick; /* 计算下一个唤醒时刻 */
+ /* USER CODE BEGIN */
+
+ /* USER CODE END */
+ osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */
+ }
+
+}
\ No newline at end of file
diff --git a/User/task/init.c b/User/task/init.c
index f41b86a..c641fd8 100644
--- a/User/task/init.c
+++ b/User/task/init.c
@@ -37,6 +37,7 @@ void Task_Init(void *argument) {
task_runtime.thread.atti_esti = osThreadNew(Task_atti_esti, NULL, &attr_atti_esti);
task_runtime.thread.ctrl_chassis = osThreadNew(Task_ctrl_chassis, NULL, &attr_ctrl_chassis);
task_runtime.thread.ctrl_gimbal = osThreadNew(Task_ctrl_gimbal, NULL, &attr_ctrl_gimbal);
+ task_runtime.thread.imu = osThreadNew(Task_imu, NULL, &attr_imu);
// 创建消息队列
/* USER MESSAGE BEGIN */
diff --git a/User/task/user_task.c b/User/task/user_task.c
index 49fe884..4e530ba 100644
--- a/User/task/user_task.c
+++ b/User/task/user_task.c
@@ -33,4 +33,9 @@ const osThreadAttr_t attr_ctrl_gimbal = {
.name = "ctrl_gimbal",
.priority = osPriorityNormal,
.stack_size = 256 * 4,
+};
+const osThreadAttr_t attr_imu = {
+ .name = "imu",
+ .priority = osPriorityNormal,
+ .stack_size = 256 * 4,
};
\ No newline at end of file
diff --git a/User/task/user_task.h b/User/task/user_task.h
index c02317c..8701a74 100644
--- a/User/task/user_task.h
+++ b/User/task/user_task.h
@@ -18,6 +18,7 @@ extern "C" {
#define ATTI_ESTI_FREQ (1000.0)
#define CTRL_CHASSIS_FREQ (500.0)
#define CTRL_GIMBAL_FREQ (500.0)
+#define IMU_FREQ (500.0)
/* 任务初始化延时ms */
#define TASK_INIT_DELAY (100u)
@@ -26,6 +27,7 @@ extern "C" {
#define ATTI_ESTI_INIT_DELAY (0)
#define CTRL_CHASSIS_INIT_DELAY (500)
#define CTRL_GIMBAL_INIT_DELAY (0)
+#define IMU_INIT_DELAY (0)
/* Exported defines --------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
@@ -40,6 +42,7 @@ typedef struct {
osThreadId_t atti_esti;
osThreadId_t ctrl_chassis;
osThreadId_t ctrl_gimbal;
+ osThreadId_t imu;
} thread;
/* USER MESSAGE BEGIN */
@@ -70,6 +73,7 @@ typedef struct {
UBaseType_t atti_esti;
UBaseType_t ctrl_chassis;
UBaseType_t ctrl_gimbal;
+ UBaseType_t imu;
} stack_water_mark;
/* 各任务运行频率 */
@@ -79,6 +83,7 @@ typedef struct {
float atti_esti;
float ctrl_chassis;
float ctrl_gimbal;
+ float imu;
} freq;
/* 任务最近运行时间 */
@@ -88,6 +93,7 @@ typedef struct {
float atti_esti;
float ctrl_chassis;
float ctrl_gimbal;
+ float imu;
} last_up_time;
} Task_Runtime_t;
@@ -102,6 +108,7 @@ extern const osThreadAttr_t attr_rc;
extern const osThreadAttr_t attr_atti_esti;
extern const osThreadAttr_t attr_ctrl_chassis;
extern const osThreadAttr_t attr_ctrl_gimbal;
+extern const osThreadAttr_t attr_imu;
/* 任务函数声明 */
void Task_Init(void *argument);
@@ -110,6 +117,7 @@ void Task_rc(void *argument);
void Task_atti_esti(void *argument);
void Task_ctrl_chassis(void *argument);
void Task_ctrl_gimbal(void *argument);
+void Task_imu(void *argument);
#ifdef __cplusplus
}
From 489415aa3437c22aab8cad3864ec37c275c9f2e5 Mon Sep 17 00:00:00 2001
From: Robofish <1683502971@qq.com>
Date: Tue, 7 Oct 2025 03:11:45 +0800
Subject: [PATCH 4/4] =?UTF-8?q?=E7=BA=A0=E6=AD=A3=E9=99=80=E8=9E=BA?=
=?UTF-8?q?=E4=BB=AA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
CMakeLists.txt | 2 +
User/task/imu.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 135 insertions(+), 3 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 750eaea..e025a25 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -67,6 +67,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
User/component/vmc.c
# User/device sources
+ User/device/bmi088.c
User/device/buzzer.c
User/device/dm_imu.c
User/device/dr16.c
@@ -86,6 +87,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
User/task/blink.c
User/task/ctrl_chassis.c
User/task/ctrl_gimbal.c
+ User/task/imu.c
User/task/init.c
User/task/rc.c
User/task/user_task.c
diff --git a/User/task/imu.c b/User/task/imu.c
index 25ac9de..24c2ed0 100644
--- a/User/task/imu.c
+++ b/User/task/imu.c
@@ -6,7 +6,13 @@
/* Includes ----------------------------------------------------------------- */
#include "task/user_task.h"
/* USER INCLUDE BEGIN */
-
+#include "bsp/mm.h"
+#include "bsp/pwm.h"
+#include "bsp/gpio.h"
+#include "component/ahrs.h"
+#include "component/pid.h"
+#include "device/bmi088.h"
+#include "task/user_task.h"
/* USER INCLUDE END */
/* Private typedef ---------------------------------------------------------- */
@@ -14,7 +20,54 @@
/* Private macro ------------------------------------------------------------ */
/* Private variables -------------------------------------------------------- */
/* USER STRUCT BEGIN */
+BMI088_t bmi088;
+AHRS_t gimbal_ahrs;
+AHRS_Magn_t magn;
+AHRS_Eulr_t eulr_to_send;
+
+KPID_t imu_temp_ctrl_pid;
+
+BMI088_Cali_t cali_bmi088= {
+ .gyro_offset = {0.00379243772f,0.00133061118f,-0.00154866849f},
+};
+ AHRS_Accl_t accl_modified;
+ AHRS_Gyro_t gyro_modified;
+ AHRS_Eulr_t eulr_modified;
+
+static const KPID_Params_t imu_temp_ctrl_pid_param = {
+ .k = 0.2f,
+ .p = 1.0f,
+ .i = 0.01f,
+ .d = 0.0f,
+ .i_limit = 1.0f,
+ .out_limit = 1.0f,
+};
+
+/* 校准相关变量 */
+typedef enum {
+ CALIB_IDLE, // 空闲状态
+ CALIB_RUNNING, // 正在校准
+ CALIB_DONE // 校准完成
+} CalibState_t;
+
+static CalibState_t calib_state = CALIB_IDLE;
+static uint16_t calib_count = 0;
+static struct {
+ float x_sum;
+ float y_sum;
+ float z_sum;
+} gyro_sum = {0.00341676874f, 0.000505680335f, -0.00134522165f};
+static void start_gyro_calibration(void) {
+ if (calib_state == CALIB_IDLE) {
+ calib_state = CALIB_RUNNING;
+ calib_count = 0;
+ gyro_sum.x_sum = 0.0f;
+ gyro_sum.y_sum = 0.0f;
+ gyro_sum.z_sum = 0.0f;
+ }
+}
+#define CALIB_SAMPLES 5000 // 校准采样数量
/* USER STRUCT END */
/* Private function --------------------------------------------------------- */
@@ -30,15 +83,92 @@ void Task_imu(void *argument) {
uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
/* USER CODE INIT BEGIN */
-
+ BMI088_Init(&bmi088,&cali_bmi088);
+ AHRS_Init(&gimbal_ahrs, &magn, BMI088_GetUpdateFreq(&bmi088));
+ PID_Init(&imu_temp_ctrl_pid, KPID_MODE_NO_D,
+ 1.0f / BMI088_GetUpdateFreq(&bmi088), &imu_temp_ctrl_pid_param);
+ BSP_PWM_Start(BSP_PWM_IMU_HEAT_PWM);
+
+ /* 注册按钮回调函数并启用中断 */
+ BSP_GPIO_RegisterCallback(BSP_GPIO_USER_KEY, start_gyro_calibration);
+ BSP_GPIO_EnableIRQ(BSP_GPIO_USER_KEY);
/* USER CODE INIT END */
while (1) {
tick += delay_tick; /* 计算下一个唤醒时刻 */
/* USER CODE BEGIN */
+ BMI088_WaitNew();
+ BMI088_AcclStartDmaRecv();
+ BMI088_AcclWaitDmaCplt();
+
+ BMI088_GyroStartDmaRecv();
+ BMI088_GyroWaitDmaCplt();
+
+ /* 锁住RTOS内核防止数据解析过程中断,造成错误 */
+ osKernelLock();
+ /* 接收完所有数据后,把数据从原始字节加工成方便计算的数据 */
+ BMI088_ParseAccl(&bmi088);
+ BMI088_ParseGyro(&bmi088);
+ // IST8310_Parse(&ist8310);
+
+ /* 陀螺仪校准处理 */
+ if (calib_state == CALIB_RUNNING) {
+ /* 累加陀螺仪数据用于计算零偏 */
+ gyro_sum.x_sum += bmi088.gyro.x;
+ gyro_sum.y_sum += bmi088.gyro.y;
+ gyro_sum.z_sum += bmi088.gyro.z;
+ calib_count++;
+
+ /* 达到采样数量后计算平均值并更新零偏 */
+ if (calib_count >= CALIB_SAMPLES) {
+ /* 计算平均值作为零偏 */
+ cali_bmi088.gyro_offset.x = gyro_sum.x_sum / CALIB_SAMPLES;
+ cali_bmi088.gyro_offset.y = gyro_sum.y_sum / CALIB_SAMPLES;
+ cali_bmi088.gyro_offset.z = gyro_sum.z_sum / CALIB_SAMPLES;
+
+ /* 校准完成,重置为空闲状态以便下次校准 */
+ calib_state = CALIB_IDLE;
+
+ /* 重新初始化BMI088以应用新的校准数据 */
+ BMI088_Init(&bmi088, &cali_bmi088);
+ AHRS_Init(&gimbal_ahrs, &magn, BMI088_GetUpdateFreq(&bmi088));
+ }
+ }
+
+ /* 只有在非校准状态下才进行正常的姿态解析 */
+ if (calib_state != CALIB_RUNNING) {
+ /* 根据设备接收到的数据进行姿态解析 */
+ AHRS_Update(&gimbal_ahrs, &bmi088.accl, &bmi088.gyro, &magn);
+
+ /* 根据解析出来的四元数计算欧拉角 */
+ AHRS_GetEulr(&eulr_to_send, &gimbal_ahrs);
+ }
+
+ osKernelUnlock();
+
+ /* 创建修改后的数据副本用于发送到消息队列 */
+
+ /* 加速度数据:x和y互换,y取负值,全部乘10 */
+ accl_modified.x = bmi088.accl.y * 10.0f;
+ accl_modified.y = -bmi088.accl.x * 10.0f;
+ accl_modified.z = bmi088.accl.z * 10.0f;
+
+
+ /* 陀螺仪数据:x和y互换,y取负值 */
+ gyro_modified.x = bmi088.gyro.y;
+ gyro_modified.y = -bmi088.gyro.x;
+ gyro_modified.z = bmi088.gyro.z;
+
+ /* 欧拉角数据:roll和pitch互换 */
+ eulr_modified.yaw = eulr_to_send.yaw;
+ eulr_modified.pit = -eulr_to_send.pit;
+ eulr_modified.rol = eulr_to_send.rol;
+
+ BSP_PWM_SetComp(BSP_PWM_IMU_HEAT_PWM, PID_Calc(&imu_temp_ctrl_pid, 50.0f, bmi088.temp, 0.0f, 0.0f));
/* USER CODE END */
osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */
}
-}
\ No newline at end of file
+}
+