From ad716705fff9553242e9e06d96e385f3aa8ff5f0 Mon Sep 17 00:00:00 2001 From: Robofish <1683502971@qq.com> Date: Tue, 30 Sep 2025 21:56:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86can=E9=81=A5?= =?UTF-8?q?=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + User/device/rc_can.c | 312 ++++++++++++++++++++++++++++++++++ User/device/rc_can.h | 157 +++++++++++++++++ User/module/balance_chassis.c | 4 +- User/module/config.c | 12 +- User/module/config.h | 5 +- User/task/rc.c | 80 ++++----- 7 files changed, 521 insertions(+), 50 deletions(-) create mode 100644 User/device/rc_can.c create mode 100644 User/device/rc_can.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1755f05..750eaea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE User/device/motor_lk.c User/device/motor_lz.c User/device/motor_rm.c + User/device/rc_can.c # User/module sources User/module/balance_chassis.c diff --git a/User/device/rc_can.c b/User/device/rc_can.c new file mode 100644 index 0000000..292aec4 --- /dev/null +++ b/User/device/rc_can.c @@ -0,0 +1,312 @@ +/* Includes ----------------------------------------------------------------- */ +#include "device/rc_can.h" +#include "bsp/time.h" +#include "device/device.h" +/* USER INCLUDE BEGIN */ + +/* USER INCLUDE END */ + +/* Private constants -------------------------------------------------------- */ + +/* USER DEFINE BEGIN */ + +/* USER DEFINE END */ + +/* Private macro ------------------------------------------------------------ */ +/* Private types ------------------------------------------------------------ */ +/* Private variables -------------------------------------------------------- */ + +/* USER VARIABLE BEGIN */ + +/* USER VARIABLE END */ + +/* USER FUNCTION BEGIN */ + +/* USER FUNCTION END */ + +/* Private function prototypes ---------------------------------------------- */ +static int8_t RC_CAN_ValidateParams(const RC_CAN_Param_t *param); +static int8_t RC_CAN_RegisterIds(RC_CAN_t *rc_can); + +/* Exported functions ------------------------------------------------------- */ + +/** + * @brief 初始化RC CAN发送模块 + * @param rc_can RC_CAN结构体指针 + * @param param 初始化参数 + * @return DEVICE_OK 成功,其他值失败 + */ +int8_t RC_CAN_Init(RC_CAN_t *rc_can, RC_CAN_Param_t *param) { + if (rc_can == NULL || param == NULL) { + return DEVICE_ERR_NULL; + } + + // 参数验证 + if (RC_CAN_ValidateParams(param) != DEVICE_OK) { + return DEVICE_ERR; + } + + rc_can->param = *param; + + // 初始化header + rc_can->header.online = false; + rc_can->header.last_online_time = 0; + + // 手动初始化数据结构 + rc_can->data.joy.ch_l_x = 0.0f; + rc_can->data.joy.ch_l_y = 0.0f; + rc_can->data.joy.ch_r_x = 0.0f; + rc_can->data.joy.ch_r_y = 0.0f; + rc_can->data.sw.sw_l = RC_CAN_SW_ERR; + rc_can->data.sw.sw_r = RC_CAN_SW_ERR; + rc_can->data.sw.ch_res = 0.0f; + rc_can->data.mouse.x = 0.0f; + rc_can->data.mouse.y = 0.0f; + rc_can->data.mouse.z = 0.0f; + rc_can->data.mouse.mouse_l = false; + rc_can->data.mouse.mouse_r = false; + rc_can->data.keyboard.key_value = 0; + for (int i = 0; i < 6; i++) { + rc_can->data.keyboard.keys[i] = RC_CAN_KEY_NONE; + } + + // 注册CAN ID队列(从机模式需要接收数据) + if (rc_can->param.mode == RC_CAN_MODE_SLAVE) { + return RC_CAN_RegisterIds(rc_can); + } + + return DEVICE_OK; +} + +/** + * @brief 更新并发送数据到CAN总线 + * @param rc_can RC_CAN结构体指针 + * @param data_type 数据类型 + * @return DEVICE_OK 成功,其他值失败 + */ +int8_t RC_CAN_SendData(RC_CAN_t *rc_can, RC_CAN_DataType_t data_type) { + if (rc_can == NULL) { + return DEVICE_ERR_NULL; + } + if (rc_can->param.mode != RC_CAN_MODE_MASTER) { + return DEVICE_ERR; + } + BSP_CAN_StdDataFrame_t frame; + frame.dlc = 8; + switch (data_type) { + case RC_CAN_DATA_JOYSTICK: + frame.id = rc_can->param.joy_id; + frame.data[0] = (uint8_t)((int16_t)(rc_can->data.joy.ch_l_x * 32768.0f) & 0xFF); + frame.data[1] = + (uint8_t)(((int16_t)(rc_can->data.joy.ch_l_x * 32768.0f) >> 8) & 0xFF); + frame.data[2] = (uint8_t)((int16_t)(rc_can->data.joy.ch_l_y * 32768.0f) & 0xFF); + frame.data[3] = + (uint8_t)(((int16_t)(rc_can->data.joy.ch_l_y * 32768.0f) >> 8) & 0xFF); + frame.data[4] = (uint8_t)((int16_t)(rc_can->data.joy.ch_r_x * 32768.0f) & 0xFF); + frame.data[5] = + (uint8_t)(((int16_t)(rc_can->data.joy.ch_r_x * 32768.0f) >> 8) & 0xFF); + frame.data[6] = (uint8_t)((int16_t)(rc_can->data.joy.ch_r_y * 32768.0f) & 0xFF); + frame.data[7] = + (uint8_t)(((int16_t)(rc_can->data.joy.ch_r_y * 32768.0f) >> 8) & 0xFF); + break; + case RC_CAN_DATA_SWITCH: + frame.id = rc_can->param.sw_id; + frame.data[0] = (uint8_t)(rc_can->data.sw.sw_l); + frame.data[1] = (uint8_t)(rc_can->data.sw.sw_r); + frame.data[2] = (uint8_t)((int16_t)(rc_can->data.sw.ch_res * 32768.0f) & 0xFF); + frame.data[3] = + (uint8_t)(((int16_t)(rc_can->data.sw.ch_res * 32768.0f) >> 8) & 0xFF); + frame.data[4] = 0; // 保留字节 + frame.data[5] = 0; // 保留字节 + frame.data[6] = 0; // 保留字节 + frame.data[7] = 0; // 保留字节 + break; + case RC_CAN_DATA_MOUSE: + frame.id = rc_can->param.mouse_id; + frame.data[0] = (uint8_t)((int16_t)(rc_can->data.mouse.x) & 0xFF); + frame.data[1] = (uint8_t)(((int16_t)(rc_can->data.mouse.x) >> 8) & 0xFF); + frame.data[2] = (uint8_t)((int16_t)(rc_can->data.mouse.y) & 0xFF); + frame.data[3] = (uint8_t)(((int16_t)(rc_can->data.mouse.y) >> 8) & 0xFF); + frame.data[4] = (uint8_t)((int16_t)(rc_can->data.mouse.z) & 0xFF); + frame.data[5] = (uint8_t)(((int16_t)(rc_can->data.mouse.z) >> 8) & 0xFF); + frame.data[6] = (uint8_t)(rc_can->data.mouse.mouse_l ? 1 : 0); + frame.data[7] = (uint8_t)(rc_can->data.mouse.mouse_r ? 1 : 0); + break; + case RC_CAN_DATA_KEYBOARD: + frame.id = rc_can->param.keyboard_id; + frame.data[0] = (uint8_t)(rc_can->data.keyboard.key_value & 0xFF); + frame.data[1] = (uint8_t)((rc_can->data.keyboard.key_value >> 8) & 0xFF); + for (int i = 0; i < 6; i++) { + frame.data[2 + i] = (i < 6) ? (uint8_t)(rc_can->data.keyboard.keys[i]) : 0; + } + break; + default: + return DEVICE_ERR; + } + if (BSP_CAN_Transmit(rc_can->param.can, BSP_CAN_FORMAT_STD_DATA, frame.id, + frame.data, frame.dlc) != BSP_OK) { + return DEVICE_ERR; + } + return DEVICE_OK; +} + +/** + * @brief 接收并更新CAN数据 + * @param rc_can RC_CAN结构体指针 + * @param data_type 数据类型 + * @return DEVICE_OK 成功,其他值失败 + */ +int8_t RC_CAN_Update(RC_CAN_t *rc_can, RC_CAN_DataType_t data_type) { + if (rc_can == NULL) { + return DEVICE_ERR_NULL; + } + + // 只有从机模式才能接收数据 + if (rc_can->param.mode != RC_CAN_MODE_SLAVE) { + return DEVICE_ERR; + } + BSP_CAN_Message_t msg; + + switch (data_type) { + case RC_CAN_DATA_JOYSTICK: + if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.joy_id, &msg, + BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) { + return DEVICE_ERR; + } + // 解包数据 + int16_t ch_l_x = (int16_t)((msg.data[1] << 8) | msg.data[0]); + int16_t ch_l_y = (int16_t)((msg.data[3] << 8) | msg.data[2]); + int16_t ch_r_x = (int16_t)((msg.data[5] << 8) | msg.data[4]); + int16_t ch_r_y = (int16_t)((msg.data[7] << 8) | msg.data[6]); + + // 转换为浮点数(范围:-1.0到1.0) + rc_can->data.joy.ch_l_x = (float)ch_l_x / 32768.0f; + rc_can->data.joy.ch_l_y = (float)ch_l_y / 32768.0f; + rc_can->data.joy.ch_r_x = (float)ch_r_x / 32768.0f; + rc_can->data.joy.ch_r_y = (float)ch_r_y / 32768.0f; + break; + case RC_CAN_DATA_SWITCH: + if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.sw_id, &msg, + BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) { + return DEVICE_ERR; + } + // 解包数据 + rc_can->data.sw.sw_l = (RC_CAN_SW_t)msg.data[0]; + rc_can->data.sw.sw_r = (RC_CAN_SW_t)msg.data[1]; + + int16_t ch_res = (int16_t)((msg.data[3] << 8) | msg.data[2]); + rc_can->data.sw.ch_res = (float)ch_res / 32768.0f; + break; + case RC_CAN_DATA_MOUSE: + if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.mouse_id, &msg, + BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) { + return DEVICE_ERR; + } + // 解包数据 + int16_t x = (int16_t)((msg.data[1] << 8) | msg.data[0]); + int16_t y = (int16_t)((msg.data[3] << 8) | msg.data[2]); + int16_t z = (int16_t)((msg.data[5] << 8) | msg.data[4]); + rc_can->data.mouse.x = (float)x; + rc_can->data.mouse.y = (float)y; + rc_can->data.mouse.z = (float)z; + rc_can->data.mouse.mouse_l = (msg.data[6] & 0x01) ? true : false; + rc_can->data.mouse.mouse_r = (msg.data[7] & 0x01) ? true : false; + break; + case RC_CAN_DATA_KEYBOARD: + if (BSP_CAN_GetMessage(rc_can->param.can, rc_can->param.keyboard_id, &msg, + BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) { + return DEVICE_ERR; + } + if (msg.dlc < 2) { + return DEVICE_ERR; + } + // 解包数据 + rc_can->data.keyboard.key_value = + (uint16_t)((msg.data[1] << 8) | msg.data[0]); + for (int i = 0; i < 6 && (i + 2) < msg.dlc; i++) { + rc_can->data.keyboard.keys[i] = (RC_CAN_Key_t)(msg.data[2 + i]); + } + // 清空未使用的按键位置 + for (int i = (msg.dlc > 2 ? msg.dlc - 2 : 0); i < 6; i++) { + rc_can->data.keyboard.keys[i] = RC_CAN_KEY_NONE; + } + break; + default: + return DEVICE_ERR; + } + + // 更新header状态 + rc_can->header.online = true; + rc_can->header.last_online_time = BSP_TIME_Get_us(); + + return DEVICE_OK; +} + +/* Private functions -------------------------------------------------------- */ + +/** + * @brief 验证RC_CAN参数 + * @param param 参数指针 + * @return DEVICE_OK 成功,其他值失败 + */ +static int8_t RC_CAN_ValidateParams(const RC_CAN_Param_t *param) { + if (param == NULL) { + return DEVICE_ERR_NULL; + } + + // 检查CAN总线有效性 + if (param->can >= BSP_CAN_NUM) { + return DEVICE_ERR; + } + + // 检查工作模式有效性 + if (param->mode != RC_CAN_MODE_MASTER && param->mode != RC_CAN_MODE_SLAVE) { + return DEVICE_ERR; + } + + // 检查CAN ID是否重复 + if (param->joy_id == param->sw_id || param->joy_id == param->mouse_id || + param->joy_id == param->keyboard_id || param->sw_id == param->mouse_id || + param->sw_id == param->keyboard_id || + param->mouse_id == param->keyboard_id) { + return DEVICE_ERR; + } + + return DEVICE_OK; +} + +/** + * @brief 注册CAN ID + * @param rc_can RC_CAN结构体指针 + * @return DEVICE_OK 成功,其他值失败 + */ +static int8_t RC_CAN_RegisterIds(RC_CAN_t *rc_can) { + if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.joy_id, 0) != + BSP_OK) { + return DEVICE_ERR; + } + if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.sw_id, 0) != BSP_OK) { + return DEVICE_ERR; + } + if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.mouse_id, 0) != + BSP_OK) { + return DEVICE_ERR; + } + if (BSP_CAN_RegisterId(rc_can->param.can, rc_can->param.keyboard_id, 0) != + BSP_OK) { + return DEVICE_ERR; + } + + return DEVICE_OK; +} + +int8_t RC_CAN_OFFLINE(RC_CAN_t *rc_can){ + if (rc_can == NULL) { + return DEVICE_ERR_NULL; + } + rc_can->header.online = false; + return DEVICE_OK; +} +/* USER CODE BEGIN */ + +/* USER CODE END */ diff --git a/User/device/rc_can.h b/User/device/rc_can.h new file mode 100644 index 0000000..e5c6d90 --- /dev/null +++ b/User/device/rc_can.h @@ -0,0 +1,157 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ----------------------------------------------------------------- */ +#include "bsp/can.h" +#include "device/device.h" +#include +#include + +/* USER INCLUDE BEGIN */ + +/* USER INCLUDE END */ + +/* USER DEFINE BEGIN */ + +/* USER DEFINE END */ + +/* Exported constants ------------------------------------------------------- */ + +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ +typedef enum { + RC_CAN_SW_ERR = 0, + RC_CAN_SW_UP = 1, + RC_CAN_SW_MID = 3, + RC_CAN_SW_DOWN = 2, +} RC_CAN_SW_t; + +typedef enum { + RC_CAN_MODE_MASTER = 0, // 主机模式 + RC_CAN_MODE_SLAVE = 1, // 从机模式 +} RC_CAN_Mode_t; + +typedef enum { + RC_CAN_DATA_JOYSTICK = 0, + RC_CAN_DATA_SWITCH, + RC_CAN_DATA_MOUSE, + RC_CAN_DATA_KEYBOARD +} RC_CAN_DataType_t; + +typedef enum { + RC_CAN_KEY_NONE = 0xFF, // 无按键 + RC_CAN_KEY_W = 0, + RC_CAN_KEY_S, + RC_CAN_KEY_A, + RC_CAN_KEY_D, + RC_CAN_KEY_SHIFT, + RC_CAN_KEY_CTRL, + RC_CAN_KEY_Q, + RC_CAN_KEY_E, + RC_CAN_KEY_R, + RC_CAN_KEY_F, + RC_CAN_KEY_G, + RC_CAN_KEY_Z, + RC_CAN_KEY_X, + RC_CAN_KEY_C, + RC_CAN_KEY_V, + RC_CAN_KEY_B, + RC_CAN_KEY_NUM, +} RC_CAN_Key_t; + +// 遥杆数据包 +typedef struct { + float ch_l_x; + float ch_l_y; + float ch_r_x; + float ch_r_y; +} RC_CAN_JoyData_t; + +// 拨杆数据包 +typedef struct { + RC_CAN_SW_t sw_l; // 左拨杆状态 + RC_CAN_SW_t sw_r; // 右拨杆状态 + float ch_res; // 第五通道 +} RC_CAN_SwitchData_t; + +// 鼠标数据包 +typedef struct { + float x; // 鼠标X轴移动 + float y; // 鼠标Y轴移动 + float z; // 鼠标Z轴(滚轮) + bool mouse_l; // 鼠标左键 + bool mouse_r; // 鼠标右键 +} RC_CAN_MouseData_t; + +// 键盘数据包 +typedef struct { + uint16_t key_value; // 键盘按键位映射 + RC_CAN_Key_t keys[16]; +} RC_CAN_KeyboardData_t; + + +typedef struct { + RC_CAN_JoyData_t joy; + RC_CAN_SwitchData_t sw; + RC_CAN_MouseData_t mouse; + RC_CAN_KeyboardData_t keyboard; +} RC_CAN_Data_t; + +// RC_CAN 参数结构 +typedef struct { + BSP_CAN_t can; // 使用的CAN总线 + RC_CAN_Mode_t mode; // 工作模式 + uint16_t joy_id; // 遥杆CAN ID + uint16_t sw_id; // 拨杆CAN ID + uint16_t mouse_id; // 鼠标CAN ID + uint16_t keyboard_id; // 键盘CAN ID +} RC_CAN_Param_t; + +// RC_CAN 主结构 +typedef struct { + DEVICE_Header_t header; + RC_CAN_Param_t param; + RC_CAN_Data_t data; +} RC_CAN_t; + +/* USER STRUCT BEGIN */ + +/* USER STRUCT END */ + +/* Exported functions prototypes -------------------------------------------- */ + +/** + * @brief 初始化RC CAN发送模块 + * @param rc_can RC_CAN结构体指针 + * @param param 初始化参数 + * @return DEVICE_OK 成功,其他值失败 + */ +int8_t RC_CAN_Init(RC_CAN_t *rc_can, RC_CAN_Param_t *param); + +/** + * @brief 更新并发送数据到CAN总线 + * @param rc_can RC_CAN结构体指针 + * @param data_type 数据类型 + * @return DEVICE_OK 成功,其他值失败 + */ +int8_t RC_CAN_SendData(RC_CAN_t *rc_can, RC_CAN_DataType_t data_type); + +/** + * @brief 接收并更新CAN数据 + * @param rc_can RC_CAN结构体指针 + * @param data_type 数据类型 + * @return DEVICE_OK 成功,其他值失败 + */ +int8_t RC_CAN_Update(RC_CAN_t *rc_can , RC_CAN_DataType_t data_type); + +int8_t RC_CAN_OFFLINE(RC_CAN_t *rc_can); +/* USER FUNCTION BEGIN */ + +/* USER FUNCTION END */ + +#ifdef __cplusplus +} +#endif diff --git a/User/module/balance_chassis.c b/User/module/balance_chassis.c index c1319c1..5939ff1 100644 --- a/User/module/balance_chassis.c +++ b/User/module/balance_chassis.c @@ -261,7 +261,7 @@ int8_t Chassis_Control(Chassis_t *c, const Chassis_CMD_t *c_cmd){ float fn; float tp1, tp2; - fn = -20.0f; + fn = -25.0f; // tp1 = 3*PID_Calc(&c->pid.tp[0], 0.0f, c->vmc_[0].leg.theta, c->vmc_[0].leg.d_theta, c->dt); @@ -490,7 +490,7 @@ int8_t Chassis_LQRControl(Chassis_t *c, const Chassis_CMD_t *c_cmd) { // 腿长控制力 = LQR摆杆力矩的径向分量 + PID腿长控制输出 + 基础支撑力 virtual_force[leg] = (Tp[leg]) * sinf(leg_theta[leg]) + - pid_output + 25.0f; + pid_output + 40.0f; // + // PID腿长控制输出 // 45.0f; // 基础支撑力 diff --git a/User/module/config.c b/User/module/config.c index c58511a..dc49643 100644 --- a/User/module/config.c +++ b/User/module/config.c @@ -5,6 +5,7 @@ /* Includes ----------------------------------------------------------------- */ #include "module/config.h" #include "bsp/can.h" +#include "device/rc_can.h" /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ @@ -205,7 +206,16 @@ Config_RobotParam_t robot_config = { }, .lqr_param.max_joint_torque = 20.0f, // 关节电机最大力矩 20Nm .lqr_param.max_wheel_torque = 4.5f, // 轮毂电机最大力矩 2.5Nm - } + }, + + .rc_can_param = { + .can = BSP_CAN_2, + .mode = RC_CAN_MODE_SLAVE, + .joy_id = 0x250, + .sw_id = 0x251, + .mouse_id = 0x252, + .keyboard_id = 0x253, + }, }; /* Private function prototypes ---------------------------------------------- */ diff --git a/User/module/config.h b/User/module/config.h index 7754b89..712bcbc 100644 --- a/User/module/config.h +++ b/User/module/config.h @@ -13,13 +13,12 @@ extern "C" { #include "device/motor_lz.h" #include "device/motor_lk.h" #include "module/balance_chassis.h" - +#include "device/rc_can.h" typedef struct { DM_IMU_Param_t imu_param; - MOTOR_LZ_Param_t joint_motors[4]; - MOTOR_LK_Param_t wheel_motors[2]; Chassis_Params_t chassis_param; + RC_CAN_Param_t rc_can_param; } Config_RobotParam_t; /* Exported functions prototypes -------------------------------------------- */ diff --git a/User/task/rc.c b/User/task/rc.c index 31c7682..53430a6 100644 --- a/User/task/rc.c +++ b/User/task/rc.c @@ -6,8 +6,11 @@ /* Includes ----------------------------------------------------------------- */ #include "task/user_task.h" /* USER INCLUDE BEGIN */ +#include "bsp/can.h" #include "device/dr16.h" +#include "device/rc_can.h" #include "module/balance_chassis.h" +#include "module/config.h" /* USER INCLUDE END */ /* Private typedef ---------------------------------------------------------- */ @@ -16,7 +19,9 @@ /* Private variables -------------------------------------------------------- */ /* USER STRUCT BEGIN */ DR16_t dr16; +RC_CAN_t rc_can; Chassis_CMD_t cmd_to_chassis; +#define USE_RC_CAN /* USER STRUCT END */ /* Private function --------------------------------------------------------- */ @@ -32,12 +37,15 @@ void Task_rc(void *argument) { uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */ /* USER CODE INIT BEGIN */ + BSP_CAN_Init(); DR16_Init(&dr16); + RC_CAN_Init(&rc_can, &Config_GetRobotParam()->rc_can_param); /* USER CODE INIT END */ while (1) { tick += delay_tick; /* 计算下一个唤醒时刻 */ /* USER CODE BEGIN */ + #ifdef USE_DR16 DR16_StartDmaRecv(&dr16); if (DR16_WaitDmaCplt(20)) { DR16_ParseData(&dr16); @@ -63,51 +71,35 @@ void Task_rc(void *argument) { DR16_Offline(&dr16); cmd_to_chassis.mode = CHASSIS_MODE_RELAX; } + #elif defined USE_RC_CAN + RC_CAN_Update(&rc_can, RC_CAN_DATA_JOYSTICK); + RC_CAN_Update(&rc_can, RC_CAN_DATA_SWITCH); + if (rc_can.header.online) { + switch (rc_can.data.sw.sw_l) { + case RC_CAN_SW_UP: // 上位 + cmd_to_chassis.mode = CHASSIS_MODE_RELAX; + break; + case RC_CAN_SW_MID: // 中位 + cmd_to_chassis.mode = CHASSIS_MODE_RECOVER; + break; + case RC_CAN_SW_DOWN: // 下位 + cmd_to_chassis.mode = CHASSIS_MODE_WHELL_BALANCE; + break; + default: + cmd_to_chassis.mode = CHASSIS_MODE_RELAX; + break; + } + cmd_to_chassis.move_vec.vx = rc_can.data.joy.ch_l_y; + cmd_to_chassis.move_vec.vy = rc_can.data.joy.ch_l_x; + cmd_to_chassis.move_vec.wz = rc_can.data.joy.ch_r_x; + cmd_to_chassis.height = rc_can.data.sw.ch_res; + } else { + RC_CAN_OFFLINE(&rc_can); + cmd_to_chassis.mode = CHASSIS_MODE_RELAX; + } + #endif osMessageQueuePut(task_runtime.msgq.Chassis_cmd, &cmd_to_chassis, 0, 0); - // if (DR16_WaitDmaCplt(20)) { - // // 根据左拨杆设置底盘模式 - // switch (dr16.data.sw_l) { - // case 1: // 上位 - // cmd_to_chassis.mode = CHASSIS_MODE_RELAX; - // break; - // case 3: // 中位 - // cmd_to_chassis.mode = CHASSIS_MODE_RECOVER; - // break; - // case 2: // 下位 - // cmd_to_chassis.mode = CHASSIS_MODE_WHELL_BALANCE; - // break; - // default: - // cmd_to_chassis.mode = CHASSIS_MODE_RELAX; - // break; - // } - - // // 解析遥控器摇杆数据为运动向量 - // // 将遥控器通道值从[364, 1684]映射到[-1.0, 1.0] - // float ch_l_y_norm = (float)(dr16.data.ch_l_y - 1024) / 660.0f; // 前后 - // float ch_l_x_norm = (float)(dr16.data.ch_l_x - 1024) / 660.0f; // 左右 - // float ch_r_x_norm = (float)(dr16.data.ch_r_y - 1024) / 660.0f; // 旋转 - - // // 设置运动向量(根据需要调整增益) - // cmd_to_chassis.move_vec.vx = ch_l_y_norm * 2.0f; // 前后运动,增益可调 - // cmd_to_chassis.move_vec.vy = ch_l_x_norm * 2.0f; // 左右运动,增益可调 - // cmd_to_chassis.move_vec.wz = ch_r_x_norm * 3.0f; // 旋转运动,增益可调 - - // // 设置目标高度(可根据右拨杆或其他输入调整) - // cmd_to_chassis.height = dr16.data.res-1024; // 目标高度,范围[-1024, 1024],可根据需要调整比例 - - // // 发送命令到底盘控制任务 - // osMessageQueuePut(task_runtime.msgq.Chassis_cmd, &cmd_to_chassis, 0, 0); - - // } else { - // // 超时处理,发送安全命令 - // cmd_to_chassis.mode = CHASSIS_MODE_RELAX; - // cmd_to_chassis.move_vec.vx = 0.0f; - // cmd_to_chassis.move_vec.vy = 0.0f; - // cmd_to_chassis.move_vec.wz = 0.0f; - // cmd_to_chassis.height = 0.0f; - // osMessageQueuePut(task_runtime.msgq.Chassis_cmd, &cmd_to_chassis, 0, 0); - // } - + /* USER CODE END */ osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */ }