当前位置:首页 > 公众号精选 > 嵌入式微处理器
[导读]本文提供了一个按键实现【单击\双击\长按】的单片机demo程序。芯片采用新唐的N76E003,但理论上可以改成其它MCU。←左右滑动,查看全部代码→#include"N76E003.h"#include"Common.h"#include"Delay.h"#include"SFR...


本文提供了一个按键实现【单击\双击\长按】的单片机demo程序。


芯片采用新唐的N76E003,但理论上可以改成其它MCU。


←左右滑动,查看全部代码→


#include "N76E003.h"#include "Common.h"#include "Delay.h"#include "SFR_Macro.h"#include "Function_define.h"
#define TIMER1_INIT (6663 * 2)
UINT8 u8TH1_Tmp, u8TL1_Tmp;UINT8 time_10ms_ok;
unsigned char key;
#define IO_KEY_INPUT  P10     //按键输入口#define IO_BEEP P30
#define N_key    0       //无键#define S_key    1       //单键#define D_key    2       //双键#define L_key    3       //长键
#define key_state_0 0#define key_state_1 1#define key_state_2 2#define key_state_3 3
unsigned char key_driver( void ){ static unsigned char key_state = key_state_0, key_time = 0; unsigned char key_press, key_return = N_key;
  key_press = IO_KEY_INPUT;    //读按键I/O电平 switch ( key_state ) {  case key_state_0:    //按键初始态 if ( !key_press )      key_state = key_state_1;      //键被按下,状态转换到按键消抖和确认状态    break;
  case key_state_1:  //按键消抖与确认态 if ( !key_press ) { key_time = 0;      key_state  = key_state_2;      //按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件 }else      key_state = key_state_0;      //按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。    break;
case key_state_2: if ( key_press ) {      key_return  = S_key;      //此时按键释放,说明是产生一次短操作,回送S_key      key_state  = key_state_0;      //转换到按键初始态    }else if (  key_time >= 100 )    //继续按下,计时加10ms(10ms为本函数循环执行间隔) {      key_return  = L_key;      //按下时间>1000ms,此按键为长按操作,返回长键事件      key_state  = key_state_3;  //转换到等待按键释放状态 } break;
  case key_state_3:   //等待按键释放状态,此状态只返回无按键事件 if ( key_press )      key_state = key_state_0;   //按键已释放,转换到按键初始态 break; } return(key_return);}/*============= * 中间层按键处理函数,调用低层函数一次,处理双击事件的判断,返回上层正确的无键、单键、双键、长键4个按键事件。 * 本函数由上层循环调用,间隔10ms * ===============*/
unsigned char key_read( void ){  static unsigned char  key_m = key_state_0, key_time_1 = 0;  unsigned char    key_return = N_key, key_temp;
key_temp = key_driver();
switch ( key_m ) { case key_state_0: if ( key_temp == S_key ) {      key_time_1  = 0;      //第1次单击,不返回,到下个状态判断后面是否出现双击      key_m = key_state_1; }else      key_return = key_temp;   //对于无键、长键,返回原事件 break;
case key_state_1:    if ( key_temp == S_key )   //又一次单击(间隔肯定<500ms)    {      key_return = D_key;   //返回双击键事件,回初始状态      key_m = key_state_0;    }else  {    //这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键 if ( key_time_1 >= 50 ) {        key_return = S_key;        //500ms内没有再次出现单键事件,返回上一次的单键事件        key_m = key_state_0;  //返回初始状态 } } break; } return(key_return);}
/* * 下面,根据程序分析按键事件的反映时间: * 1、对于长键,按下超过1s马上响应,反映最快 * 2、对于双键,第2次按键释放后马上得到反映。 * 3、对于单键,释放后延时拖后500ms才能响应,反映最慢。这个与需要判断后面是否有双击操作有关,只能这样。实际应用中,可以调整两次单击间隔时间定义,比如为300ms,这样单击的响应回快一点,单按键操作人员需要加快按键的操作过程。如果产品是针对老年人的,这个时间不易太短,因为年纪大的人,反映和动作都比较慢。 * 当然,上面两段可以合在一起。这样做的目的,是为了可以方便的扩展为N击(当然,需要做修改)。可是最底层的就是最基本的操作处理短按和长按,不用改动的。至于双击,还是N击,在中间层处理。这就是程序设计中分层结构的优点。 * 测试代码环境如下: */
void Timer1_ISRvoid ) interrupt 3     //timer1定时器10ms中断服务{  TH1 = u8TH1_Tmp;  TL1 = u8TL1_Tmp;
  P06 = ~P06;         //P0.3 toggle when interrupt time_10ms_ok = 1;}
main( void ){ Set_All_GPIO_Quasi_Mode;  TIMER1_MODE1_ENABLE;  //定时器1, 模式1, 16bit定时器, 定时器值满 0xFFFF -> 0x0000 产生中断。  clr_T1M;  //T1M = 0,兼容传统 8051,TIMER1时钟 = Fsys/12 = 16M /12  //set_T1M;  //T1M = 1,TIMER1时钟 = Fsys = 16M
u8TH1_Tmp = (65536 - TIMER1_INIT) / 256; u8TL1_Tmp = (65536 - TIMER1_INIT) % 256;
  TH1 = u8TH1_Tmp;  TL1 = u8TL1_Tmp;
  set_ET1;              //enable Timer1 interrupt  set_EA;               //enable interrupts  set_TR1;             //Timer1 run
while ( 1 ) {    if ( time_10ms_ok )    //每10ms执行一次 { time_10ms_ok = 0;      key    = key_read();      //10ms一次调用按键中间层函数,根据返回键值,点亮不同的LED灯,全面测试按键操作是否正常
      if ( key == S_key )      //短按 { IO_BEEP = 0; Timer0_Delay1ms( 10 ); IO_BEEP = 1; }
      else if ( key == D_key )       //双击 { IO_BEEP = 0; Timer0_Delay1ms( 50 ); IO_BEEP = 1; }
      else if ( key == L_key )       //长按 { IO_BEEP = 0; Timer0_Delay1ms( 150 ); IO_BEEP = 1; } } }}

END

来源:网络版权归原作者所有,如有侵权,请联系删除。
嵌入式ARM

扫描二维码,关注更多精彩内容

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
关闭
关闭