【按键】[独立按键] - 1: 单击,双击,三击以及N击

5 篇文章 3 订阅
3 篇文章 3 订阅

此按键程序的实现的功能是单个独立按键的[单击],[长按],[双击],[三击]以及[多击]。本文分为三个部分,

  • 第一个部分是说[单击],[长按]的程序;
  • 第二部分是讲[双击]
  • 第三部分是讲[三击],[N击]

一、 [单击]、[长按]程序

1. 简单介绍本按键程序的单击和长按

首先说一下单击,长按的响应情况,就是按多久算单击或者长按,按下按键马上返回有效键值,还是释放之后返回有效键值等等,下面说下它在什么情况下返回有效的【单击】和【长按】。

首先看一张时序图:
这里写图片描述

注:
T1:是单击的按键消抖时长,这里预设的是30ms,也可以根据需求自行定义;
T2:是单击时,按键释放的有效时间段,提前或者超过这个时间段释放的按键都再是单击了。提前释放则是无效键值,超过后释放则是长按。
T3:是长按时长,按键超过此时长,则为长按。这里的预设值是3s,同样可根据需求自行更改。

  • 【单击】:按键按下超过消抖时长T1(30ms),并且在T2时间段内释放按键,按键一释放,马上返回有效按键值—【单击】。
    注意:单击是释放后,才返回有效按键值,不释放时,是无效按键值。

  • 【长按】:按键按下的时间超过预设的长按时长T3(3s) ,马上返回有效按键值—【长按】;
    注意:长按是只要按下的时间超过预设的长按时长,马上返回有效键值。但是,如果按键一直按着不释放,则只返回一次有效按键值,不重复返回,直到释放之后,才开始重新读取键值。

2. 按键程序的架构

按键程序可以分为四个部分,

  1. 第一部分:判断有无按键按下
  2. 第二部分:按键是否有效(按键消抖)
  3. 第三部分:确定有效按键的种类(单击还是长按)
  4. 第四部分:等待按键释放

3. 按键程序的源代码以及注释

程序的注释写的很详细,应该是可以读懂的,如果有疑问可以留言讨论。

以下是key.c 的源代码:

//============================ key.c ===================

#define KEY_INPUT           P1.0    // 按键IO

#define KEY_STATE_0         0       // 按键状态
#define KEY_STATE_1         1
#define KEY_STATE_2         2
#define KEY_STATE_3         3

#define LONG_KEY_TIME       300     // LONG_KEY_TIME*10MS = 3S
#define SINGLE_KEY_TIME     3       // SINGLE_KEY_TIME*10MS = 30MS

#define N_KEY    0                  // no click
#define S_KEY    1                  // single click
#define L_KEY    10                 // long press

unsigned char key_driver(void) 
{     
    static unsigned char key_state = 0;         // 按键状态变量
    static unsigned int key_time = 0;           // 按键计时变量
    unsigned char key_press, key_return; 

    key_return = N_KEY;                         // 清除 返回按键值

    key_press = KEY_INPUT;                      // 读取当前键值

    switch (key_state)     
    {       
        case KEY_STATE_0:                       // 按键状态0:判断有无按键按下
            if (!key_press)                     // 有按键按下
            {
                key_time = 0;                   // 清零时间间隔计数
                key_state = KEY_STATE_1;        // 然后进入 按键状态1
            }        
            break;

        case KEY_STATE_1:                       // 按键状态1:软件消抖(确定按键是否有效,而不是误触)。按键有效的定义:按键持续按下超过设定的消抖时间。
            if (!key_press)                     
            {
                key_time++;                     // 一次10ms
                if(key_time>=SINGLE_KEY_TIME)   // 消抖时间为:SINGLE_KEY_TIME*10ms = 30ms;
                {
                    key_state = KEY_STATE_2;    // 如果按键时间超过 消抖时间,即判定为按下的按键有效。按键有效包括两种:单击或者长按,进入 按键状态2, 继续判定到底是那种有效按键
                }
            }         
            else key_state = KEY_STATE_0;       // 如果按键时间没有超过,判定为误触,按键无效,返回 按键状态0,继续等待按键
            break; 

        case KEY_STATE_2:                       // 按键状态2:判定按键有效的种类:是单击,还是长按
            if(key_press)                       // 如果按键在 设定的长按时间 内释放,则判定为单击
            { 
                 key_return = S_KEY;            // 返回 有效按键值:单击
                 key_state = KEY_STATE_0;       // 返回 按键状态0,继续等待按键
            } 
            else
            {
                key_time++;                     

                if(key_time >= LONG_KEY_TIME)   // 如果按键时间超过 设定的长按时间(LONG_KEY_TIME*10ms=200*10ms=2000ms), 则判定为 长按
                {
                    key_return = L_KEY;         // 返回 有效键值值:长按
                    key_state = KEY_STATE_3;    // 去状态3,等待按键释放
                }
            }
            break;

      case KEY_STATE_3:                         // 等待按键释放
          if (key_press) 
          {
              key_state = KEY_STATE_0;          // 按键释放后,进入 按键状态0 ,进行下一次按键的判定
          }         
          break; 

        default:                                // 特殊情况:key_state是其他值得情况,清零key_state。这种情况一般出现在 没有初始化key_state,第一次执行这个函数的时候
            key_state = KEY_STATE_0;
            break;
    }

    return key_return;                          // 返回 按键值
} 

