×
嵌入式 > 技术百科 > 详情

【单片机笔记】单个按键实现单击、双击、长按的实现

发布时间:2020-06-04 发布时间:
|

直接贴上源码和测试例程,附带的都有中文注释不多做解释。


底层驱动:


#define key_state_0 0

#define key_state_1 1

#define key_state_2 2

#define key_state_3 3

 

#define key_no 0

#define key_click 1

#define key_double 2

#define key_long 3

 

#define key_input P30

/***************************************************************************

程序功能:一个按键的单击、双击、长按。三种按键方式,然后做不同的处理。   

***************************************************************************/

 

static unsigned char key_driver(void)

{

static unsigned char key_state_buffer1 = key_state_0;

static unsigned char key_timer_cnt1 = 0;

unsigned char key_return = key_no;

unsigned char key;


key = key_input;  //read the I/O states


switch(key_state_buffer1)

{

case key_state_0:

if(key == 0)

key_state_buffer1 = key_state_1; 

//按键被按下,状态转换到按键消抖和确认状态//

break;


case key_state_1:

if(key == 0)

{

key_timer_cnt1 = 0;

key_state_buffer1 = key_state_2;

//按键仍然处于按下状态

//消抖完成,key_timer开始准备计时

//状态切换到按下时间计时状态

}

else

key_state_buffer1 = key_state_0;

//按键已经抬起,回到按键初始状态

break;  //完成软件消抖


case key_state_2:

if(key == 1) 

{

key_return = key_click;  //按键抬起,产生一次click操作

key_state_buffer1 = key_state_0;  //转换到按键初始状态

}

else if(++key_timer_cnt1 >= 100)  //按键继续按下,计时超过1000ms

{

key_return = key_long;  //送回长按事件

key_state_buffer1 = key_state_3;  //转换到等待按键释放状态

}

break;


case key_state_3:  //等待按键释放

if(key == 1)  //按键释放

key_state_buffer1 = key_state_0;  //切回按键初始状态

break;

}

return key_return;

}

 

/***************************************************************************

函数功能:中层按键处理函数,调用底层函数一次,处理双击事件的判断,

                                        返回上层正确的无键、单击、双击、长按四种状态

本函数由上层循环调用,间隔10ms

***************************************************************************/

unsigned char key_read(void)

{

static unsigned char key_state_buffer2 = key_state_0;

static unsigned char key_timer_cnt2 = 0;

unsigned char key_return = key_no;

unsigned char key;


key = key_driver();


switch(key_state_buffer2)

{

case key_state_0:

if(key == key_click)

{

key_timer_cnt2 = 0;  //第一次单击,不返回,到下个状态判断是否会出现双击

key_state_buffer2 = key_state_1;

}

else 

key_return = key;  //对于无键、长按,返回原事件

break;


case key_state_1:

if(key == key_click)  //又一次单击,时间间隔小于500ms

{

key_return = key_double;  //返回双击事件,回到初始状态

key_state_buffer2 = key_state_0;

}

else if(++key_timer_cnt2 >= 50)

{

//这里500ms内肯定读到的都是无键事件,因为长按大于1000ms

//在1s前底层返回的都是无键


key_return = key_click;  //500ms内没有再次出现单击事件,返回单击事件

key_state_buffer2 = key_state_0;  //返回初始状态


}

break;

}


return key_return;

}

测试例程(基于51内核)


void main(void)

{

u8 cnt_1ms=0,cnt_100ms=0;

u8 key_value = 0;

u8 led_flash=0;

GPIO_Configuration();

P3M1 &= ~(1<<0);P3M2 &= ~(1<<0); //P30准双向

P1M1 &= ~(1<<2);P1M2 |=  (1<<2); //P12推挽


P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();

P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();

P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();

P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();


enableInterrupts();

IWDG_Configuration();

while(1)

{

if(++cnt_1ms>=10)

{

cnt_1ms=0;

key_value = key_read();

if(key_value != key_no) led_flash = key_value*2;

}

if(++cnt_100ms>=100)

{

cnt_100ms=0;

if(led_flash)

{

led_flash--;

P12 = ~P12;

}

}

}

}


 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
物联传感与Atmel强强联手 达成智能家居战略合作协议