找回密码
 立即注册
楼主: wszjw2

关于独立按键的单击、双击、长按开关机

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:313
  • 最近打卡:2025-05-01 00:52:15

4

主题

66

回帖

977

积分

高级会员

积分
977
发表于 2025-3-11 14:04:28 | 显示全部楼层
还不错,这适用于单独工作的按键,如果有多个工作似乎不实用,比如如果有称重模块,计数模块等等,那个延时函数就是个问题。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:33
  • 最近打卡:2025-04-28 10:23:12

11

主题

93

回帖

469

积分

中级会员

积分
469
发表于 2025-3-11 16:40:48 | 显示全部楼层

中断只开机长按使用,应该没事吧
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:33
  • 最近打卡:2025-04-28 10:23:12

11

主题

93

回帖

469

积分

中级会员

积分
469
发表于 2025-3-11 16:41:37 | 显示全部楼层
huaru*** 发表于 2025-3-11 14:04
还不错,这适用于单独工作的按键,如果有多个工作似乎不实用,比如如果有称重模块,计数模块等等,那个延时 ...

多个模块就需要用定时器了,先做个最基础的起来,后面可以再加
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:38
  • 最近打卡:2025-04-29 08:28:25
已绑定手机

17

主题

446

回帖

1173

积分

金牌会员

积分
1173
发表于 2025-3-11 17:20:30 | 显示全部楼层
wsz*** 发表于 2025-3-11 16:40
中断只开机长按使用,应该没事吧

这样还好
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:309
  • 最近打卡:2025-05-01 21:51:03

0

主题

37

回帖

1334

积分

金牌会员

积分
1334
发表于 2025-3-11 23:44:34 | 显示全部楼层
谢谢分享
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:313
  • 最近打卡:2025-05-01 00:52:15

4

主题

66

回帖

977

积分

高级会员

积分
977
发表于 2025-3-12 07:07:05 | 显示全部楼层
wsz*** 发表于 2025-3-11 16:41
多个模块就需要用定时器了,先做个最基础的起来,后面可以再加

谢谢分享,静等楼主更好的模块。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-01 08:20:47
已绑定手机

1

主题

63

回帖

521

积分

高级会员

积分
521
发表于 2025-3-12 07:24:50 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:33
  • 最近打卡:2025-04-28 10:23:12

11

主题

93

回帖

469

积分

中级会员

