modified: MDK-ARM/.vscode/keil-assistant.log

modified:   User/task/ai.c
	modified:   User/task/atti_esti.c
This commit is contained in:
zzzhkgs@gmail.com 2026-03-12 18:39:41 +08:00
parent ad46170768
commit 11ee01e9f9
3 changed files with 188 additions and 27 deletions

View File

@ -4,3 +4,11 @@
[info] Log at : 2026/3/8|18:16:24|GMT+0800
[info] Log at : 2026/3/9|19:40:56|GMT+0800
[info] Log at : 2026/3/10|14:01:43|GMT+0800
[info] Log at : 2026/3/11|12:22:50|GMT+0800
[info] Log at : 2026/3/12|15:59:31|GMT+0800

View File

@ -1,44 +1,190 @@
/*
ai Task
1. 姿 (atti_esti)
2. (gimbal)(shoot)
3.
*/
/* Includes ----------------------------------------------------------------- */
#include "task/user_task.h"
/* USER INCLUDE BEGIN */
#include <stdint.h>
#include <string.h>
#include "bsp/uart.h"
#include "component/crc16.h"
#include "module/gimbal.h" /* 引用云台结构体获取反馈 */
#include "module/shoot.h" /* 引用发射机构结构体获取反馈 */
/* USER INCLUDE END */
/* Private typedef ---------------------------------------------------------- */
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
#define ID_MCU (0xC4) // MCU 数据包 (发送)
#define ID_REF (0xA8) // 裁判系统数据包 (发送)
#define ID_AI (0xB5) // AI 控制数据包 (接收)
// MCU 数据结构MCU -> 上位机)
typedef struct __attribute__((packed)) {
uint8_t mode; // 0: 空闲, 1: 自瞄, 2: 小符, 3: 大符
float q[4]; // 四元数 wxyz 顺序
float yaw; // 偏航角
float yaw_vel; // 偏航角速度
float pitch; // 俯仰角
float pitch_vel; // 俯仰角速度
float bullet_speed; // 弹速
uint16_t bullet_count; // 子弹累计发送次数
} DataMCU_t;
typedef struct __attribute__((packed)) {
uint8_t id; // 数据包 ID: 0xC4
DataMCU_t data;
uint16_t crc16;
} PackageMCU_t;
// AI 控制数据结构(上位机 -> MCU
typedef struct __attribute__((packed)) {
uint8_t mode; // 0: 不控制, 1: 控制云台但不开火, 2: 控制云台且开火
float yaw; // 目标偏航角/偏移量
float yaw_vel; // 偏航角速度
float yaw_acc; // 偏航角加速度
float pitch; // 目标俯仰角/偏移量
float pitch_vel; // 俯仰角速度
float pitch_acc; // 俯仰角加速度
float vx; // X 方向速度
float vy; // Y 方向速度
float wz; // Z 方向角速度
uint8_t reserved; // 预留字段
} DataAI_t;
typedef struct __attribute__((packed)) {
uint8_t id; // 数据包 ID: 0xB5
DataAI_t data;
uint16_t crc16;
} PackageAI_t;
/* Private variables -------------------------------------------------------- */
/* USER STRUCT BEGIN */
static uint8_t ai_rx_buf[sizeof(PackageAI_t)];
static PackageAI_t ai_rx_data;
/* USER STRUCT END */
/* 声明外部全局变量,用于直接获取高频反馈数据 */
extern Gimbal_t gimbal;
extern Shoot_t shoot;
/* USER FUNCTION BEGIN */
/**
* @brief AI串口接收完成回调函数
* @note ID与CRC16校验DMA接收
*/
static void AI_RxCpltCallback(void) {
if (ai_rx_buf[0] == ID_AI) {
/* 校验 CRC确保数据包完整 */
if (CRC16_Verify(ai_rx_buf, sizeof(PackageAI_t))) {
memcpy(&ai_rx_data, ai_rx_buf, sizeof(PackageAI_t));
Gimbal_CMD_t ai_gimbal_cmd;
Shoot_CMD_t ai_shoot_cmd;
/* 1. 解析指令并生成系统控制信号 */
switch (ai_rx_data.data.mode) {
case 0: /* 不控制 */
ai_gimbal_cmd.mode = GIMBAL_MODE_RELAX;
// ai_shoot_cmd.mode = SHOOT_MODE_STOP; /* 需根据实际枚举名称修改 */
break;
case 1: /* 控制云台但不开火 */
ai_gimbal_cmd.mode = GIMBAL_MODE_ABSOLUTE;
// ai_shoot_cmd.mode = SHOOT_MODE_READY; /* 摩擦轮开启,不拨弹 */
break;
case 2: /* 控制云台且开火 */
ai_gimbal_cmd.mode = GIMBAL_MODE_ABSOLUTE;
// ai_shoot_cmd.mode = SHOOT_MODE_FIRE; /* 摩擦轮开启,拨弹 */
break;
default:
ai_gimbal_cmd.mode = GIMBAL_MODE_RELAX;
break;
}
/* 云台位姿控制信号赋值 (假设协议中发下来的 yaw/pitch 直接作为速度增量) */
ai_gimbal_cmd.delta_yaw = ai_rx_data.data.yaw;
ai_gimbal_cmd.delta_pit = ai_rx_data.data.pitch;
/* 2. 将命令压入控制队列(非阻塞) */
osMessageQueuePut(msgq.gimbal.cmd, &ai_gimbal_cmd, 0, 0);
// 注意:若 ctrl_shoot.c 中使用的是 task_runtime.msgq.shoot.shoot_cmd
// 则替换为该全局结构体的队列句柄。此处采用常规 msgq 定义示范:
osMessageQueuePut(msgq.shoot.shoot_cmd, &ai_shoot_cmd, 0, 0);
}
}
/* 重新开启DMA定长接收 */
BSP_UART_Receive(BSP_UART_AI, ai_rx_buf, sizeof(PackageAI_t), true);
}
/**
* @brief MCU状态数据
*/
static void AI_Send_MCU_Data(void) {
PackageMCU_t tx_pkg;
quat_t current_quat;
tx_pkg.id = ID_MCU;
memset(&tx_pkg.data, 0, sizeof(DataMCU_t));
/* 1. 获取四元数 (从消息队列读取) */
if (osMessageQueueGet(msgq.ai.quat, &current_quat, NULL, 0) == osOK) {
tx_pkg.data.q[0] = current_quat.q0;
tx_pkg.data.q[1] = current_quat.q1;
tx_pkg.data.q[2] = current_quat.q2;
tx_pkg.data.q[3] = current_quat.q3;
}
/* 2. 获取云台状态 (直接读取全局 gimbal 结构体) */
tx_pkg.data.yaw = gimbal.feedback.imu.eulr.yaw;
tx_pkg.data.yaw_vel = gimbal.feedback.imu.gyro.z;
tx_pkg.data.pitch = gimbal.feedback.imu.eulr.rol; /* 电控中 Pitch 对应 IMU 的 Rol */
tx_pkg.data.pitch_vel = gimbal.feedback.imu.gyro.y;
/* 3. 获取发射机构与模式状态 (直接读取全局 shoot 结构体) */
/* 模式回传,取值为实际枚举映射 */
tx_pkg.data.mode = (uint8_t)shoot.mode;
/* 弹速反馈:由于硬件可能无法直接测弹速,暂用摩擦轮目标转速或估算转速代替。
*/
tx_pkg.data.bullet_speed = shoot.target_variable.target_rpm;
/* 弹量统计:如有独立计数变量,可进行赋值 */
// tx_pkg.data.bullet_count = shoot.feedback.xxxx;
/* 4. 计算 CRC16扣除末尾 2 字节) */
tx_pkg.crc16 = CRC16_Calc((const uint8_t *)&tx_pkg, sizeof(PackageMCU_t) - 2, CRC16_INIT);
/* 5. 通过 DMA 发送至上位机 */
BSP_UART_Transmit(BSP_UART_AI, (uint8_t *)&tx_pkg, sizeof(PackageMCU_t), true);
}
/* USER FUNCTION END */
/* Private function --------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
void Task_ai(void *argument) {
(void)argument; /* 未使用argument消除警告 */
(void)argument;
/* 计算任务运行到指定频率需要等待的tick数 */
const uint32_t delay_tick = osKernelGetTickFreq() / AI_FREQ;
osDelay(AI_INIT_DELAY);
uint32_t tick = osKernelGetTickCount();
/* 计算任务运行到指定频率需要等待的tick数 */
const uint32_t delay_tick = osKernelGetTickFreq() / AI_FREQ;
osDelay(AI_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); /* 运行结束,等待下一次唤醒 */
}
/* USER CODE INIT BEGIN */
/* 注册串口接收完成回调并启动第一次DMA接收 */
BSP_UART_RegisterCallback(BSP_UART_AI, BSP_UART_RX_CPLT_CB, AI_RxCpltCallback);
BSP_UART_Receive(BSP_UART_AI, ai_rx_buf, sizeof(PackageAI_t), true);
/* USER CODE INIT END */
while (1) {
tick += delay_tick;
/* USER CODE BEGIN */
/* 定期向上位机发送包含姿态、云台、射击反馈的 MCU 状态包 */
AI_Send_MCU_Data();
/* USER CODE END */
osDelayUntil(tick);
}
}

View File

@ -83,7 +83,14 @@ void Task_atti_esti(void *argument) {
/* 根据解析出来的四元数计算欧拉角 */
AHRS_GetEulr(&eulr_to_send, &gimbal_ahrs);
osKernelUnlock();
// 将四元数发送至 AI 任务的消息队列
// &gimbal_ahrs.quat: 四元数结构体地址
// 0: 消息优先级
// 0: 不等待,如果队列满了直接跳过(保证实时性)
osMessageQueuePut(msgq.ai.quat, &gimbal_ahrs.quat, 0, 0);
// 如果 AI 任务还需要欧拉角,也可以发送欧拉角队列
osMessageQueuePut(msgq.ai.eulr, &eulr_to_send, 0, 0);
BSP_PWM_SetComp(BSP_PWM_IMU_HEAT_PWM, PID_Calc(&imu_temp_ctrl_pid, 40.5f,
bmi088.temp, 0.0f, 0.0f));