这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» MCU» 一个按键实现【单击/双击/长按】的单片机demo程序

共27条 1/3 1 2 3 跳转至

一个按键实现【单击/双击/长按】的单片机demo程序

工程师
2021-09-02 23:01:19 打赏

一个按键实现【单击/双击/长按】的单片机 demo程序,芯片采用新唐的N76E003,但理论上可以改成其它MCU.


Enjoy!


#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_ISR (void) 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;

}

}

}

}





关键词: 按键 双击 单击 长按 demo

工程师
2021-09-03 23:19:02 打赏
2楼

很好的参考源码!


专家
2021-09-05 08:12:17 打赏
3楼

按键程序


专家
2021-09-05 08:14:00 打赏
4楼

学习了,谢谢提供。


专家
2021-09-05 08:27:04 打赏
5楼

学习学习


高工
2021-09-05 08:56:55 打赏
6楼

感谢楼主的分享,学习了


专家
2021-09-05 09:07:02 打赏
7楼

谢谢分享


专家
2021-09-05 09:38:21 打赏
8楼

理解


工程师
2021-09-05 16:08:31 打赏
9楼

难得一见的源码!


工程师
2021-09-05 16:15:29 打赏
10楼

很实用的按键功能, 收藏研究一下


共27条 1/3 1 2 3 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]