积分
469
发表于 2025-3-19 17:12:30 | 显示全部楼层
这段程序测试感觉已经完成了,但是为什么把这段程序封装成BUTTON.C之后让main调用它就不稳定,会出现双击识别不了,关机后得多次长按才行


  1. #include <STC8H.H>
  2. #include <intrins.h>
  3. // 硬件配置
  4. sbit KEY_PIN = P3^2;      // 按键接P3.2
  5. sbit LIGHT=P1^0;
  6. //
  7. typedef         unsigned char        u8;
  8. typedef         unsigned int        u16;
  9. typedef         unsigned long        u32;
  10. // 宏定义
  11. #define DEBOUNCE_MS     20       // 消抖时间20ms
  12. #define DOUBLE_PRESS    300      // 双击间隔300ms
  13. #define LONG_PRESS     10000
  14. #define MAIN_LOOP_CYCLE 10       // 主循环周期10ms
  15. #define MAIN_Fosc                24000000L        //定义主时钟
  16. // 全局变量
  17. static u8 key_event = 0;                // 按键事件(1=单击,2=双击)
  18. static u8 key_state = 0;                // 按键状态机
  19. static u8 power_flag=0;
  20. static u8 wake_flag=0;
  21. u8 mode=0;
  22. void power_off();
  23. void  delay_ms(u16 ms)
  24. {
  25.      u16 i;
  26.          do
  27.          {
  28.                  i = MAIN_Fosc / 10000;
  29.                 while(--i)        ;
  30.      }while(--ms);
  31. }
  32. void key_scan() {
  33.     static u16 release_timer = 0;
  34.     static u8  click_count = 0;
  35.     static bit last_pin_state = 1;
  36.         static u16 press_counter=0;
  37.     // 状态机处理
  38.     switch(key_state) {
  39.         case 0: // 初始状态
  40.                        
  41.                         if(KEY_PIN == 0 && last_pin_state == 1)// 检测到下降沿
  42.                         {
  43.                 delay_ms(DEBOUNCE_MS);
  44.                 if(KEY_PIN == 0)
  45.                                 { // 确认按下
  46.                     key_state = 1;
  47.                     click_count+=1;
  48.                                         press_counter=0;
  49.                 }
  50.             }
  51.             break;
  52.         case 1: // 已按下,等待释放
  53.                         press_counter+=MAIN_LOOP_CYCLE;
  54.                        
  55.             if(KEY_PIN == 1) // 检测到释放
  56.                         {
  57.                 delay_ms(DEBOUNCE_MS);
  58.                 if(KEY_PIN == 1)
  59.                                         {
  60.                     key_state = 2;
  61.                     release_timer = 0; // 启动双击检测窗口
  62.                 }
  63.             }
  64.                         else if(press_counter>LONG_PRESS)
  65.                         {
  66.                                 key_event=3;                        //长按
  67.                                
  68.                                 click_count=0;
  69.                                 key_state=0;
  70.                                 press_counter=0;
  71.                         }
  72.             break;
  73.         case 2: // 释放状态,检测双击窗口
  74.             release_timer += MAIN_LOOP_CYCLE;
  75.             
  76.             if(release_timer >= DOUBLE_PRESS) { // 超时处理
  77.                 if(click_count == 1) {
  78.                     key_event = 1; // 单击
  79.                 }
  80.                 click_count = 0;
  81.                 key_state = 0;
  82.             } else if(KEY_PIN == 0) { // 再次按下
  83.                 delay_ms(DEBOUNCE_MS);
  84.                 if(KEY_PIN == 0) {
  85.                     click_count+=1;
  86.                     key_state = 3;
  87.                 }
  88.             }
  89.             break;
  90.         case 3: // 第二次按下,等待释放
  91.             if(KEY_PIN == 1) {
  92.                 delay_ms(DEBOUNCE_MS);
  93.                 if(KEY_PIN == 1) {
  94.                     if(click_count >= 2) {
  95.                         key_event = 2; // 双击
  96.                     }
  97.                     click_count = 0;
  98.                     key_state = 0;
  99.                 }
  100.             }
  101.             break;
  102.     }
  103.     last_pin_state = KEY_PIN; // 更新引脚状态
  104. }
  105. void power_off()
  106. {
  107.         power_flag=0;                        //关机标志置0
  108.        
  109.        
  110.         P1IE=0X00;
  111.         P2IE=0X00;
  112.         P3IE=0X04;                                //关闭除P32外的数字输入
  113.        
  114.         IT0=1;
  115.         EX0=1;
  116.         EA=1;                                        //关机时打开外部中断,进行初始化,下降沿触发
  117.        
  118.         PCON |=PD;                                //进入掉电模式
  119.         NOP1();
  120. }
  121. void wake_init()
  122. {
  123.        
  124.         P1M0 = 0x00; P1M1 = 0x00;
  125.     P2M0 = 0x00; P2M1 = 0x00;
  126.         P3M0 = 0x00; P3M1 = 0x00;//初始化端口,设置为双向口
  127.        
  128.         EX0=0;
  129.         EA=0;                                           //开机时关闭中断
  130.        
  131.         wake_flag=0;                        //唤醒初始化完成,唤醒标志置0
  132. }
  133. /**/
  134. // 主函数
  135. void main()
  136. {
  137.         power_off();                        //上电默认为低功耗模式
  138.        
  139.     while(1)
  140.         {
  141.                 key_scan();
  142.                 if(power_flag==1)        //
  143.                 {
  144.                         if(wake_flag==1)wake_init();
  145.                         P25=0;
  146.                
  147.                         switch(key_event)
  148.                         {
  149.                         case 1:
  150.                                 P21=~P21;
  151.                                 key_event=0;
  152.                                 break;
  153.                         case 2:
  154.                                 P24=~P24;
  155.                                 key_event=0;
  156.                                 break;
  157.                         case 3:                       
  158.                         P25=1;power_off();       
  159.                         key_event=0;
  160.                                 break;
  161.                         }
  162.                 }
  163.                 else{power_off();P25=1;}
  164.                 delay_ms(10);
  165.         }
  166.       
  167. }
  168. void exint0() interrupt 0
  169. {
  170.          u16 hold_cnt = 0;  // 改为16位计数器
  171.    
  172.     // 长按检测(不依赖延时函数)
  173.     while(KEY_PIN == 0) {
  174.         if(++hold_cnt > (LONG_PRESS/10)) { // 每10ms计数
  175.             power_flag = 1;
  176.                         wake_flag=1;
  177.                         P23=~P23;
  178.             return;
  179.         }
  180.         delay_ms(10);  // 仅用于粗略计时
  181.     }
  182. }
复制代码
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤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.

快速回复 返回顶部 返回列表