单片机 c语言 按键长按短按,【单片机笔记】单个按键实现单击、双击、长按的实现...

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

底层驱动:#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_click1#define key_double2#define key_long3#define key_inputP30/***************************************************************************程序功能:一个按键的单击、双击、长按。三种按键方式,然后做不同的处理。***************************************************************************/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 statesswitch(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开始准备计时//状态切换到按下时间计时状态}elsekey_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;}elsekey_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;}}}}

By Urien 2018年6月7日 11:29:47

你可能感兴趣的:(单片机,c语言,按键长按短按)