From f3ad8040483b2afbcd1c29fd4c5cf7682648cda3 Mon Sep 17 00:00:00 2001 From: chenfu <2412777093@qq.com> Date: Mon, 27 Mar 2023 22:03:35 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=94=AE=E9=BC=A0?= =?UTF-8?q?=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HAL_N_Middlewares/Src/can.c | 4 +- application/chassis/chassis.c | 12 +- application/cmd/robot_cmd.c | 157 ++++++++++++++++++------ application/gimbal/gimbal.c | 13 +- application/robot_def.h | 5 +- modules/master_machine/master_process.c | 2 +- modules/remote/remote_control.c | 67 ++++++---- modules/remote/remote_control.h | 14 ++- 8 files changed, 193 insertions(+), 81 deletions(-) diff --git a/HAL_N_Middlewares/Src/can.c b/HAL_N_Middlewares/Src/can.c index c4c0948..292573f 100644 --- a/HAL_N_Middlewares/Src/can.c +++ b/HAL_N_Middlewares/Src/can.c @@ -122,7 +122,7 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle) HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /* CAN1 interrupt Init */ - HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 6, 0); + HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn); HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn); @@ -155,7 +155,7 @@ void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle) HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* CAN2 interrupt Init */ - HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 6, 0); + HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn); HAL_NVIC_SetPriority(CAN2_RX1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(CAN2_RX1_IRQn); diff --git a/application/chassis/chassis.c b/application/chassis/chassis.c index 1af1908..34a66ef 100644 --- a/application/chassis/chassis.c +++ b/application/chassis/chassis.c @@ -19,7 +19,7 @@ // referee需要移动到module层 ///////////////////////// -#include "referee.h" + #include "rm_referee.h" ///////////////////////// @@ -68,16 +68,16 @@ void ChassisInit() .can_init_config.can_handle = &hcan1, .controller_param_init_config = { .speed_PID = { - .Kp = 4.5,//9 - .Ki = 0,//0.02 - .Kd = 0.01,//0.01 + .Kp = 10,//4.5 + .Ki = 0,//0 + .Kd = 0,//0 .IntegralLimit = 3000, .Improve = PID_Trapezoid_Intergral | PID_Integral_Limit |PID_Derivative_On_Measurement, .MaxOut = 12000, }, .current_PID = { - .Kp = 0.4,//0.7 - .Ki = 0,//0.1 + .Kp = 0.5,//0.4 + .Ki = 0,//0 .Kd = 0, .IntegralLimit = 3000, .Improve = PID_Trapezoid_Intergral | PID_Integral_Limit |PID_Derivative_On_Measurement, diff --git a/application/cmd/robot_cmd.c b/application/cmd/robot_cmd.c index 4883e04..5e4f787 100644 --- a/application/cmd/robot_cmd.c +++ b/application/cmd/robot_cmd.c @@ -21,11 +21,12 @@ static CANCommInstance *cmd_can_comm; // 双板通信 #ifdef ONE_BOARD static Publisher_t *chassis_cmd_pub; // 底盘控制消息发布者 static Subscriber_t *chassis_feed_sub; // 底盘反馈信息订阅者 -#endif // ONE_BOARD +#endif // ONE_BOARD static Chassis_Ctrl_Cmd_s chassis_cmd_send; // 发送给底盘应用的信息,包括控制信息和UI绘制相关 static Chassis_Upload_Data_s chassis_fetch_data; // 从底盘应用接收的反馈信息信息,底盘功率枪口热量与底盘运动状态等 + static RC_ctrl_t *rc_data; // 遥控器数据,初始化时返回 static Vision_Recv_s *vision_recv_data; // 视觉接收数据指针,初始化时返回 static Vision_Send_s vision_send_data; // 视觉发送数据 @@ -68,7 +69,7 @@ void RobotCMDInit() }; cmd_can_comm = CANCommInit(&comm_conf); #endif // GIMBAL_BOARD -gimbal_cmd_send.pitch = 0; + gimbal_cmd_send.pitch = 0; robot_state = ROBOT_READY; // 启动时机器人进入工作模式,后续加入所有应用初始化完成之后再进入 } @@ -81,9 +82,9 @@ gimbal_cmd_send.pitch = 0; static void CalcOffsetAngle() { // 别名angle提高可读性,不然太长了不好看,虽然基本不会动这个函数 - static float angle; + static float angle; angle = gimbal_fetch_data.yaw_motor_single_round_angle; // 从云台获取的当前yaw电机单圈角度 -#if YAW_ECD_GREATER_THAN_4096 // 如果大于180度 +#if YAW_ECD_GREATER_THAN_4096 // 如果大于180度 if (angle > YAW_ALIGN_ANGLE && angle <= 180.0f + YAW_ALIGN_ANGLE) chassis_cmd_send.offset_angle = angle - YAW_ALIGN_ANGLE; else if (angle > 180.0f + YAW_ALIGN_ANGLE) @@ -100,17 +101,6 @@ static void CalcOffsetAngle() #endif } -static void OffsetAnglePidCalc() -{ - // float pid_measure,pid_ref; - // static PIDInstance AngleCal = { - // .Kp = -1, - // .Ki = 0, - // .Kd = 0, - // .MaxOut = 10000, - // }; - // chassis_cmd_send.offset_angle = PIDCalculate(&AngleCal,chassis_cmd_send.offset_angle,0); -} /** * @brief 控制输入为遥控器(调试时)的模式和控制量设置 * @@ -119,11 +109,15 @@ static void RemoteControlSet() { // 控制底盘和云台运行模式,云台待添加,云台是否始终使用IMU数据? if (switch_is_down(rc_data[TEMP].rc.switch_right)) // 右侧开关状态[下],底盘跟随云台 - {chassis_cmd_send.chassis_mode = CHASSIS_ROTATE; - gimbal_cmd_send.gimbal_mode = GIMBAL_GYRO_MODE;} + { + chassis_cmd_send.chassis_mode = CHASSIS_ROTATE; + gimbal_cmd_send.gimbal_mode = GIMBAL_GYRO_MODE; + } else if (switch_is_mid(rc_data[TEMP].rc.switch_right)) // 右侧开关状态[中],底盘和云台分离,底盘保持不转动 - {chassis_cmd_send.chassis_mode = CHASSIS_NO_FOLLOW; - gimbal_cmd_send.gimbal_mode = GIMBAL_FREE_MODE;} + { + chassis_cmd_send.chassis_mode = CHASSIS_NO_FOLLOW; + gimbal_cmd_send.gimbal_mode = GIMBAL_FREE_MODE; + } // 云台参数,确定云台控制数据 if (switch_is_mid(rc_data[TEMP].rc.switch_left)) // 左侧开关状态为[中],视觉模式 @@ -136,25 +130,24 @@ static void RemoteControlSet() { // 按照摇杆的输出大小进行角度增量,增益系数需调整 gimbal_cmd_send.yaw += 0.005f * (float)rc_data[TEMP].rc.rocker_l_; gimbal_cmd_send.pitch += 0.001f * (float)rc_data[TEMP].rc.rocker_l1; - // if (gimbal_cmd_send.pitch <= 122) - // { - // gimbal_cmd_send.pitch =125; - // } - // else if (gimbal_cmd_send.pitch >= 175) - // { - // gimbal_cmd_send.pitch = 174; - // } - + // 摇杆控制的软件限位 + // if (gimbal_cmd_send.pitch <= PITCH_MIN_ECD) + // { + // gimbal_cmd_send.pitch = PITCH_MIN_ECD; + // } + // else if (gimbal_cmd_send.pitch >= PITCH_MAX_ECD) + // { + // gimbal_cmd_send.pitch = PITCH_MAX_ECD; + // } } // 底盘参数,目前没有加入小陀螺(调试似乎暂时没有必要),系数需要调整 chassis_cmd_send.vx = 10.0f * (float)rc_data[TEMP].rc.rocker_r_; // _水平方向 chassis_cmd_send.vy = 10.0f * (float)rc_data[TEMP].rc.rocker_r1; // 1数值方向 - //chassis_cmd_send.wz = 300; // 发射参数 if (switch_is_up(rc_data[TEMP].rc.switch_right)) // 右侧开关状态[上],弹舱打开 - ; // 弹舱舵机控制,待添加servo_motor模块,开启 + ; // 弹舱舵机控制,待添加servo_motor模块,开启 else ; // 弹舱舵机控制,待添加servo_motor模块,关闭 @@ -163,7 +156,7 @@ static void RemoteControlSet() shoot_cmd_send.friction_mode = FRICTION_ON; else shoot_cmd_send.friction_mode = FRICTION_OFF; - // 拨弹控制,目前固定为连发 + // 拨弹控制,遥控器固定为一种拨弹模式,可自行选择 if (rc_data[TEMP].rc.dial < -500) shoot_cmd_send.load_mode = LOAD_BURSTFIRE; else @@ -178,14 +171,89 @@ static void RemoteControlSet() */ static void MouseKeySet() { - // 待添加键鼠控制 - // ... + chassis_cmd_send.vx = rc_data[TEMP].key[KEY_PRESS].w * 300 - rc_data[TEMP].key[KEY_PRESS].s * 300; // 系数待测 + chassis_cmd_send.vy = rc_data[TEMP].key[KEY_PRESS].s * 300 - rc_data[TEMP].key[KEY_PRESS].d * 300; + + gimbal_cmd_send.yaw += (float)rc_data[TEMP].mouse.x / 660 * 10; // 系数待测 + gimbal_cmd_send.pitch += (float)rc_data[TEMP].mouse.y / 660 * 10; + + switch (rc_data[TEMP].key_count[KEY_PRESS][Key_Z] % 3) // Z键设置弹速 + { + case 0: + shoot_cmd_send.bullet_speed = 15; + break; + case 1: + shoot_cmd_send.bullet_speed = 18; + break; + default: + shoot_cmd_send.bullet_speed = 30; + break; + } + switch (rc_data[TEMP].key_count[KEY_PRESS][Key_E] % 4) // E键设置发射模式 + { + case 0: + shoot_cmd_send.load_mode = LOAD_STOP; + break; + case 1: + shoot_cmd_send.load_mode = LOAD_1_BULLET; + break; + case 2: + shoot_cmd_send.load_mode = LOAD_3_BULLET; + break; + default: + shoot_cmd_send.load_mode = LOAD_BURSTFIRE; + break; + } + switch (rc_data[TEMP].key_count[KEY_PRESS][Key_R] % 2) // R键开关弹舱 + { + case 0: + shoot_cmd_send.lid_mode = LID_OPEN; + break; + default: + shoot_cmd_send.lid_mode = LID_CLOSE; + break; + } + switch (rc_data[TEMP].key_count[KEY_PRESS][Key_F] % 2) // F键开关摩擦轮 + { + case 0: + shoot_cmd_send.friction_mode = FRICTION_OFF; + break; + default: + shoot_cmd_send.friction_mode = FRICTION_ON; + break; + } + switch (rc_data[TEMP].key_count[KEY_PRESS][Key_C] % 4) // C键设置底盘速度 + { + case 0: + chassis_cmd_send.chassis_speed_buff = 40; + break; + case 1: + chassis_cmd_send.chassis_speed_buff = 60; + break; + case 2: + chassis_cmd_send.chassis_speed_buff = 80; + break; + default: + chassis_cmd_send.chassis_speed_buff = 100; + break; + } + switch (rc_data[TEMP].key[KEY_PRESS].shift) //待添加 按shift允许超功率 消耗缓冲能量 + { + case 1: + + break; + + default: + + break; + } + } /** * @brief 紧急停止,包括遥控器左上侧拨轮打满/重要模块离线/双板通信失效等 * 停止的阈值'300'待修改成合适的值,或改为开关控制. - * + * * @todo 后续修改为遥控器离线则电机停止(关闭遥控器急停),通过给遥控器模块添加daemon实现 * */ @@ -204,9 +272,25 @@ static void EmergencyHandler() // 遥控器右侧开关为[上],恢复正常运行 if (switch_is_up(rc_data[TEMP].rc.switch_right)) { - robot_state = ROBOT_READY; + robot_state = ROBOT_READY; shoot_cmd_send.shoot_mode = SHOOT_ON; } + switch (rc_data[TEMP].key_count[KEY_PRESS_WITH_CTRL][Key_C]%2) //ctrl+c 进入急停 + { + case 0: + robot_state = ROBOT_READY; + shoot_cmd_send.shoot_mode = SHOOT_ON; + break; + + default: + robot_state = ROBOT_STOP; + gimbal_cmd_send.gimbal_mode = GIMBAL_ZERO_FORCE; + chassis_cmd_send.chassis_mode = CHASSIS_ZERO_FORCE; + shoot_cmd_send.shoot_mode = SHOOT_OFF; + shoot_cmd_send.friction_mode = FRICTION_OFF; + shoot_cmd_send.load_mode = LOAD_STOP; + break; + } } /* 机器人核心控制任务,200Hz频率运行(必须高于视觉发送频率) */ @@ -237,7 +321,8 @@ void RobotCMDTask() vision_send_data.enemy_color = 0; vision_send_data.pitch = gimbal_fetch_data.gimbal_imu_data.Pitch; vision_send_data.yaw = gimbal_fetch_data.gimbal_imu_data.Yaw; - vision_send_data.roll = gimbal_fetch_data.gimbal_imu_data.Roll;; + vision_send_data.roll = gimbal_fetch_data.gimbal_imu_data.Roll; + ; // 推送消息,双板通信,视觉通信等 // 其他应用所需的控制数据在remotecontrolsetmode和mousekeysetmode中完成设置 diff --git a/application/gimbal/gimbal.c b/application/gimbal/gimbal.c index f02ce9c..327fd79 100644 --- a/application/gimbal/gimbal.c +++ b/application/gimbal/gimbal.c @@ -74,8 +74,8 @@ void GimbalInit() .MaxOut = 500, }, .speed_PID = { - .Kp = 50,//40 - .Ki = 200, + .Kp = 50,//50 + .Ki = 200,//200 .Kd = 0, .Improve = PID_Trapezoid_Intergral |PID_Integral_Limit |PID_Derivative_On_Measurement, .IntegralLimit = 3000, @@ -111,7 +111,7 @@ void GimbalInit() .speed_PID = { .Kp=50,//50 .Ki =350,//350 - .Kd =0,//0.1 + .Kd =0,//0 .Improve = PID_Trapezoid_Intergral | PID_Integral_Limit |PID_Derivative_On_Measurement, .IntegralLimit =2500, .MaxOut = 20000, @@ -136,7 +136,7 @@ void GimbalInit() gimbal_pub = PubRegister("gimbal_feed", sizeof(Gimbal_Upload_Data_s)); gimbal_sub = SubRegister("gimbal_cmd", sizeof(Gimbal_Ctrl_Cmd_s)); } - +int aaaaaaa; /* 机器人云台控制核心任务,后续考虑只保留IMU控制,不再需要电机的反馈 */ void GimbalTask() { @@ -178,7 +178,10 @@ void GimbalTask() default: break; } - +// if(yaw_motor->motor_measure.total_angle>120) +// { +// aaaaaaa++; +// } // 在合适的地方添加pitch重力补偿前馈力矩 // 根据IMU姿态/pitch电机角度反馈计算出当前配重下的重力矩 // ... diff --git a/application/robot_def.h b/application/robot_def.h index f432ece..107eb7d 100644 --- a/application/robot_def.h +++ b/application/robot_def.h @@ -37,6 +37,8 @@ #define YAW_CHASSIS_ALIGN_ECD 2711 // 云台和底盘对齐指向相同方向时的电机编码器值,若对云台有机械改动需要修改 #define YAW_ECD_GREATER_THAN_4096 0 // ALIGN_ECD值是否大于4096,是为1,否为0;用于计算云台偏转角度 #define PITCH_HORIZON_ECD 3412 // 云台处于水平位置时编码器值,若对云台有机械改动需要修改 +#define PITCH_MAX_ANGLE 0 //云台竖直方向最大角度 (注意反馈如果是陀螺仪,则填写陀螺仪的角度) +#define PITCH_MIN_ANGLE 0 //云台竖直方向最小角度 (注意反馈如果是陀螺仪,则填写陀螺仪的角度) // 发射参数 #define ONE_BULLET_DELTA_ANGLE 36 // 发射一发弹丸拨盘转动的距离,由机械设计图纸给出 #define REDUCTION_RATIO_LOADER 49.0f // 拨盘电机的减速比,英雄需要修改为3508的19.0f @@ -132,6 +134,7 @@ typedef enum // 功率限制,从裁判系统获取 typedef struct { // 功率控制 + float chassis_power_mx; } Chassis_Power_Data_s; /* ----------------CMD应用发布的控制数据,应当由gimbal/chassis/shoot订阅---------------- */ @@ -148,7 +151,7 @@ typedef struct float wz; // 旋转速度 float offset_angle; // 底盘和归中位置的夹角 chassis_mode_e chassis_mode; - + int chassis_speed_buff; // UI部分 // ... diff --git a/modules/master_machine/master_process.c b/modules/master_machine/master_process.c index 9cf70b4..7bb5282 100644 --- a/modules/master_machine/master_process.c +++ b/modules/master_machine/master_process.c @@ -84,7 +84,7 @@ void VisionSend(Vision_Send_s *send) static uint8_t send_buff[VISION_SEND_SIZE]; static uint16_t tx_len; // TODO: code to set flag_register - +flag_register = 30<<8|0b00000001; // 将数据转化为seasky协议的数据包 get_protocol_send_data(0x02, flag_register, &send->yaw, 3, send_buff, &tx_len); USARTSend(vision_usart_instance, send_buff, tx_len, USART_TRANSFER_DMA); // 和视觉通信使用IT,防止和接收使用的DMA冲突 diff --git a/modules/remote/remote_control.c b/modules/remote/remote_control.c index 5e9917b..7e4361f 100644 --- a/modules/remote/remote_control.c +++ b/modules/remote/remote_control.c @@ -32,9 +32,10 @@ static void RectifyRCjoystick() * @param[out] rc_ctrl: remote control data struct point * @retval none */ +uint16_t aaaaa; static void sbus_to_rc(const uint8_t *sbus_buf) { - memcpy(&rc_ctrl[1], &rc_ctrl[TEMP], sizeof(RC_ctrl_t)); // 保存上一次的数据,用于按键持续按下和切换的判断 + // 摇杆,直接解算时减去偏置 rc_ctrl[TEMP].rc.rocker_r_ = ((sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff) - RC_CH_VALUE_OFFSET; //!< Channel 0 rc_ctrl[TEMP].rc.rocker_r1 = (((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff) - RC_CH_VALUE_OFFSET; //!< Channel 1 @@ -53,32 +54,51 @@ static void sbus_to_rc(const uint8_t *sbus_buf) rc_ctrl[TEMP].mouse.press_l = sbus_buf[12]; //!< Mouse Left Is Press ? rc_ctrl[TEMP].mouse.press_r = sbus_buf[13]; //!< Mouse Right Is Press ? - // 按键值,每个键1bit,key_temp共16位;按键顺序在remote_control.h的宏定义中可见 - // 使用位域后不再需要这一中间操作 - rc_ctrl[TEMP].key_temp = sbus_buf[14] | (sbus_buf[15] << 8); //!< KeyBoard value + // 位域的按键值解算,直接memcpy即可,注意小端低字节在前,即lsb在第一位,msb在最后. 尚未测试 + *(uint16_t *)&rc_ctrl[TEMP].key[KEY_PRESS] = (uint16_t)(sbus_buf[14] | (sbus_buf[15] << 8)); - // @todo 似乎可以直接用位域操作进行,把key_temp通过强制类型转换变成key类型? 位域方案在下面,尚未测试 - // 按键值解算,利用宏+循环减少代码长度 - for (uint16_t i = 0x0001, j = 0; i != 0x8000; i *= 2, j++) // 依次查看每一个键 + if (rc_ctrl[TEMP].key[KEY_PRESS].ctrl) + rc_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL] = rc_ctrl[TEMP].key[KEY_PRESS]; + else + memset(&rc_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL], 0, sizeof(Key_t)); + if (rc_ctrl[TEMP].key[KEY_PRESS].shift) + rc_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT] = rc_ctrl[TEMP].key[KEY_PRESS]; + else + memset(&rc_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT], 0, sizeof(Key_t)); + + for (uint32_t i = 0, j = 0x1; i < 16; j <<= 1, i++) { - // 如果键按下,对应键的key press状态置1,否则为0 - rc_ctrl[TEMP].key[KEY_PRESS][j] = rc_ctrl[TEMP].key_temp & i; - // 如果当前按下且上一次没按下,切换按键状态.一些模式要通过按键状态而不是按键是否按下来确定(实际上是大部分) - rc_ctrl[TEMP].key[KEY_STATE][j] = rc_ctrl[TEMP].key[KEY_PRESS][j] && !rc_ctrl[1].key[KEY_PRESS][j]; - // 检查是否有组合键按下 - if (rc_ctrl[TEMP].key_temp & 0x0001u << Key_Shift) // 按下ctrl - rc_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT][j] = rc_ctrl[TEMP].key_temp & i; - if (rc_ctrl[TEMP].key_temp & 0x0001u << Key_Ctrl) // 按下shift - rc_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL][j] = rc_ctrl[TEMP].key_temp & i; + if (((*(uint16_t *)&rc_ctrl[TEMP].key[KEY_PRESS] & j) == j) && ((*(uint16_t *)&rc_ctrl[1].key[KEY_PRESS] & j) == 0) && ((*(uint16_t *)&rc_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL] & j) != j) && ((*(uint16_t *)&rc_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT] & j) != j)) + { + rc_ctrl[TEMP].key_count[KEY_PRESS][i]++; + + if (rc_ctrl[TEMP].key_count[KEY_PRESS][i] >= 240) + { + rc_ctrl[TEMP].key_count[KEY_PRESS][i] = 0; + } + + } + if (((*(uint16_t *)&rc_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL] & j) == j) && ((*(uint16_t *)&rc_ctrl[1].key[KEY_PRESS_WITH_CTRL] & j) == 0)) + { + rc_ctrl[TEMP].key_count[KEY_PRESS_WITH_CTRL][i]++; + + if (rc_ctrl[TEMP].key_count[KEY_PRESS_WITH_CTRL][i] >= 240) + { + rc_ctrl[TEMP].key_count[KEY_PRESS_WITH_CTRL][i] = 0; + } + } + if (((*(uint16_t *)&rc_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT] & j) == j) && ((*(uint16_t *)&rc_ctrl[1].key[KEY_PRESS_WITH_SHIFT] & j) == 0)) + { + rc_ctrl[TEMP].key_count[KEY_PRESS_WITH_SHIFT][i]++; + + if (rc_ctrl[TEMP].key_count[KEY_PRESS_WITH_SHIFT][i] >= 240) + { + rc_ctrl[TEMP].key_count[KEY_PRESS_WITH_SHIFT][i] = 0; + } + } } - // 位域的按键值解算,直接memcpy即可,注意小端低字节在前,即lsb在第一位,msb在最后. 尚未测试 - // *(uint16_t *)&rc_ctrl[TEMP].key_test[KEY_PRESS] = (uint16_t)(sbus_buf[14] | (sbus_buf[15] << 8)); - // *(uint16_t *)&rc_ctrl[TEMP].key_test[KEY_STATE] = *(uint16_t *)&rc_ctrl[TEMP].key_test[KEY_PRESS] & ~(*(uint16_t *)&(rc_ctrl[1].key_test[KEY_PRESS])); - // if (rc_ctrl[TEMP].key_test[KEY_PRESS].ctrl) - // rc_ctrl[TEMP].key_test[KEY_PRESS_WITH_CTRL] = rc_ctrl[TEMP].key_test[KEY_PRESS]; - // if (rc_ctrl[TEMP].key_test[KEY_PRESS].shift) - // rc_ctrl[TEMP].key_test[Key_Shift] = rc_ctrl[TEMP].key_test[KEY_PRESS]; + memcpy(&rc_ctrl[1], &rc_ctrl[TEMP], sizeof(RC_ctrl_t)); // 保存上一次的数据,用于按键持续按下和切换的判断 } /** @@ -126,5 +146,4 @@ uint8_t RemotecontrolIsOnline() if (rc_init_flag) return DaemonIsOnline(rc_daemon_instance); return 0; - } \ No newline at end of file diff --git a/modules/remote/remote_control.h b/modules/remote/remote_control.h index d2c2187..8407ddd 100644 --- a/modules/remote/remote_control.h +++ b/modules/remote/remote_control.h @@ -24,8 +24,8 @@ // 获取按键操作 #define KEY_PRESS 0 #define KEY_STATE 1 -#define KEY_PRESS_WITH_CTRL 2 -#define KEY_PRESS_WITH_SHIFT 3 +#define KEY_PRESS_WITH_CTRL 1 +#define KEY_PRESS_WITH_SHIFT 2 // 检查接收值是否出错 #define RC_CH_VALUE_MIN ((uint16_t)364) @@ -42,6 +42,9 @@ #define switch_is_up(s) (s == RC_SW_UP) #define LEFT_SW 1 // 左侧开关 #define RIGHT_SW 0 // 右侧开关 +//键盘状态的宏 +#define key_is_press(s) (s == 1) +#define key_not_press(s) (s == 0) /* ----------------------- PC Key Definition-------------------------------- */ // 对应key[x][0~16],获取对应的键;例如通过key[KEY_PRESS][Key_W]获取W键是否按下,后续改为位域后删除 @@ -105,11 +108,10 @@ typedef struct uint8_t press_l; uint8_t press_r; } mouse; + + Key_t key[3]; // 改为位域后的键盘索引,空间减少8倍,速度增加16~倍 - uint16_t key_temp; - uint8_t key[4][16]; // 当前使用的键盘索引 - // Key_t key_test[4]; // 改为位域后的键盘索引,空间减少8倍,速度增加16~倍 - + uint8_t key_count[3][16]; } RC_ctrl_t; /* ------------------------- Internal Data ----------------------------------- */ From 3f0325df28b919dc0b8cba9dc12adfa0f2b52b6c Mon Sep 17 00:00:00 2001 From: chenfu <2412777093@qq.com> Date: Mon, 27 Mar 2023 22:05:54 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=94=AE=E9=BC=A0?= =?UTF-8?q?=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ps_handle/ps_handle.c | 115 ++++++++++++++++++++++++++++++++++ modules/ps_handle/ps_handle.h | 38 +++++++++++ 2 files changed, 153 insertions(+) create mode 100644 modules/ps_handle/ps_handle.c create mode 100644 modules/ps_handle/ps_handle.h diff --git a/modules/ps_handle/ps_handle.c b/modules/ps_handle/ps_handle.c new file mode 100644 index 0000000..8928512 --- /dev/null +++ b/modules/ps_handle/ps_handle.c @@ -0,0 +1,115 @@ +#include "ps_handle.h" +uint8_t PS2_RawData[9] = {0}; +PS2_Instance PS2_Data = {0}; +void PS2_CS(uint8_t Val) +{ + if (Val) + HAL_GPIO_WritePin(PS2_CS_GPIOx, PS2_CS_Pin, GPIO_PIN_SET); + else + HAL_GPIO_WritePin(PS2_CS_GPIOx, PS2_CS_Pin, GPIO_PIN_RESET); +} +void PS2_CLK(uint8_t Val) +{ + if (Val) + HAL_GPIO_WritePin(PS2_CLK_GPIOx, PS2_CLK_Pin, GPIO_PIN_SET); + else + HAL_GPIO_WritePin(PS2_CLK_GPIOx, PS2_CLK_Pin, GPIO_PIN_RESET); +} +void PS2_DO(uint8_t Val) +{ + if (Val) + HAL_GPIO_WritePin(PS2_DO_GPIOx, PS2_DO_Pin, GPIO_PIN_SET); + else + HAL_GPIO_WritePin(PS2_DO_GPIOx, PS2_DO_Pin, GPIO_PIN_RESET); +} +uint8_t PS2_Read_DI() +{ + return HAL_GPIO_ReadPin(PS2_DI_GPIOx, PS2_DI_Pin); +} +void PS2_Delay() +{ + for (int i = 0; i < 0xBf; i++) + __NOP(); +} +uint8_t PS2_ReadWrite_Byte(uint8_t TxData) +{ + uint8_t TX = TxData; + uint8_t RX = 0; + for (int i = 0; i < 8; i++) + { + if (TX & 0x01) + PS2_DO(1); + else + PS2_DO(0); + TX >>= 1; + PS2_CLK(1); + PS2_Delay(); + PS2_CLK(0); + RX >>= 1; + RX |= (PS2_Read_DI() << 7); + PS2_Delay(); + PS2_CLK(1); + PS2_Delay(); + } + return RX; +} + +static void PS2_Decode() +{ + if (PS2_RawData[2] == 0x5A) + { + PS2_Data.Key_Select = (~PS2_RawData[3] >> 0) & 0x01; //选择键 + PS2_Data.Key_Start = (~PS2_RawData[3] >> 3) & 0x01; //开始键 + + //左侧按键 + PS2_Data.Key_L_Up = (~PS2_RawData[3] >> 4) & 0x01; + PS2_Data.Key_L_Right = (~PS2_RawData[3] >> 5) & 0x01; + PS2_Data.Key_L_Down = (~PS2_RawData[3] >> 6) & 0x01; + PS2_Data.Key_L_Left = (~PS2_RawData[3] >> 7) & 0x01; + + //后侧按键 + PS2_Data.Key_L2 = (~PS2_RawData[4] >> 0) & 0x01; + PS2_Data.Key_R2 = (~PS2_RawData[4] >> 1) & 0x01; + PS2_Data.Key_L1 = (~PS2_RawData[4] >> 2) & 0x01; + PS2_Data.Key_R1 = (~PS2_RawData[4] >> 3) & 0x01; + + //右侧按键 + PS2_Data.Key_R_Up = (~PS2_RawData[4] >> 4) & 0x01; + PS2_Data.Key_R_Right = (~PS2_RawData[4] >> 5) & 0x01; + PS2_Data.Key_R_Down = (~PS2_RawData[4] >> 6) & 0x01; + PS2_Data.Key_R_Left = (~PS2_RawData[4] >> 7) & 0x01; + + if (PS2_RawData[1] == 0x41) + { //无灯模式(摇杆值八向) + PS2_Data.Rocker_LX = 127 * (PS2_Data.Key_L_Right - PS2_Data.Key_L_Left); + PS2_Data.Rocker_LY = 127 * (PS2_Data.Key_L_Up - PS2_Data.Key_L_Down); + + PS2_Data.Rocker_RX = 127 * (PS2_Data.Key_R_Right - PS2_Data.Key_R_Left); + PS2_Data.Rocker_RY = 127 * (PS2_Data.Key_R_Up - PS2_Data.Key_R_Down); + } + else if (PS2_RawData[1] == 0x73) + { //红灯模式(摇杆值模拟) + + //摇杆按键 + PS2_Data.Key_Rocker_Left = (~PS2_RawData[3] >> 1) & 0x01; + PS2_Data.Key_Rocker_Right = (~PS2_RawData[3] >> 2) & 0x01; + + //摇杆值 + PS2_Data.Rocker_LX = PS2_RawData[7] - 0x80; + PS2_Data.Rocker_LY = -1 - (PS2_RawData[8] - 0x80); + PS2_Data.Rocker_RX = PS2_RawData[5] - 0x80; + PS2_Data.Rocker_RY = -1 - (PS2_RawData[6] - 0x80); + } + } +} +void PS2_Read_Data(void) +{ + PS2_CS(0); + PS2_RawData[0] = PS2_ReadWrite_Byte(0x01); // 0 + PS2_RawData[1] = PS2_ReadWrite_Byte(0x42); // 1 + for (int i = 2; i < 9; i++) + PS2_RawData[i] = PS2_ReadWrite_Byte(0xff); + PS2_CS(1); + PS2_Decode(); +} + diff --git a/modules/ps_handle/ps_handle.h b/modules/ps_handle/ps_handle.h new file mode 100644 index 0000000..bd35311 --- /dev/null +++ b/modules/ps_handle/ps_handle.h @@ -0,0 +1,38 @@ +#ifndef PS_HANDLE_H +#define PS_HANDLE_H + +#include "bsp_spi.h" +#include "bsp_gpio.h" +#include "bsp_dwt.h" + +#define PS2_CS_GPIOx GPIOB +#define PS2_CS_Pin GPIO_PIN_12 + +#define PS2_CLK_GPIOx GPIOB +#define PS2_CLK_Pin GPIO_PIN_13 + +#define PS2_DO_GPIOx GPIOB +#define PS2_DO_Pin GPIO_PIN_15 + +#define PS2_DI_GPIOx GPIOB +#define PS2_DI_Pin GPIO_PIN_14 + +typedef struct +{ + uint8_t A_D; //模拟(红灯)为1 数字(无灯)为0 + int8_t Rocker_RX, Rocker_RY, Rocker_LX, Rocker_LY; //摇杆值(模拟状态为实际值0-0xFF)(数字态为等效的值0,0x80,0xFF) + //按键值0为未触发,1为触发态 + uint8_t Key_L1, Key_L2, Key_R1, Key_R2; //后侧大按键 + uint8_t Key_L_Right, Key_L_Left, Key_L_Up, Key_L_Down; //左侧按键 + uint8_t Key_R_Right, Key_R_Left, Key_R_Up, Key_R_Down; //右侧按键 + uint8_t Key_Select; //选择键 + uint8_t Key_Start; //开始键 + uint8_t Key_Rocker_Left, Key_Rocker_Right; //摇杆按键 + +} PS2_Instance; + + + + + +#endif // !PS_HANDLE_H#define PS_HANDLE_H