不借助GPIO中断,采用轮询的方式,实现按键的长按、短按、连发

参考:https://blog.csdn.net/qq_31151689/article/details/85228441

百度快照:http://cache.baiducontent.com/c?m=9d78d513d99603f405fa950e1a66d571695297134dc0a46468d5e35fe3654c324171e2cb30521213a3c36b6671b83958fd814765367337c799dff84ccabae27938895723061d913666c46facdc3023d567d004e6f55fa1f8b12592ddcfce8f0a0e9f44050dd1b1dd061714bd33a7522ca0e58e4f615e13b9ea3361f5526a7adf651be719aefd643941d2ad831d51c92dd0611b91a936&p=85769a479d8211a05bed9362544f97&newp=90759a46d6c416e04ea4f82d02148f231610db2151d7d31f6b82c825d7331b001c3bbfb423261403d7cf7d6604af4f5beef7307237012ba3dda5c91d9fb4c57479df68223970&user=baidu&fm=sc&query=gpio%B0%B4%BC%FC%B3%A4%B0%B4%B6%CC%B0%B4C%D3%EF%D1%D4&qid=a2d95b6400011865&p1=8

#include <stdio.h>
#include <time.h>// 定义长按键的TICK数, 以及连发间隔的TICK数, 单位是毫秒ms
#define KEY_DEBOUNCE_PERIOD     20   // 延时消抖时间
#define KEY_LONG_PERIOD         1000
#define KEY_CONTINUE_PERIOD     200#define TRUE    1
#define FALSE   0typedef unsigned int Bool;typedef enum {LOW = 0,HIGH
} KEY_LEVEL_E;typedef enum
{KEY1 = 0,KEY2,KEY3,KEY4,KEY_MAX_NUM
} KEY_NUM_E;// 定义按键返回值状态(按下,长按,连发,释放,无动作)
typedef enum {KEY_NULL = 0,KEY_DOWN,KEY_LONG,KEY_CONTINUE,KEY_UP
} KEY_VALUE_E;typedef enum {KEY_STATE_INIT = 0,KEY_STATE_WOBBLE,KEY_STATE_PRESS,KEY_STATE_LONG,KEY_STATE_CONTINUE,KEY_STATE_RELEASE
} KEY_STATE_E;typedef struct
{KEY_NUM_E eKeyId;KEY_LEVEL_E eKeyLevel;         //key level(low or high)unsigned int downTick;unsigned int upTick;KEY_STATE_E eKeyCurState;      //key cur state(fsm)KEY_STATE_E eKeyLastState;     //key last state(fsm)Bool bStateChangedFlag;        //state changed flagKEY_VALUE_E eLastKeyValue;     //key value
} KEY_HANDLE_T;typedef void (*pf)(void);typedef struct
{pf keyDownAction;pf keyLongAction;pf keyContinueAction;pf keyUpAction;
} KEY_FUNCTION_T;KEY_HANDLE_T keyList[KEY_MAX_NUM] =
{{KEY1, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL},{KEY2, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL},{KEY3, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL},{KEY4, LOW, 0, 0, KEY_STATE_INIT, KEY_STATE_INIT, FALSE, KEY_NULL}
};// 用于获取当前时间, 单位是毫秒ms
unsigned int getTime0(void)
{struct timespec time;clock_gettime(CLOCK_MONOTONIC, &time);return ((time.tv_sec * 1000) + (time.tv_nsec/1000000));
}unsigned int timeDiffFromNow(unsigned int time0)
{unsigned int cur = 0;struct timespec time;clock_gettime(CLOCK_MONOTONIC, &time);cur = (time.tv_sec * 1000) + (time.tv_nsec/1000000);return cur - time0;
}void keyScan(KEY_HANDLE_T* key)
{// gpioReadPin()需根据你的平台来写if(HIGH == gpioReadPin(key->eKeyId)){// 根据原理图, HIGH代表松开key->eKeyLevel = HIGH;}else{// 根据原理图, LOW代表按下key->eKeyLevel = LOW;}// 获取当前key是按下还是松开KEY_LEVEL_E level = key->eKeyLevel;key->eLastKeyValue = KEY_NULL;switch(key->eKeyCurState){case KEY_STATE_INIT:if(LOW == level){key->downTick = getTime0();key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_WOBBLE;}break;case KEY_STATE_WOBBLE:if(LOW == level){if(timeDiffFromNow(key->downTick) >= KEY_DEBOUNCE_PERIOD){key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_PRESS;}}else{key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_INIT;}break;case KEY_STATE_PRESS:if(TRUE == key->bStateChangedFlag){key->bStateChangedFlag = FALSE;key->eLastKeyValue = KEY_DOWN;}if(LOW == level){if(timeDiffFromNow(key->downTick) >= KEY_LONG_PERIOD){key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_LONG;}}else{key->upTick = getTime0();key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_RELEASE;}break;case KEY_STATE_LONG:if(TRUE == key->bStateChangedFlag){key->bStateChangedFlag = FALSE;key->eLastKeyValue = KEY_LONG;}if(LOW == level){if(timeDiffFromNow(key->downTick) >= (KEY_LONG_PERIOD + KEY_CONTINUE_PERIOD)){key->downTick = getTime0();key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_CONTINUE;}}else{key->upTick = getTime0();key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_RELEASE;}break;case KEY_STATE_CONTINUE:if(TRUE == key->bStateChangedFlag){key->bStateChangedFlag = FALSE;key->eLastKeyValue = KEY_CONTINUE;}if(LOW == level){if(timeDiffFromNow(key->downTick) >= KEY_CONTINUE_PERIOD){key->downTick = getTime0();key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_CONTINUE;}}else{key->upTick = getTime0();key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_RELEASE;}break;case KEY_STATE_RELEASE:if(timeDiffFromNow(key->upTick) >= KEY_DEBOUNCE_PERIOD) // 松开按键也来个消抖{if(TRUE == key->bStateChangedFlag){key->bStateChangedFlag = FALSE;key->eLastKeyValue = KEY_UP;}key->bStateChangedFlag = TRUE;key->eKeyCurState = KEY_STATE_INIT;}else{if(LOW == level){key->eKeyCurState = key->eKeyLastState;}}break;default:break;}key->eKeyLastState = key->eKeyCurState;
}void key1DownAction(void)
{printf("%s\n", __FUNCTION__);
}void key1LongAction(void)
{printf("%s\n", __FUNCTION__);
}void key1ContinueAction(void)
{printf("%s\n", __FUNCTION__);
}void key1UpAction(void)
{printf("%s\n", __FUNCTION__);
}void key2DownAction(void)
{printf("%s\n", __FUNCTION__);
}void key2LongAction(void)
{printf("%s\n", __FUNCTION__);
}void key2ContinueAction(void)
{printf("%s\n", __FUNCTION__);
}void key2UpAction(void)
{printf("%s\n", __FUNCTION__);
}void key3DownAction(void)
{printf("%s\n", __FUNCTION__);
}void key3LongAction(void)
{printf("%s\n", __FUNCTION__);
}void key3ContinueAction(void)
{printf("%s\n", __FUNCTION__);
}void key3UpAction(void)
{printf("%s\n", __FUNCTION__);
}void key4DownAction(void)
{printf("%s\n", __FUNCTION__);
}void key4LongAction(void)
{printf("%s\n", __FUNCTION__);
}void key4ContinueAction(void)
{printf("%s\n", __FUNCTION__);
}void key4UpAction(void)
{printf("%s\n", __FUNCTION__);
}KEY_FUNCTION_T keyMapList[KEY_MAX_NUM] =
{{key1DownAction, key1LongAction, key1ContinueAction, key1UpAction}, //KEY1{key2DownAction, key2LongAction, key2ContinueAction, key2UpAction}, //KEY2{key3DownAction, key3LongAction, key3ContinueAction, key3UpAction}, //KEY3{key4DownAction, key4LongAction, key4ContinueAction, key4UpAction}, //KEY4
};void keyMapHandle(KEY_HANDLE_T *key, KEY_FUNCTION_T *keyMap)
{unsigned char keyValue = key->eLastKeyValue;if(KEY_NULL == keyValue){return;}else{switch(keyValue){case KEY_DOWN:if(keyMap->keyDownAction != NULL){keyMap->keyDownAction();}break;case KEY_LONG:if(keyMap->keyLongAction != NULL){keyMap->keyLongAction();}break;case KEY_CONTINUE:if(keyMap->keyContinueAction != NULL){keyMap->keyContinueAction();}break;case KEY_UP:if(keyMap->keyUpAction != NULL){keyMap->keyUpAction();}break;default:break;}}
}int main(void)
{KEY_NUM_E keyId = KEY_MAX_NUM;while(1){for(keyId=KEY1; keyId<KEY_MAX_NUM; keyId++){keyScan(&keyList[keyId]);}for(keyId=KEY1; keyId<KEY_MAX_NUM; keyId++){keyMapHandle(&keyList[keyId], &keyMapList[keyId]);}usleep(10*1000);}return 0;
}

