#include "app_key.h" #include /* 按键行为说明: * K1 单击 -> 回零(朝光电开关方向,低速) * K2 长按/松开 -> JOG+ 启动 / 减速停止 * K3 长按/松开 -> JOG- 启动 / 减速停止 * K4 单击 -> 速度档位循环 * K5 单击 -> 立即停止 */ #define SPEED_LEVEL_COUNT (3u) #define JOG_SPEED_LOW_MM_S (5.0f) #define JOG_SPEED_MID_MM_S (25.0f) #define JOG_SPEED_HIGH_MM_S (60.0f) #define HOME_SPEED_MM_S (5.0f) #define HOME_TRAVEL_MM (500.0f) static const float s_speed_levels[SPEED_LEVEL_COUNT] = { JOG_SPEED_LOW_MM_S, JOG_SPEED_MID_MM_S, JOG_SPEED_HIGH_MM_S, }; static uint8_t s_speed_idx = 0u; static uint8_t s_jog_key = KEY_NONE; static uint8_t s_home_active = 0u; /* 光电零位开关:低电平有效。 */ static uint8_t key_home_switch_active(void) { return (HAL_GPIO_ReadPin(X_ZERO_GPIO_Port, X_ZERO_Pin) == GPIO_PIN_RESET) ? 1u : 0u; } /* 根据方向和已走步数估算当前位置(mm)。 */ static float key_estimate_pos_mm(const Stepper_t *stepper) { float moved_mm = (float)stepper->step_count / STEPS_PER_MM; if (stepper->dir == GPIO_PIN_RESET) { return last_move_start_pos_mm + moved_mm; } return last_move_start_pos_mm - moved_mm; } static void local_motion_start(Stepper_t *stepper, GPIO_PinState dir, float speed_mm_s, float travel_mm) { if (stepper == NULL) { return; } if (speed_mm_s < 0.1f) { speed_mm_s = 0.1f; } if (stepper->state != STOP) { Int_TMC2209_stop(); stepper->state = STOP; } stepper->dir = dir; stepper->distance = travel_mm; stepper->speed = (uint16_t)speed_mm_s; stepper->acc = 50; stepper->dec = 50; stepper->start_speed = 1.0f; stepper->run_flag = 1u; last_move_start_pos_mm = current_absolute_pos_mm; Int_TMC2209_start(stepper, &encoder_1); } /* 将当前运动切换为减速停止。 */ static void local_motion_stop_decel(Stepper_t *stepper) { if (stepper == NULL) { return; } if (stepper->state == STOP) { stepper->run_flag = 0u; return; } stepper->total_step = stepper->step_count + stepper->acc_step; if (stepper->state == ACCELERATE || stepper->state == CONSTANT) { stepper->state = DECELERATE; } stepper->run_flag = 0u; } /* 立即停止通道:用于 STOP 按键和 HOME 完成后的收尾。 */ static void local_motion_estop(Stepper_t *stepper) { if (stepper == NULL) { return; } Int_TMC2209_stop(); stepper->state = STOP; stepper->run_flag = 0u; s_jog_key = KEY_NONE; s_home_active = 0u; } /* 运行时守卫:运动中执行限位判断与 HOME 触发判断。 */ static void key_guard_check(Stepper_t *stepper) { float est_pos_mm = 0.0f; uint8_t xzero_active = 0u; if (stepper == NULL || stepper->state == STOP) { return; } est_pos_mm = key_estimate_pos_mm(stepper); current_absolute_pos_mm = est_pos_mm; xzero_active = key_home_switch_active(); if ((stepper->x_zero == 1u) && (xzero_active == 0u)) { /* 若引脚当前未触发,清除可能因抖动造成的 EXTI 残留置位。 */ stepper->x_zero = 0u; } if (s_home_active) { if ((stepper->x_zero == 1u) && (xzero_active == 1u)) { local_motion_estop(stepper); stepper->x_zero = 0u; debug_printf("[KEY] HOME done"); } return; } if ((s_jog_key == KEY_2) && (est_pos_mm >= SOFT_LIMIT_MAX_MM)) { local_motion_stop_decel(stepper); current_absolute_pos_mm = SOFT_LIMIT_MAX_MM; debug_printf("[KEY] JOG+ reach soft limit %.1f mm", SOFT_LIMIT_MAX_MM); } else if ((s_jog_key == KEY_3) && ((stepper->x_zero == 1u) && (xzero_active == 1u))) { local_motion_stop_decel(stepper); stepper->x_zero = 0u; debug_printf("[KEY] JOG- reach home boundary"); } } void App_key_run(Stepper_t *stepper) { Int_Key_Task(); key_guard_check(stepper); KeyAction_t action; while (Int_Key_PopAction(&action)) { switch (action.key) { case KEY_1: if (action.evt == KEY_EVT_CLICK) { s_jog_key = KEY_NONE; s_home_active = 1u; stepper->x_zero = 0u; local_motion_start(stepper, GPIO_PIN_SET, HOME_SPEED_MM_S, HOME_TRAVEL_MM); debug_printf("[KEY] HOME start @ %.1f mm/s", HOME_SPEED_MM_S); } break; case KEY_2: if (action.evt == KEY_EVT_LONG_START) { s_home_active = 0u; s_jog_key = KEY_2; local_motion_start(stepper, GPIO_PIN_RESET, s_speed_levels[s_speed_idx], HOME_TRAVEL_MM); debug_printf("[KEY] JOG+ start @ %.1f mm/s", s_speed_levels[s_speed_idx]); } else if (action.evt == KEY_EVT_RELEASE && s_jog_key == KEY_2) { local_motion_stop_decel(stepper); s_jog_key = KEY_NONE; debug_printf("[KEY] JOG+ release -> decel stop"); } break; case KEY_3: if (action.evt == KEY_EVT_LONG_START) { s_home_active = 0u; s_jog_key = KEY_3; stepper->x_zero = 0u; local_motion_start(stepper, GPIO_PIN_SET, s_speed_levels[s_speed_idx], HOME_TRAVEL_MM); debug_printf("[KEY] JOG- start @ %.1f mm/s", s_speed_levels[s_speed_idx]); } else if (action.evt == KEY_EVT_RELEASE && s_jog_key == KEY_3) { local_motion_stop_decel(stepper); s_jog_key = KEY_NONE; debug_printf("[KEY] JOG- release -> decel stop"); } break; case KEY_4: if (action.evt == KEY_EVT_CLICK) { s_speed_idx++; if (s_speed_idx >= SPEED_LEVEL_COUNT) { s_speed_idx = 0u; } debug_printf("[KEY] SPEED -> %.1f mm/s", s_speed_levels[s_speed_idx]); } break; case KEY_5: if (action.evt == KEY_EVT_CLICK) { local_motion_estop(stepper); debug_printf("[KEY] STOP"); } break; default: break; } } }