Files
CHJ/user/Device/key_power.c
2026-03-20 21:16:58 +08:00

178 lines
5.9 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
}