2026-03-02 14:57:34 +08:00
|
|
|
|
#include "app_key.h"
|
2026-02-28 17:36:05 +08:00
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* 按键行为说明:
|
|
|
|
|
|
* 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();
|
2026-03-02 14:57:34 +08:00
|
|
|
|
if (xzero_active == 1u)
|
2026-02-28 17:36:05 +08:00
|
|
|
|
{
|
2026-03-02 14:57:34 +08:00
|
|
|
|
/* 引脚有效即锁存命中,避免短脉冲漏检。 */
|
|
|
|
|
|
stepper->x_zero = 1u;
|
2026-02-28 17:36:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (s_home_active)
|
|
|
|
|
|
{
|
2026-03-02 14:57:34 +08:00
|
|
|
|
if (stepper->x_zero == 1u)
|
2026-02-28 17:36:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
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) &&
|
2026-03-02 14:57:34 +08:00
|
|
|
|
(stepper->x_zero == 1u))
|
2026-02-28 17:36:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|