178 lines
5.9 KiB
C
178 lines
5.9 KiB
C
#include "../main/SystemInclude.h"
|
||
|
||
// 全局变量(静态,仅本文件访问)
|
||
Device_StateTypeDef g_device_state = DEVICE_STATE_OFF; // 初始状态:关机
|
||
uint32_t g_key_press_time = 0; // 按键按下累计时间(单位:扫描周期)
|
||
uint8_t g_key_last_state = 0; // 按键上一次状态(0=未按下,1=按下)
|
||
|
||
extern bool g_SystemStartupComplete;
|
||
|
||
// 单位按键按下标志位
|
||
volatile uint8_t key_press_flag = 0;
|
||
|
||
// 1 = 定时器时间到,请求关机;0 = 无关机请求
|
||
volatile uint8_t g_auto_shutdown_flag = 0;
|
||
|
||
// 引脚初始化:PA0(下拉输入)、PA1(推挽输出)
|
||
void Key_Power_Init(void)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStruct;
|
||
|
||
// PA0:下拉输入(按键检测)
|
||
GPIO_InitStruct.Pin = KEY1_PIN;
|
||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||
GPIO_InitStruct.Current = GPIO_CURRENT_2mA;
|
||
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||
GPIO_InitStruct.SchmittTrigger = ENABLE;
|
||
GPIO_InitStruct.Alternate = GPIOx_AF_GPIO; // // AF为普通IO
|
||
LHL_GPIO_Init(KEY1_PORT, &GPIO_InitStruct);
|
||
|
||
// PA1:推挽输出(电源控制)
|
||
GPIO_InitStruct.Pin = POWER_CTRL_PIN;
|
||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||
GPIO_InitStruct.Current = GPIO_CURRENT_2mA;
|
||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||
GPIO_InitStruct.SchmittTrigger = ENABLE;
|
||
GPIO_InitStruct.Alternate = GPIOx_AF_GPIO; // // AF为普通IO
|
||
LHL_GPIO_Init(POWER_CTRL_PORT, &GPIO_InitStruct);
|
||
|
||
// 初始状态:关机→PA1拉低(关闭外部电源)
|
||
LHL_GPIO_WritePin(POWER_CTRL_PORT, POWER_CTRL_PIN, GPIO_PIN_RESET);
|
||
g_device_state = DEVICE_STATE_OFF;
|
||
|
||
// 单位切换检测脚:上拉输入
|
||
GPIO_InitStruct.Pin = UnitKEY_PIN;
|
||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||
GPIO_InitStruct.Current = GPIO_CURRENT_2mA;
|
||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||
GPIO_InitStruct.SchmittTrigger = ENABLE;
|
||
GPIO_InitStruct.Alternate = GPIOx_AF_GPIO; // // AF为普通IO
|
||
LHL_GPIO_Init(UnitKEY_PORT, &GPIO_InitStruct);
|
||
|
||
|
||
}
|
||
|
||
// 设备开机处理
|
||
static void Device_Start(void) {
|
||
LHL_GPIO_WritePin(POWER_CTRL_PORT, POWER_CTRL_PIN,GPIO_PIN_SET); // PA1拉高→外部电源启动
|
||
delay_ms(100); // 等待电源稳定
|
||
g_device_state = DEVICE_STATE_ON;
|
||
g_key_press_time = 0; // 重置按键计时
|
||
|
||
g_auto_shutdown_flag = 0;
|
||
}
|
||
|
||
// 设备关机处理
|
||
static void Device_Shutdown(void) {
|
||
LHL_GPIO_WritePin(POWER_CTRL_PORT, POWER_CTRL_PIN,GPIO_PIN_RESET); // PA1拉低→外部电源关闭
|
||
delay_ms(100); // 等待电源完全关闭
|
||
g_device_state = DEVICE_STATE_OFF;
|
||
g_key_press_time = 0;
|
||
}
|
||
|
||
// 增加一个标志位,用于记录长按是否已经触发
|
||
static bool g_key_long_pressed_flag = false;
|
||
// 增加消抖计数器
|
||
static uint16_t g_key_debounce_count = 0;
|
||
|
||
void Key_Scan_Task(void) {
|
||
// 1. 读取当前按键状态
|
||
uint8_t key_current_state = LHL_GPIO_ReadPin(KEY1_PORT, KEY1_PIN);
|
||
|
||
// 2. 简单的消抖处理:当读取到状态与上次一致时,计数器增加;否则重置
|
||
if (key_current_state == g_key_last_state) {
|
||
if (g_key_debounce_count < 65535) g_key_debounce_count++;
|
||
} else {
|
||
g_key_debounce_count = 0;
|
||
g_key_last_state = key_current_state; // 更新状态以便下一次比较
|
||
}
|
||
|
||
// 3. 只有消抖计数器达到阈值(例如5次,即50ms)才认为状态有效
|
||
if (g_key_debounce_count < 2) {
|
||
return;
|
||
}
|
||
|
||
// 如果设备处于开机状态,且检测到自动关机标志被置 1
|
||
if (g_device_state == DEVICE_STATE_ON) {
|
||
if (g_auto_shutdown_flag == 1) {
|
||
Device_Shutdown(); // 执行关机
|
||
g_auto_shutdown_flag = 0; // 清除标志位,防止死循环关机
|
||
// 注意:这里不需要 break,因为关机后状态变为 OFF,下面的 switch 不会再执行 ON 的分支
|
||
}
|
||
}
|
||
// 4. 状态机处理
|
||
switch (g_device_state) {
|
||
case DEVICE_STATE_OFF:
|
||
if (key_current_state == 1) {
|
||
// 按键按下
|
||
if (!g_key_long_pressed_flag) {
|
||
g_key_press_time++;
|
||
// 长按阈值检查 (40 * 10ms = 400ms)
|
||
if (g_key_press_time >= (KEY_PRESS_TIME_LONG / KEY_SCAN_INTERVAL)) {
|
||
Device_Start(); // 执行开机
|
||
g_key_long_pressed_flag = true; // 标记长按已触发,防止重复执行
|
||
}
|
||
}
|
||
} else {
|
||
// 按键松开
|
||
g_key_press_time = 0;
|
||
g_key_long_pressed_flag = false; // 重置长按标志
|
||
}
|
||
break;
|
||
|
||
case DEVICE_STATE_ON:
|
||
if (key_current_state == 1) {
|
||
// 按键按下
|
||
if (!g_key_long_pressed_flag) {
|
||
g_key_press_time++;
|
||
if (g_key_press_time >= (KEY_PRESS_TIME_LONG / KEY_SCAN_INTERVAL)) {
|
||
Device_Shutdown(); // 执行关机
|
||
g_key_long_pressed_flag = true; // 标记长按已触发
|
||
}
|
||
}
|
||
} else {
|
||
// 按键松开
|
||
g_key_press_time = 0;
|
||
g_key_long_pressed_flag = false; // 重置长按标志
|
||
}
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
// 获取当前设备状态
|
||
Device_StateTypeDef Get_Device_State(void) {
|
||
return g_device_state;
|
||
}
|
||
|
||
void Unit_key(void)
|
||
{
|
||
static uint8_t key_state = 0; // 0: 释放/消抖中, 1: 已确认按下
|
||
static uint16_t key_count = 0;
|
||
uint8_t key_level = LHL_GPIO_ReadPin(UnitKEY_PORT,UnitKEY_PIN);
|
||
switch (key_state)
|
||
{
|
||
case 0:
|
||
if (key_level == 0) {
|
||
key_count++;
|
||
if (key_count >= 3) {
|
||
key_state = 1;
|
||
key_press_flag = 1;// 触发事件:告诉主循环有按键按下
|
||
key_count=0;
|
||
}
|
||
} else {
|
||
key_count = 0; // 只要没按下,就一直清零
|
||
}
|
||
break;
|
||
|
||
case 1:
|
||
if (key_level == 1) {// 检测到松开
|
||
key_state = 0;
|
||
key_count = 0;// 复位计数,准备下一次
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|