关于独立按键的单击、双击、长按开关机
#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_TIME30 // 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_();
}
}
}
我使用的是开天斧,只能识别单击,识别不了双击是为啥 在嵌入式系统中,独立按键的单击、双击和长按功能实现是常见的需求。以下代码片段展示了基于51单片机的按键状态识别逻辑,适用于开关机等控制场景。
1. **硬件定义**:按键引脚定义在`P3.2`,电源控制引脚在`P5.5`,状态指示灯通过`P5.5`控制。
2. **时间阈值**:消抖时间为30ms(`DEBOUNCE_TIME=3`),长按时间为2秒(`LONG_PRESS_TIME=200`)。
3. **逻辑实现**:通过主循环周期(10ms)检测按键状态,消除抖动后,根据按键持续时间判断单击、双击或长按。长按触发开关机,单击或双击执行相应功能。
4. **注意事项**:确保按键消抖处理充分,避免误触发;长按时间可根据实际需求调整。
此实现方案简洁高效,适用于资源有限的嵌入式系统。
[本文内容由国芯人工智能辅助生成,仅供参考] 还有里面的长按开机可以实现吗,有没有大佬指点一下 布丁橘长教学视频第19期有介绍:
视频教程-32位8051-屠龙刀-第0-100期合集-布丁橘长
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=463
(出处: 国芯技术交流网站)
wnagming 发表于 2025-3-7 20:42
如果你的按键只是接在IO口上,那么长按开机就是假的,比如有屏幕时,没有长按,屏幕不亮,长按后,屏幕有 ...
是的,其实就是相当于长按后进入低功耗模式,然后在低功耗模式下只有长按才能唤醒,单击双击无效 乘风飞扬 发表于 2025-3-7 19:12
布丁橘长教学视频第19期有介绍:
我看看,谢谢{:4_168:} {:qiang:} 中断里还死等 bit click_count = 0; // 单击计数
这个是不是定义错了。
页:
[1]
2