11
93
469
中级会员
#include <STC8.H> #include <intrins.h> // 硬件定义 #define KEY_PIN P32 // 按键引脚P3.2 #define POWER_PIN P55 // 电源控制引脚 sbit LED = P5^5; // 状态指示灯 // 时间阈值定义(基于主循环周期10ms) #define DEBOUNCE_TIME 3 // 30ms消抖 #define LONG_PRESS_TIME 200 // 200*10ms=2秒 #define DOUBLE_CLICK_TIME 30 // 30*10ms=300ms // 全局状态变量 bit power_flag = 0; // 电源状态 0:关机 1:开机 unsigned char key_state = 0; // 按键状态机 unsigned int press_counter = 0; // 按下计时 unsigned int release_counter = 0;// 释放计时 bit click_count = 0; // 单击计数 // 延时函数(24MHz粗略延时) void delay_ms(unsigned int ms) { unsigned int i, j; for(i=ms; i>0; i--) for(j=6000; j>0; j--); // 粗略调整延时 } // 系统进入低功耗模式 void enter_low_power() { POWER_PIN = 0; // 关闭外设电源 P3M0 &= ~0x04; P3M1 |= 0x04; // P3.2高阻输入 PCON |= 0x02; // 进入掉电模式 _nop_(); _nop_(); } // 外部中断0初始化(下降沿触发) void INT0_Init() { INT0 = 1; // 使能INT0 IT0 = 1; // 下降沿触发 EX0 = 1; // 允许中断 EA = 1; // 总中断使能 } // INT0中断服务函数(唤醒+长按检测) void exint0() interrupt 0 { unsigned int hold_time = 0; while(KEY_PIN == 0) { // 保持循环直到按键释放 delay_ms(10); if(++hold_time > (LONG_PRESS_TIME*10)) { // 2秒长按 power_flag = 1; // 开机 POWER_PIN = 1; // 开启外设电源 P3M0 = 0x00; // P3.2准双向模式 P3M1 = 0x00; return; } } } // 按键扫描函数(状态机实现) void key_scan() { static bit last_state = 1; static unsigned int debounce_counter = 0; // 状态机处理 switch(key_state) { case 0: // 初始状态 if(!KEY_PIN && last_state) { // 检测到下降沿 debounce_counter = 0; key_state = 1; } break; case 1: // 消抖检测 if(++debounce_counter > DEBOUNCE_TIME) { if(!KEY_PIN) { // 确认有效按下 key_state = 2; press_counter = 0; } else { key_state = 0; } } break; case 2: // 按下状态 press_counter++; if(KEY_PIN) { // 检测释放 key_state = 3; release_counter = 0; } else if(press_counter > LONG_PRESS_TIME) { // 长按处理 if(power_flag) { // 开机状态下长按关机 power_flag = 0; enter_low_power(); } key_state = 0; } break; case 3: // 释放状态 release_counter++; if(release_counter > DOUBLE_CLICK_TIME) { // 单击确认 click_count = 1; key_state = 0; } else if(!KEY_PIN) { // 第二次按下 click_count++; key_state = 4; } break; case 4: // 双击确认 if(++debounce_counter > DEBOUNCE_TIME) { if(KEY_PIN) { // 释放确认 click_count = (click_count >= 2) ? 2 : 0; key_state = 0; } } break; } last_state = KEY_PIN; // 更新状态 } // 主函数 void main() { // 初始化配置 P_SW2 |= 0x80; // 开启扩展寄存器访问 INT0_Init(); // 外部中断初始化 POWER_PIN = 0; // 默认关闭外设 enter_low_power(); // 初始进入低功耗 while(1) { if(power_flag) { key_scan(); // 仅在开机时扫描按键 // 事件处理 if(click_count == 1) { // 单击事件处理 LED = ~LED; click_count = 0; } else if(click_count == 2) { // 双击事件处理 // 添加双击功能代码 click_count = 0; } // 其他应用代码... } else { PCON |= 0x02; // 确保进入掉电模式 _nop_(); } } }复制代码
使用道具 举报 送花
3
1160
1031
等待验证会员
39
2006
6841
论坛元老
wnag*** 发表于 2025-3-7 20:42 如果你的按键只是接在IO口上,那么长按开机就是假的,比如有屏幕时,没有长按,屏幕不亮,长按后,屏幕有 ...
乘风*** 发表于 2025-3-7 19:12 布丁橘长教学视频第19期有介绍:
2
106
262
17
446
1173
金牌会员
7
22
1063
本版积分规则 发表回复 回帖后跳转到最后一页
|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )
GMT+8, 2025-5-2 01:47 , Processed in 0.126471 second(s), 112 queries .
Powered by Discuz! X3.5
© 2001-2025 Discuz! Team.