GPIO按键的长按、短按、连发——C程序相关推荐

  1. STM32-蓝桥杯嵌入式之三行按键检测(按键的长、短,单击、双击)

    STM32-蓝桥杯嵌入式之三行按键检测(按键的长.短,单击.双击) 目录 STM32-蓝桥杯嵌入式之三行按键检测(按键的长.短,单击.双击) 一.检测按键下降沿分析 二.检测按键上升沿分析 三.按键检 ...

  2. 海思Hi3531 GPIO按键的长按、短按、连发——Linux驱动+应用程序

    转:https://blog.csdn.net/cfl927096306/article/details/88842398### 之前整理了一篇博文,是纯粹在应用层(用户空间)来轮询GPIO口的电平状 ...

  3. c语言连发器,GPIO按键的长按、短按、连发——C程序

    不借助GPIO中断,采用轮询的方式,实现按键的长按.短按.连发 参考:https://blog.csdn.net/qq_31151689/article/details/85228441 百度快照:h ...

  4. 记录C语言学习【单个按键之长按+短按】

    最近学习C语言,偶然看到一句话很是赞同. 学会了的境界: 境界1是自己看会了: 境界2自己独立做出来了: 境界3自己可以独立做出来,并描述出来了: 境界4可以把别人教会了. 初学单片机C语言,本按键程 ...

  5. 按键的拓展:长按短按 (2)

    上一篇文章中,按键的长按短按是按照 短按--第一次长按--第二次长按,按顺序来的. 但是今天重读考题发现,考察的不是按顺序先短按,后长按一个一个来:而是对按下时间长短有一个判断:比如说:只要按下按键, ...

  6. (转)嵌入式按键驱动,支持短按、长按、双击(中断方式)

    轮训方式连接:https://blog.csdn.net/Golf_research/article/details/52760320  目录: 1:概述 2:stm32外部中断配置 3:code 概 ...

  7. 按键的长按与短按让蜂鸣器响一下

    最近我用标准库和stm32写了一个关于,多个按键的长按与短按,伴随蜂鸣器响一下的小实验,和大家分享一下! 按键的思路框架: 这个框架是我从网上找到的,便于大家理解. void Key_Scan(voi ...

  8. 三行代码按键消抖 独立按键 矩阵按键 长按 短按 双击

    九层妖塔 起于垒土 直接跳转到三行代码 三行代码按键消抖 独立按键 矩阵按键 长按 短按 双击 一.基本理论 0.按键的常见名词:  ①按键抖动  ②按键稳定闭合时间 1.按键的扫描: 2.按键的消抖 ...

  9. stm32 工业按键检测_STM32f103按键检测程序实现长按短按

    背景本文引用地址:http://www.eepw.com.cn/article/201807/384495.htm 只要使用单片机,按键检测基本上是一定要实现的功能.按键检测要好用,最重要的是实时和去 ...

最新文章

  1. 这个德国山寨工厂靠抄袭干到240亿,让硅谷恨之入骨
  2. 直播预告丨聚焦银行数字化运营体系搭建,助力银行构建核心竞争力
  3. 数据结构-常用的排序算法
  4. 做移动互联网App,你的测试用例足够吗?
  5. 数学与计算机科学学院宣传词,【榜样人物】筑梦前行 不负韶华——数学与计算机科学学院姚彬彬同学的考研心路...
  6. JavaWeb19-HTML篇笔记
  7. Leetcode 207. 课程表(值得一刷的宽搜)
  8. Windows常用运行库合集--官网(VC++、DirectX、.NET)
  9. 换脸算法 X2Face 详解
  10. IT狂人第一至四季/全集The IT Crowd迅雷下载
  11. java图片上传同时后台直接给MultipartFile对象添加图片水印或者文字水印,然后直接上传带水印的图片
  12. 如何批量将多个 PPT 文档按指定页分别拆分成多个文档
  13. 三国杀代码12武将C++
  14. BlockingQueue应用
  15. ZOOM:1的原理和作用
  16. Java常见的线程池有哪些?
  17. hdu多校第七场 1011 (hdu6656) Kejin Player 概率dp
  18. 问题 K: 古罗马数字
  19. MSSQL的datediff函数
  20. 如何确保程序的稳定性 - Android

热门文章

  1. OushuDB入门(四)——数仓架构篇
  2. linux中文谐音,GNU和LINUX到底怎么个发音?
  3. 操作系统:操作系统的概念
  4. linux lp0设备,P1108打印机插入Linux设备USB口后自动reset
  5. STM32系统滴答_及不可不知的延时技巧 - (上)
  6. 【INDEMIND相机运行SLAM】
  7. linux停止tomcat 8005,严重:无法联系localhost:8005.关闭tomcat服务器时,Tomcat可能没有运行错误....
  8. PowerDesigner 添加字段和表名备注
  9. WebShell -- Linux反弹
  10. android edittext禁止输入特殊字符,禁止输入表情以及特殊字符方法