使用注意:
1)硬件:按键的一端接地(GND),另一端接IO口。IO为输入,一定要有上拉电阻。
2)定时器:这里为了精确的定时,所以使用了定时器,定时器的时间是10ms。
3)扫描周期:调用此函数时,一定确保”扫描周期“要小于10ms。不然按键内所涉及的时间就会不准,会偏大。所涉及的时间包括消抖时长按键长按时长等。
扫描周期定义:从 第一次进入按键扫描程序 开始,到第二次进入按键扫描程序时 结束,之间所用的时间。
测量扫描周期的方法:可以在按键扫描程序的第一句,添加IO口取反函数,然后用示波器查看改IO口,其IO口周期的一般就是扫描周期了。

4. 按键程序的使用实例

这里以C51位硬件平台进行实例讲解
1)实例程序的功能:

  • 单击:点亮LED1
  • 长按:熄灭LED1

2)硬件:

  • 按键IO:P1.0
  • LED1 :P2.0

以下是 main.c 源代码:

//============================ main.c ===================

#include "reg51.h"
#include "key.c"

sbit LED1 = P2.0;                             // 定义LEDIO口

unsigned char g_u8_KeyValue;                  // 按键值
unsigned char g_flag_10ms_key;                // 10ms 计时标志


//timer0,初始化函数 ,定时时间为 10ms
void T0_Init_10ms(void)
{
    TMOD |= 0x01;
    TH0 = (65535 - 10000)/256;
    TL0 = (65535 - 10000)%256;

    ET0 = 1;
    TR0 = 1;
    EA = 1;
}

//主函数
void main(void)
{
    P1.0 = 1;                                  // P1.0 拉高
    T0_Init_10ms();                            // 定时器0,初始化,定时10ms

    while(1)
    {
        if(g_flag_10ms_key)                     // 等待10ms,定时完成
        {
            g_flag_10ms_key = 0;                // 清零10ms定时标志

            g_u8_KeyValue = key_driver();       // 读取按键值

            switch(g_u8_KeyValue)
            {
                case S_KEY: LED1 = 1; break;    // 单击 点亮LED1
                case L_KEY: LED1 = 0; break;    // 长按 熄灭LED1
            }
        }
    }
}

//timer0 中断服务程序
void IRQ_T0(void) interrupt 1
{
    g_flag_10ms_key = 1;                        // 置位 10ms 定时标志
}

Pillar Peng
2016.3.23 18:00


其余分享链接:

第二部分:【按键】[独立按键] - 2: 双击

第三部分:【按键】[独立按键] - 3: 三击以及N击

  • 37
    点赞
  • 179
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
以下是使用C语言实现的按键单击双击三击的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define CLICK_INTERVAL 500 // 500毫秒内算做双击三击 int main() { int click_count = 0; clock_t last_click_time = 0; while (1) { // 等待按键事件 int button_state = wait_for_button_click(); // 计算两次按键时间间隔 clock_t current_time = clock(); int click_interval = (current_time - last_click_time) * 1000 / CLOCKS_PER_SEC; if (click_interval > CLICK_INTERVAL) { // 时间间隔超过CLICK_INTERVAL,重置点计数器 click_count = 1; } else { // 否则增加点计数器 click_count++; } if (click_count == 1) { // 单击事件 handle_single_click(button_state); } else if (click_count == 2) { // 双击事件 handle_double_click(button_state); } else if (click_count == 3) { // 三击事件 handle_triple_click(button_state); click_count = 0; // 重置点计数器 } last_click_time = current_time; } return 0; } ``` 在这个示例代码中,我们使用了一个`click_count`变量来记录按键的次数,使用`last_click_time`变量来记录上一次按键事件的时间。在每次按键事件发生时,我们计算当前时间与上一次按键事件的时间间隔`click_interval`。如果`click_interval`超过了`CLICK_INTERVAL`,我们重置点计数器`click_count`为1,否则增加`click_count`的值。当`click_count`的值为1时,处理单击事件;当`click_count`的值为2时,处理双击事件;当`click_count`的值为3时,处理三击事件,并重置点计数器。 注意:这个示例代码中的`wait_for_button_click`、`handle_single_click`、`handle_double_click`和`handle_triple_click`函数都是伪代码,需要根据实际情况进行实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PillarPeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值