4
66
977
高级会员
使用道具 举报 送花
11
93
469
中级会员
Ayb_*** 发表于 2025-3-10 08:46 中断里还死等
huaru*** 发表于 2025-3-11 14:04 还不错,这适用于单独工作的按键,如果有多个工作似乎不实用,比如如果有称重模块,计数模块等等,那个延时 ...
17
446
1173
金牌会员
wsz*** 发表于 2025-3-11 16:40 中断只开机长按使用,应该没事吧
0
37
1334
wsz*** 发表于 2025-3-11 16:41 多个模块就需要用定时器了,先做个最基础的起来,后面可以再加
1
63
521
#include <STC8H.H> #include <intrins.h> // 硬件配置 sbit KEY_PIN = P3^2; // 按键接P3.2 sbit LIGHT=P1^0; // typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; // 宏定义 #define DEBOUNCE_MS 20 // 消抖时间20ms #define DOUBLE_PRESS 300 // 双击间隔300ms #define LONG_PRESS 10000 #define MAIN_LOOP_CYCLE 10 // 主循环周期10ms #define MAIN_Fosc 24000000L //定义主时钟 // 全局变量 static u8 key_event = 0; // 按键事件(1=单击,2=双击) static u8 key_state = 0; // 按键状态机 static u8 power_flag=0; static u8 wake_flag=0; u8 mode=0; void power_off(); void delay_ms(u16 ms) { u16 i; do { i = MAIN_Fosc / 10000; while(--i) ; }while(--ms); } void key_scan() { static u16 release_timer = 0; static u8 click_count = 0; static bit last_pin_state = 1; static u16 press_counter=0; // 状态机处理 switch(key_state) { case 0: // 初始状态 if(KEY_PIN == 0 && last_pin_state == 1)// 检测到下降沿 { delay_ms(DEBOUNCE_MS); if(KEY_PIN == 0) { // 确认按下 key_state = 1; click_count+=1; press_counter=0; } } break; case 1: // 已按下,等待释放 press_counter+=MAIN_LOOP_CYCLE; if(KEY_PIN == 1) // 检测到释放 { delay_ms(DEBOUNCE_MS); if(KEY_PIN == 1) { key_state = 2; release_timer = 0; // 启动双击检测窗口 } } else if(press_counter>LONG_PRESS) { key_event=3; //长按 click_count=0; key_state=0; press_counter=0; } break; case 2: // 释放状态,检测双击窗口 release_timer += MAIN_LOOP_CYCLE; if(release_timer >= DOUBLE_PRESS) { // 超时处理 if(click_count == 1) { key_event = 1; // 单击 } click_count = 0; key_state = 0; } else if(KEY_PIN == 0) { // 再次按下 delay_ms(DEBOUNCE_MS); if(KEY_PIN == 0) { click_count+=1; key_state = 3; } } break; case 3: // 第二次按下,等待释放 if(KEY_PIN == 1) { delay_ms(DEBOUNCE_MS); if(KEY_PIN == 1) { if(click_count >= 2) { key_event = 2; // 双击 } click_count = 0; key_state = 0; } } break; } last_pin_state = KEY_PIN; // 更新引脚状态 } void power_off() { power_flag=0; //关机标志置0 P1IE=0X00; P2IE=0X00; P3IE=0X04; //关闭除P32外的数字输入 IT0=1; EX0=1; EA=1; //关机时打开外部中断,进行初始化,下降沿触发 PCON |=PD; //进入掉电模式 NOP1(); } void wake_init() { P1M0 = 0x00; P1M1 = 0x00; P2M0 = 0x00; P2M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00;//初始化端口,设置为双向口 EX0=0; EA=0; //开机时关闭中断 wake_flag=0; //唤醒初始化完成,唤醒标志置0 } /**/ // 主函数 void main() { power_off(); //上电默认为低功耗模式 while(1) { key_scan(); if(power_flag==1) // { if(wake_flag==1)wake_init(); P25=0; switch(key_event) { case 1: P21=~P21; key_event=0; break; case 2: P24=~P24; key_event=0; break; case 3: P25=1;power_off(); key_event=0; break; } } else{power_off();P25=1;} delay_ms(10); } } void exint0() interrupt 0 { u16 hold_cnt = 0; // 改为16位计数器 // 长按检测(不依赖延时函数) while(KEY_PIN == 0) { if(++hold_cnt > (LONG_PRESS/10)) { // 每10ms计数 power_flag = 1; wake_flag=1; P23=~P23; return; } delay_ms(10); // 仅用于粗略计时 } }复制代码
本版积分规则 发表回复 回帖后跳转到最后一页
|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )
GMT+8, 2025-5-2 01:54 , Processed in 0.124729 second(s), 101 queries .
Powered by Discuz! X3.5
© 2001-2025 Discuz! Team.