目录

  • 1、自己使用的按键驱动
    • 1.1 驱动源码
    • 1.2 使用方法
  • 2、另一种按键驱动
    • 2.1 驱动源码
    • 2.2 使用方法

在我们嵌入式开发中,产品上往往少不了按键,一个好的按键驱动可以满足不同场合的客户需求,这里我分享几个实用的按键驱动,希望抛砖引玉,大家多多指出不足以及提出改进办法,或者有更好的方案希望也能分享分享。

不废话,直接上源码:

1、自己使用的按键驱动

不同平台需要做相应的修改,该驱动最初在51上运行,然后我用在了STM32F系列上,最近在STM32L系列上也在使用。

1.1 驱动源码

用最近的一个作为demo

/*
2019/5/21 按键程序移植成功,以后可以使用此按键,需要研究一下
和以前单片机项目按钮方式类似
by  qzh
2019/8/30
确定了第三行,第一个必须是7,才能按下到时间自动触发
by  qzh
*/
#include "mod_button.h"//GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
void io_getDigital(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin,uint8 *pu8Value)
{   *pu8Value = HAL_GPIO_ReadPin(GPIOx,GPIO_Pin);
}void time_setTimerCount(TIMER_TYPE *pu8timer,uint32 u32timeToCount)
{// __HAL_TIM_SET_COUNTERHAL_TIM_Base_Start_IT(&htim21);// HAL_TIM_Base_Stop_IT// TIM_Cmd(TIM4, ENABLE);if(pu8timer->on == 0)pu8timer->on = 1;if(pu8timer->on == 1)//IntNum = 0;pu8timer->timeInit = Timer4_count;//pu8timer->timeInit = IntNum;pu8timer->timeOut = 0;pu8timer->timeToCount = u32timeToCount;
}RETURN_TYPE time_getTimeOut(TIMER_TYPE *pu8timer)
{uint32 Temp_Val;if(Timer4_count > pu8timer->timeInit)Temp_Val = Timer4_count - pu8timer->timeInit;elseTemp_Val = (0xFFFFFFFF-pu8timer->timeInit)+Timer4_count;if(Temp_Val >= pu8timer->timeToCount){pu8timer->timeOut = 1;pu8timer->on = 0;pu8timer->timeToCount = 0;pu8timer->timeInit = 0;}    else pu8timer->timeOut = 0;return (pu8timer->timeOut == 1)?TIME_OUT:OK;
}BTN_STATE btn_getState(BTN_STRUCT *pBtn)
{const uint8 transition_table[8][4]={   0,  1,  0,  1,5,    2,  5,  1,7,    2,  5,  3,5,    4,  5,  4,5,    4,  5,  4,6,    1,  0,  1,6,    1,  7,  1,0,    1,  0,  1 };//register uint8 u8Input;uint8 u8Input;// Get button stateio_getDigital(pBtn->u8Pin,pBtn->GPIO_Pin ,&u8Input);u8Input = (u8Input == pBtn->u8ActiveState)?1:0;// Get timeout stateu8Input |= ((time_getTimeOut(&(pBtn->tTimer))==TIME_OUT)?2:0);// Get new statepBtn->u8State = transition_table[pBtn->u8State][u8Input]; // we want only the state, not action// Perform action switch (pBtn->u8State){case 1:time_setTimerCount(&(pBtn->tTimer), pBtn->u16TimeOutON);break;case 5:time_setTimerCount(&(pBtn->tTimer), pBtn->u16TimeOutOFF);break;}// return pBtn->u8State;//待测试return (BTN_STATE)pBtn->u8State;
} //下面是mod_button.h#ifndef _MOD_BUTTON_H_INCLUDED
#define _MOD_BUTTON_H_INCLUDED#include "main.h"
#include "Datadef.h"
#include "tim.h"
/*Timeout ON_______|_____P             |             |        Timeout OFFR  ___________|             |________|____^      ^  ^    ^  ^  ^   ^    ^S     0      1  2    3  4  5   6    7P - pressed, R - released, S - BTN_STATE
*//*
°´Å¥Ïà¹Ø  KEY1  learn  PB5  KEY2  CLEAR  PB6
*/
#define BTN_ACTIVE    0          //when pressed, switch to GNDtypedef struct
{// Public //uint8      u8Pin;          // e.g. ADIO0//uint16       u8Pin;          // e.g. ADIO0GPIO_TypeDef * u8Pin;uint16_t    GPIO_Pin;uint8        u8ActiveState;  // button is pressed if (io_getDigital(u8Button)==bActiveState)uint16     u16TimeOutON;   // time the button has to be pressed to be recognized as presseduint16      u16TimeOutOFF;  // time the button has to be pressed to be recognized as released// PrivateTIMER_TYPE   tTimer;uint8        u8State;} BTN_STRUCT;typedef enum
{BTN_IDLE = 0,BTN_EDGE1,BTN_TRIGGERED,BTN_PRESSED, //< most importantBTN_PRESS_HOLD,BTN_EDGE2,BTN_RELEASE_HOLD,BTN_RELEASED
} BTN_STATE;extern u16 Timer4_count;BTN_STATE btn_getState(BTN_STRUCT *pBtn);
void time_setTimerCount(TIMER_TYPE *pu8timer,uint32 u32timeToCount);
void io_getDigital(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,uint8 *pu8Value);
RETURN_TYPE time_getTimeOut(TIMER_TYPE *pu8timer);#endif //_MOD_BUTTON_H_INCLUDED

1.2 使用方法

//先定义一个按键的结构体类型,
BTN_STRUCT  K1_BUTTON_150mS ={K1_GPIO_Port,    K1_Pin,BTN_ACTIVE,                            // Active state150,                                 // Time the button has to be in 'Active state' to be recognized as pressed100 };
BTN_STRUCT  K1_BUTTON_2S = { K1_GPIO_Port,K1_Pin,BTN_ACTIVE,                             // Active state2000,                                // Time the button has to be in 'Active state' to be recognized as pressed100    } ;//然后在主函数循环中调用不同的状态
if(btn_getState(&K1_BUTTON_150mS) == BTN_EDGE2){...}//BTN_EDGE2按住松开
if(btn_getState(&K1_BUTTON_2S) == BTN_PRESSED){...} //BTN_PRESSED为按住不松开状态
//注意使用的时候,如果长时间的按钮操作需要状态为 BTN_EDGE2 ,即长按松开 才会执行,在执行完语句最后需要包含比此次短的 BTN_EDGE2 操作:if((btn_getState(&CLEAR_BUTTON_2S)==BTN_EDGE2){...while(btn_getState(&CLEAR_BUTTON_150mS));// 防止长时间按住松开会触发短时间的松开操作
}

一般的情况下,上面代码中用到的按键事件足够应付,所以 BTN_STATE 中其他的按键状态我也没有花太多事件去测试,如果有谁能够把其他状态测试说清楚,还希望能够告知一声,

此按键程序最初原型是国外一家公司提供的SDK包里面的 Demo,然后经过自己的多次测试与修改才变成自己的最常用的驱动,当然他还可以更加的优化,希望大家多多指导。

2、另一种按键驱动

当初在做按键的时候,想着除了上面的是否有其他简单的通俗易懂的按键驱动,然后自己在网上各种寻找,反正不可能按键直接检测IO,然后防抖做一个短延时,最终这种还是逃不过得开定时器,然后还是做了一个测试可用的:

2.1 驱动源码

//开启按键IO的外部中断,为上升下降沿都能触发,这样是检测按下,弹起之间的时间差EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
/*
有一个问题,就是按下以后,长按需要下一次进入外部中断才能执行
*/
void EXTI9_5_IRQHandler(void)
{if( EXTI_GetITStatus(EXTI_Line7)!= RESET){if( KEY == 0 ){               Timer4_count = 0;readkey1 =0;}else readkey1=1;}EXTI_ClearITPendingBit(EXTI_Line7);
}//外部中断实施按键操作
KEY_TIME Press_Key1(void)
{KEY_TIME i;if( readkey1 == 1 ){if( Timer4_count < 20 ){Timer4_count = 0;readkey1 = 0;i = NOT;}else if(( Timer4_count >= 80) && (Timer4_count < 2000 )){Timer4_count = 0;readkey1 = 0;i = Short;}else if(( Timer4_count >= 2000 ) && (Timer4_count < 5000 )){Timer4_count = 0;readkey1 = 0;i = Medium;}else if( Timer4_count >= 5000 ){Timer4_count = 0;readkey1 = 0;i = Long;}}return i;
}//在.h文件中定义枚举类型
typedef enum
{NOT   = 0,Short =2,Medium=3 ,Long =4 ,
}KEY_TIME;
/*
好像记得当时在上面这个枚举类型时候,Short 定义为 1 是会有问题的,当时也不确定是什么问题,改成 2 测试就OK了,也没花时间研究
*/
KEY_TIME Press_Key1(void);

2.2 使用方法

if(Press_Key1() == Short){...
}
else if(Press_Key1() == Medium);

当时这种按键也用了一会,但是好像是与点小问题,但是只使用 short 和 Medium 是可以的,具体什么问题,因为实际用不到那么多,所以也没继续研究下去,这个方法是在网上参照的例子拿过来使用的。

单片机系统中实用的按键驱动(STM32、51都适用)相关推荐

  1. 单片机系统中的红外通信接口

    摘要:本文结合复费率电能表中红外通信的设计实从事贸易,介绍了单片机系统中红外通信的软硬件设计方法,并给出了具体的电路原理和通信源程序. 关键词:单片机,红外通信,遥控 在许多基于单片机的应用系统中,系 ...

  2. Windows XP系统中实用的命令及操作技巧

    Windows XP系统中实用的命令及操作技巧 转贴自:电脑报 想在命令提示符窗口中输入重复命令时,只须按F7键,就会出现图形界面,然后选择你想输入的命令即可. 一"符"安天下利用 ...

  3. x21能刷小米系统吗_小米系统是安卓系统中最强的吗?大家都错了,它是MIUI的进化版...

    小米系统是安卓系统中最强的吗?大家都错了,它是MIUI的进化版 现在国产手机做得越来越好了,在硬件方面国产手机比同级别的外国品牌要厚道太多了,所以在中国,外国品牌是没有任何生存空间的.在性价比方面他们 ...

  4. 单片机数字滤波c语言程序,单片机系统中数字滤波的算法【C程序整理】

    声明:此内容经本人整理,供大家交流使用.不妥之处,敬请指出.QQ:779589211 吾生有涯 随机误差是有随机干搅引起的,其特点是在相同条件下测量同一个量时,其大小和符号做无规则变化而无法预测,但多 ...

  5. linux 显卡亮度,在Deepin 15.10系统中安装NVIDIA显卡驱动后设置屏幕亮度的方法

    首先需要在Deepin 15.10操作系统中安装NVIDIA显卡驱动,参考在Deepin系统中安装英伟达NVIDIA显卡驱动的方法一文,然后按照下面的两种方法设置屏幕亮度,实测在Deepin 15.1 ...

  6. 064_将 Linux 系统中 UID 大于等于 1000 的普通用户都删除

    #!/bin/bash #先用 awk 提取所有 uid 大于等于 1000 的普通用户名称 #再使用 for 循环逐个将每个用户删除即可 user=$(awk -F: '$3>=1000{pr ...

  7. win系统中打印机驱动点击打开,没反应的解释

    不少小伙伴,私信咨询我,win系统中,打印机的驱动,打不开,是什么原因? 在此,跟大家分析下 这种现象,多属于win10和win11出现,其他版本,例如win7就很少出现这种问题 win7就比较稳定, ...

  8. 单片机系统不稳定情况

    1.概述 本篇记录以后在单片机系统中遇到的不稳定情况 2.单片机系统启动不稳定情况分析 经常碰到做的单片机系统不稳定的情况,分析是在上电的时候 CPU稳定与外设的稳定时间不一致,所以单片机系统程序需要 ...

  9. c语言按键松手检测,51单片机按键检测的方法

    本文旨在介绍单片机入门的基础知识,为初接触或即将接触单片的新手提供一个入门指导.本文章会陆续推出,隔几天一个章节.希望对广大即将接触单片机的人有所帮助,如果有错误欢迎回帖指出与本人交流或加入QQ群14 ...

  10. WINCE 按键驱动编写

    该按键驱动摘自WINCE的FM1702读写器中的按键代码,按键中断的触发将会通过发送消息传递到标题为"FM1702测试界面[wenziqi@hotmail.com]"的对话框中. ...

最新文章

  1. vue build text html,Vue中v-text / v-HTML使用实例代码详解_放手_前端开发者
  2. 怎样才算熟悉python-怎样才算学会Python
  3. 重置linux桌面,Ubuntu 18.04小贴士:重置Gnome桌面与使用隐藏的屏幕录像工具
  4. 国内IDC行业现状及投资策略分析
  5. ssh密码长度漏洞java_Linux中 OpenSSH 输入验证错误漏洞(CVE-2019-16905) 修复解决方案...
  6. python学习HTML之CSS(2)
  7. linux 系统迁移到固态硬盘,把Debian GNU/Linux迁移到SSD上
  8. mongodb 总结
  9. 零基础Python学习路线图,Python学习不容错过
  10. Word2Vec教程-Skip-Gram模型
  11. 《spring-boot学习》-02-hello world
  12. linux下vhd win10,利用win10纯净版系统的VHD虚拟硬盘安装win10系统的方法
  13. span标签居中显示的正确方法
  14. bzoj 1618: [Usaco2008 Nov]Buying Hay 购买干草(完全背包)
  15. oracle 参数类型 存储过程 获取_oracle Array类型作为参数传入函数(存储过程) 大字符串参数解决方案...
  16. 击鼓传花:对比 muduo 与 libevent2 的事件处理效率
  17. Easy make - emake
  18. CSS实现气泡对话框
  19. 《中医确有专长证》和《中医专长医师资格证》的区别
  20. android和平精英安装目录,和平精英文件目录在哪里 本体及安装包位置

热门文章

  1. 基于51单片机的pid算法温度控制系统protues仿真
  2. 唐山初中计算机考试知识点,画法几何点知识点及考点.doc
  3. C语言数组指针和指向数组的指针变量—数组名作函数参数.doc
  4. 台式计算机如何连接投影仪,台式机怎么接投影仪 台式机接投影仪方法【详解】...
  5. oracle自学视频
  6. 安徽省滁州市谷歌卫星地图下载
  7. 以太网MAC协议--CSMA/CD协议
  8. PS4在Jetson nano下的配对使用,并用ROS接口来控制
  9. 使用MySQL创建数据库,实现基本SQL语句
  10. obs源码简析之推流