• 按键单击与双击
2021-05-23 06:51:24

按键的单击与双击与长按短按实现方式相近，以下代码仅供参考，写得不是很好

适用于蓝桥杯开发板

程序扩展性不强，更重要的是思路

io.h

#ifndef _IO_H

#define _IO_H

#include "stm32f10x.h"

#define SingleClick 1

#define DoubleClick 2

#define KEY_B1 1

#define KEY_B2 2

#define KEY_B3 3

#define KEY_B4 4

#define TimeInterval 300 //判断双击与单击时间

#define keyState1 1

#define keyState2 2

#define keyState3 3

#define keyState4 4

//enum ss{keyState1,keyState2,keyState3,keyState4}keyState;

enum k{key0,key1,key2,key3};

extern void Delay_Ms(u32 nTime);

void RCC_Init(void);

void IO_Init(void);

void LED_Control(u16 nled , u8 flag);

u8 KEY_Scan(void);

void Key_Double(void);

#endif

io.c

u8 KEY_Scan(void)//按键扫描函数，查找键值

{

static u8 flag = 1;

if(flag&&(KEY0==0||KEY1==0||KEY2==0||KEY3==0))

{

Delay_Ms(10);

flag = 0;

if(KEY0==0)return key0;

else if(KEY1==0)return key1;

else if(KEY2==0)return key2;

else if(KEY3==0)return key3;

}

else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==1)flag = 1;

return 0xff;

}

//单击双击

/*

1、两次间隔10ms - 300ms以内是双击, 按下第一次开始计时

2、300ms 之后没有按下第二次就是单击

3、思路与我按键单击双击的思维在方向上不太一样，这里是直接状态中判断按键

*/

void Key_Double(void)

{

static u8 key_value = 0xff;

// static u16 keynum1 = 0,keynum2 = 0;

static u8 key = 0; //记录第一次按键是谁按下

switch(keyState)//keyState见宏定义，是按键第一次按下

{

case keyState1: key_value = KEY_Scan();

if(key_value != 0xff){

// keynum1 = keyTime;

flag_1 = 1;

keyState = keyState2;

if(key_value==key0)key = 1;

else if(key_value==key1)key = 2;

else if(key_value==key2)key = 3;

else if(key_value==key3)key = 4;

}

else

{

flag_1 = 0;

keyState = keyState1;

}

break;

case keyState2: key_value = KEY_Scan();

if(keyTime<300)

{

switch(key)

{

case 1:if(key_value==key0){

keyDouble = KEY_B1;flag_1 = 0;

keyTime = 0;

keyState = keyState1;

} break;

case 2:if(key_value==key1){

keyDouble = KEY_B2;flag_1 = 0;

keyTime = 0;

keyState = keyState1;

} break;

case 3:if(key_value==key2){

keyDouble = KEY_B3;flag_1 = 0;

keyTime = 0;

keyState = keyState1;

}

break;

case 4:if(key_value==key3){

keyDouble = KEY_B4;flag_1 = 0;

keyTime = 0;

keyState = keyState1;

}

break;

}

}

else

{

switch(key)

{

case 1:keySingle = KEY_B1; break;

case 2:keySingle = KEY_B2; break;

case 3:keySingle = KEY_B3; break;

case 4:keySingle = KEY_B4; break;

}

flag_1 = 0;

keyTime = 0;

keyState = keyState1;

key = 0;

}

break;

case keyState3:

break;

case keyState4:

break;

default: break;

}

}

更多相关内容
• 单击后，马上返回按键值单击后，释放之后，返回按键值单击后，按住不放，多次返回按键值但是在其上面扩展双击和三击以及多击程序时，遇到了麻烦(其实就是不会啦)，于是在网上看了某个老师的经典按键程序，...

下面这段是引言，和按键程序实质内容没有任何关系，可以当P话，可直接跳到分割线的地方。

最近自己在琢磨按键程序，之前弄了，按键单击程序，程序可以实现读取按键的几个状态，然后根据需求使用。单击按键的几个状态如下：

单击后，马上返回按键值

单击后，释放之后，返回按键值

单击后，按住不放，多次返回按键值

但是在其上面扩展双击和三击以及多击程序时，遇到了麻烦(其实就是不会啦)，于是在网上看了某个老师的经典按键程序，里面讲了单击和双击，拿着源程序理解了半天，终于一知半解了(一知半解的状态就是能读懂思想，但是闭卷完全自己写，写不出)。但是个人觉得其中的消抖部分还有按键释放的部分还可以改善，还有根据其思路扩展了三击以及N击，于是写了这篇博客供自己以后遗忘时参考以及跟大家分享。

正文：

此按键程序的实现的功能是单个独立按键的[单击]，[长按]，[双击]，[三击]以及[多击]。本文分为三个部分，

第一个部分是说[单击]，[长按]的程序；

第二部分是讲[双击]；

第三部分是讲[三击]，[多击]；

一、[单击]、[长按]程序

1. 简单介绍本按键程序的单击和长按

首先说一下单击，长按的响应情况，就是按多久算单击或者长按，按下按键马上返回有效键值，还是释放之后返回有效键值等等，下面说下它在什么情况下返回有效的【单击】和【长按】。

首先看一张时序图：

注：

T1：是单击的按键消抖时长，这里预设的是30ms，也可以根据需求自行定义；

T2：是单击时，按键释放的有效时间段，提前或者超过这个时间段释放的按键都再是单击了。提前释放则是无效键值，超过后释放则是长按。

T3：是长按时长，按键超过此时长，则为长按。这里的预设值是3s，同样可根据需求自行更改。

【单击】：按键按下超过消抖时长T1(30ms)，并且在T2时间段内释放按键，按键一释放，马上返回有效按键值—【单击】。

注意：单击是释放后，才返回有效按键值，不释放时，是无效按键值。

【长按】：按键按下的时间超过预设的长按时长T3(3s) ，马上返回有效按键值—【长按】；

注意：双击是只要按下的时间超过预设的长按时长，马上返回有效键值。但是，如果按键一直按着不释放，则只返回一次有效按键值，不重复返回，直到释放之后，才开始重新读取键值。

2. 按键程序的架构

按键程序可以分为四个部分，第一部分：判断有无按键按下；第二部分：按键是否有效(按键消抖)；第三部分：确定有效按键的种类(单击还是长按)；第四部分：等待按键释放。

3. 按键程序的源代码以及注释

程序的注释写的很详细，应该是可以读懂的，如果有疑问可以留言讨论。

以下是key.c 的源代码：

#define KEY_INPUT P1.0 //按键IO

#define KEY_STATE_0 0 //按键状态

#define KEY_STATE_1 1

#define KEY_STATE_2 2

#define KEY_STATE_3 3

#define LONG_KEY_TIME 300 //LONG_KEY_TIME*10MS = 3S

#define SINGLE_KEY_TIME 3 //SINGLE_KEY_TIME*10MS = 30MS

#define N_KEY 0 //no click

#define S_KEY 1 //single click

#define L_KEY 10 //long press

void key_driver(void)

{

static byte key_state; //按键状态变量

static word key_time; //按键计时变量

byte key_press, key_return;

key_return = N_KEY; // 清除 返回按键值

key_press = KEY_INPUT; // 读取当前键值

switch (key_state)

{

case KEY_STATE_0: // 按键状态0：判断有无按键按下

if (!key_press) // 有按键按下

{

key_time = 0; // 清零时间间隔计数

key_state = KEY_STATE_1; // 然后进入 按键状态1

}

break;

case KEY_STATE_1: // 按键状态1：软件消抖(确定按键是否有效，而不是误触)。按键有效的定义：按键持续按下超过设定的消抖时间。

if (!key_press)

{

key_time++; // 一次10ms

if(key_time>=SINGLE_KEY_TIME) // 消抖时间为：SINGLE_KEY_TIME*10ms = 30ms;

{

key_state = KEY_STATE_2; // 如果按键时间超过 消抖时间，即判定为按下的按键有效。按键有效包括两种：单击或者长按，进入 按键状态2， 继续判定到底是那种有效按键

}

}

else key_state = KEY_STATE_0; // 如果按键时间没有超过，判定为误触，按键无效，返回 按键状态0，继续等待按键

break;

case KEY_STATE_2: // 按键状态2：判定按键有效的种类：是单击，还是长按

if(key_press) // 如果按键在 设定的长按时间 内释放，则判定为单击

{

key_return = S_KEY; // 返回 有效按键值：单击

key_state = KEY_STATE_0; // 返回 按键状态0，继续等待按键

}

else

{

key_time++;

if(key_time >= LONG_KEY_TIME) // 如果按键时间超过 设定的长按时间(LONG_KEY_TIME*10ms=200*10ms=2000ms), 则判定为 长按

{

key_return = L_KEY; // 返回 有效键值值：长按

key_state = KEY_STATE_3; // 去状态3，等待按键释放

}

}

break;

case KEY_STATE_3: // 等待按键释放

if (key_press)

{

key_state = KEY_STATE_0; // 按键释放后，进入 按键状态0 ，进行下一次按键的判定

}

break;

default: // 特殊情况：key_state是其他值得情况，清零key_state。这种情况一般出现在 没有初始化key_state，第一次执行这个函数的时候

key_state = KEY_STATE_0;

break;

}

return key_return; // 返回 按键值

}

使用注意：

1)硬件：按键的一端接地(GND)，另一端接IO口。IO为输入，一定要有上拉电阻。

2)定时器：这里为了精确的定时，所以使用了定时器，定时器的时间是10ms。

3)扫描周期：调用此函数时，一定确保”扫描周期“要小于10ms。不然按键内所涉及的时间就会不准，会偏大。所涉及的时间包括消抖时长，按键长按时长等。

扫描周期定义：从 第一次进入按键扫描程序 开始，到第二次进入按键扫描程序时 结束，之间所用的时间。

测量扫描周期的方法：可以在按键扫描程序的第一句，添加IO口取反函数，然后用示波器查看改IO口，其IO口周期的一般就是扫描周期了。

4. 按键程序的使用实例

这里以C51位硬件平台进行实例讲解

1)实例程序的功能：

单击：点亮LED1

长按：熄灭LED1

2)硬件：

按键IO：P1.0

LED1 ：P2.0

以下是 main.c 源代码:

#include "reg51.h"

#include "key.c"

sbit LED1 = P2.0; //定义LEDIO口

unsigned char g_u8_KeyValue; //按键值

unsigned char g_flag_10ms_key; //10ms 计时标志

//timer0，初始化函数 ，定时时间为 10ms

void T0_Init_10ms(void)

{

TMOD |= 0x01;

TH0 = (65535 - 10000)/256;

TL0 = (65535 - 10000)%256;

ET0 = 1;

TR0 = 1;

EA = 1;

}

//主函数

void main(void)

{

P1.0 = 1; //P1.0 拉高

T0_Init_10ms(); //定时器0，初始化，定时10ms

while(1)

{

if(g_flag_10ms_key) //等待10ms,定时完成

{

g_flag_10ms_key = 0; //清零10ms定时标志

g_u8_KeyValue = key_driver(); //读取按键值

switch(g_u8_KeyValue)

{

case S_Key: LED1 = 1; break; //单击 点亮LED1

case L_Key: LED1 = 1; break; //长按 熄灭LED1

}

}

}

}

//timer0 中断服务程序

void IRQ_T0(void) interrupt 1

{

g_flag_10ms_key = 1; //置位 10ms 定时标志

}

pillarpeng

2016.3.23 18:00

…未完待续

展开全文
• 检测长按 短按 连击等各种状态按键检测程序，使用C语言编写
• 按键C语言程序zhchxgh | 2009-07-04 01:46:51 阅读：8246 发布文章一共用了四个按钮.#define_KEYDOWN_TEST_TIME(20)unsignedcharIsKeyDown(volatileunsignedcharValue,unsignedcharpin){unsignedlongCurSta...

长按键C语言程序

zhchxgh | 2009-07-04 01:46:51    阅读：8246

发布文章

一共用了四个按钮.

#define _KEYDOWN_TEST_TIME      (20)

unsigned char IsKeyDown(volatile unsigned char Value, unsigned char pin)

{

unsigned long CurState = 0, i;

for(i = 0; i

CurState += _GET_BIT(Value, pin)? 0:1;     //键盘接了上拉电阻,低电平才是按下

if(CurState == _KEYDOWN_TEST_TIME)

return 1;

return 0;

}

//以下所有值均是以 DealWithKey函数的调用频率为基础的，该频率是定时器2的定时值决定的

//短按键的计数值，只有当按键检测计数器计数大于等于此值时才认为是一次短按

#define _KEY_SHORT_CNTR             (2)

//长按键的计数值，只有当按键检测计数器计数大于等于此值时才认为是一次长按

#define _KEY_LONG_CNTR              (_KEY_SHORT_CNTR * 3)

//无按键按下时的按键检测间隔，用于按键消抖动

#define _KEY_NORMAL_DEVIDER         (2)

//此值用于按钮长按后，按钮检测函数的执行频率

//此值用于按钮短按后，按钮检测函数的执行频率

//此值用于设置蜂鸣器鸣响时间

#define _BEEPER_DEVIDER             (10)

void DealWithKey(void)

{

static unsigned int AddCntr = 0;

static unsigned int MinCntr = 0;

static unsigned int UnitCntr = 0;

static unsigned int RunCntr = 0;

static unsigned char BeepCntr = 0;

static unsigned int DevCntr = 0;

static unsigned char LastRunState = 0;

unsigned char temp;

if(g_State != Setting)  //运行状态, 所有按键都无效

return;

if(BeepCntr > 0)        //处理蜂鸣器

--BeepCntr;

else

_BEEPER_OFF;

if(DevCntr)           //按键处理分频器

{

--DevCntr;

return;

}

//这个按钮是可以重复进入的, 长按后先低频率动作, 当动作几次后再高频率动作

{

...

}

//同上

MinCntr = IsKeyDown(_PIN(_TO_KEY_MIN), _KEY_MIN)? MinCntr + 1 : 0;

if((temp = (MinCntr >= _KEY_LONG_CNTR)) || MinCntr >= _KEY_SHORT_CNTR)

{

...

}

//这个按钮是不可重复进入的, 就是说只有抬起后再按下才动作

UnitCntr = IsKeyDown(_PIN(_TO_KEY_UNIT), _KEY_UNIT)? UnitCntr + 1 : 0;

if(UnitCntr == _KEY_SHORT_CNTR)

{

...

}

else if(UnitCntr > _KEY_SHORT_CNTR)

{

UnitCntr = _KEY_SHORT_CNTR + 1; //禁止重复执行

}

//这个按钮是要在按钮抬起后才执行其他函数的

if(IsKeyDown(_PIN(_TO_KEY_RUN), _KEY_RUN))

{

++RunCntr;

}

else

{

RunCntr = 0;

if(LastRunState)            //表明键已经按下后才抬起的

{

LastRunState = 0;

g_State = EmptyInflatting;

}

}

if(RunCntr == _KEY_SHORT_CNTR)

{

BeepCntr = _BEEPER_DEVIDER;

_BEEPER_ON;

LastRunState = 1;       //此键是抬起时生效.

}

else if(RunCntr > _KEY_SHORT_CNTR)

{

RunCntr = _KEY_SHORT_CNTR + 1;  //禁止重复执行

}

DevCntr = _KEY_NORMAL_DEVIDER;

}

*博客内容为网友个人发布，仅代表博主个人观点，如有侵权请联系工作人员删除。

参与讨论

请登录...

登录后参与讨论

展开全文
• （1）如果为按键按下到释放的一个过程，t1 如果大于 250ms 认为按键有效 否则 按键无效，不做处理。 （2）如果联系两个双脉冲，脉冲之间相差时间t2 < 1S 认为是 双按键 否则 判定为两次不相干的按键行为。 （3...

【一】：按键的模型
（1）单击按键： 按键按下到释放的一个过程，t1 如果大于 50ms.

（2）双击按键：如果两个脉冲之间相差时间t2 < 200ms 认为是 双按键
否则 判定为两次不相干的按键行为。
<同样可以判定连续多次按键，但是一般没什么意义>

（3）长按键：如果按下时间t3 >=500ms 判定为长按键

【二】主函数的处理
按键的处理函数： void APP_KEY_Task(void) 。 需要每5ms 调用一次
该函数需要判断上次状态last，以及当前的状态now。

所以主函数就显得比较简单：

void  act0 ( KEY_StateMachine *   pStateMachine);
void  act1 ( KEY_StateMachine *   pStateMachine);
void  act2 ( KEY_StateMachine *   pStateMachine);
void  act3 ( KEY_StateMachine *   pStateMachine);

ActionFunType transition_table[KEY_STATES][KEY_STATES]={
{&act3,&act0,},
{&act2,&act1,},
};

void KEY_GPIO_DEAL(MYKEY_TYPE* mykey)
{
KEY_State  State_now= KEY_STATES_RELEASE ;

(*transition_table[mykey->Machine.State_last][State_now] )( (KEY_StateMachine *) (&(mykey->Machine))  );  //根据状态 *FUNC【last】【now】 执行对应的处理函数

mykey->Machine.State_last=State_now;  //保存当前的按键状态
}


这个函数数值中依次对应关系为：

其中act0: 表示 从释放状态到按下，为按下按键的瞬间
其中act1: 表示 从按下状态到按下，为保持按下的状态
其中act2: 表示 从按下状态到释放，为释放按键的瞬间
其中act3: 表示 从释放状态到释放，为保持释放的状态

在这一步中我们不需要关系act0–3回调函数执行了什么，我们关系的是当前状态和上一个状态是否按下，然后执行哪种回调处理即可！

【三】按键的判断的处理。
定义一个结构体：

typedef struct
{
KEY_State         State_last;       //记录当前的时间
uint32_t          usTime;        //记录按下的时间
uint32_t          usTS;          //记录释放的时间
uint32_t          usKeyDtcNum;	 //记录脉冲数
KeyDeal           NO_PRO_Deal;
KeyDeal           SHOURT_Deal;
KeyDeal           LONG_Deal;
KeyDeal           DOUBLE_Deal;
}KEY_StateMachine,*KEY_pStateMachine;


依次保存上一次调用时候的状态：State_last，
按下保持时间的计时：usTime
释放保持时间的计时：usTS
满足连续单击按钮的次数：usKeyDtcNum

执行：act0: usTime=0

执行：act1: usTime++
if(usTime== 500ms)

usKeyDtcNum=0； //清空连续单击按钮的次数
LONG_Deal(); //回调长按键处理
｝ //

在长按键处理上 如果==500s 那么一直按只会调用一次（不考虑溢出）如果加上判断可以实现长按快速增加数值的，例如：像SMC表头长按按键快速增减，随着长按的时间的增加，数值增加的速度也会加快。

执行：act2: usTS=0
if( 50ms < usTime< 200ms)
{
usKeyDtcNum++; //连续单击按钮的次数增加
}

执行：act3:
if(usTS<200ms)usTS++
else{
if( usKeyDtcNum == 1)SHOURT_Deal)(); //短按键处理
if(usKeyDtcNum >= 2) DOUBLE_Deal)(); //双击按键处理
usKeyDtcNum=0; usTS=0; //清空标志
}

这里可以判断单击，双击，甚至连续三击。。（双击之上的判断没什么意义）

附：

#include "bsp/key/bsp_key.h"

MYKEY_TYPE  MYKEY1 = {
{RCC_APB2Periph_GPIOB,GPIOB,GPIO_Pin_4},
{0,0,0,0,0,0,0,0, },
};

MYKEY_TYPE  MYKEY2 = {
{RCC_APB2Periph_GPIOB,GPIOB,GPIO_Pin_3},
{0,0,0,0,0,0,0,0, },
};

void  act0 ( KEY_StateMachine *   pStateMachine);
void  act1 ( KEY_StateMachine *   pStateMachine);
void  act2 ( KEY_StateMachine *   pStateMachine);
void  act3 ( KEY_StateMachine *   pStateMachine);

ActionFunType transition_table[KEY_STATES][KEY_STATES]={
{&act3,&act0,},
{&act2,&act1,},
};

void KEY_GPIO_Init( MYKEY_TYPE* mykey )
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(mykey->keyset.RCC_AHB1Periph, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = mykey->keyset.Pin;
GPIO_Init(mykey->GPIOx, &GPIO_InitStructure);
mykey->Machine.State_last=0;
mykey->Machine.usKeyDtcNum=0;
mykey->Machine.usTime=0;
mykey->Machine.usTS=0;
}

void KEY_GPIO_DEAL(MYKEY_TYPE* mykey)
{
KEY_State  State_now= KEY_STATES_RELEASE ;

(*transition_table[mykey->Machine.State_last][State_now] )( (KEY_StateMachine *) (&(mykey->Machine))  );  //根据状态 *FUNC【last】【now】 执行对应的处理函数

mykey->Machine.State_last=State_now;  //保存当前的按键状态
}

//释放状态被按下
void  act0 ( KEY_StateMachine *  pStateMachine)
{
pStateMachine->usTime=0;
}
//按下状态
void  act1 ( KEY_StateMachine *   pStateMachine)
{
uint32_t number=0;
pStateMachine->usTime++;
if( pStateMachine->usTime ==  KEY_PUSH_0500MS  )
{
pStateMachine->usKeyDtcNum=0;
(*pStateMachine->LONG_Deal)(); //长按键处理
}
}
//按下状态被释放
void  act2 ( KEY_StateMachine *   pStateMachine)
{
pStateMachine->usTS=0;
if ( ( pStateMachine->usTime >KEY_PUSH_0050MS) && ( pStateMachine->usTime <KEY_PUSH_0200MS) )
{
pStateMachine->usKeyDtcNum++;
}
}
//释放状态
void  act3 ( KEY_StateMachine *   pStateMachine)
{
if( pStateMachine->usTS < KEY_PUSH_0200MS )
{
pStateMachine->usTS++;
}else
{
if(pStateMachine->usKeyDtcNum == 1)
{
(*pStateMachine->SHOURT_Deal)(); //短按键处理
}
if(pStateMachine->usKeyDtcNum >= 2)
{
(*pStateMachine->DOUBLE_Deal)(); //双击按键处理
}
pStateMachine->usKeyDtcNum=0;
pStateMachine->usTS=0;

}
}
/*********************END OF FILE*********************/

#ifndef __BSP_KEY_H__
#define __BSP_KEY_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include <stm32f10x.h>

/* 类型定义 --------------------------------------------------------------*/
typedef enum
{
KEY_UP   = 0,
KEY_DOWN = 1,
}KEYState_TypeDef;

#define KEY_PUSH               0
#define KEY_PUSH_0050MS        10    //定义按键判断时间  10X5ms= 50MS
#define KEY_PUSH_0200MS        40    //定义按键判断时间   40X5ms=200MS
#define KEY_PUSH_0500MS        100   //定义按键判断时间   100X5ms=500MS

typedef int KEY_State;
typedef int KEY_Condition;

//状态
#define KEY_STATES            2
#define KEY_STATES_RELEASE    0
#define KEY_STATES_PUSH       1

typedef void  (*KeyDeal)( void);

typedef struct
{
KEY_State         State_last;       //记录当前的状态
uint32_t          usTime;        //记录按下的时间
uint32_t          usTS;          //记录释放的时间
uint32_t          usKeyDtcNum;	 //记录脉冲数
KeyDeal           NO_PRO_Deal;
KeyDeal           SHOURT_Deal;
KeyDeal           LONG_Deal;
KeyDeal           DOUBLE_Deal;

}KEY_StateMachine,*KEY_pStateMachine;

typedef void  (*ActionFunType)( KEY_pStateMachine  pStateMachine);
typedef struct
{
uint32_t   RCC_AHB1Periph;
GPIO_TypeDef*   GPIOx;
uint16_t        Pin;
}MYKEY_SET_TYPE;
typedef struct
{
MYKEY_SET_TYPE    keyset;
KEY_StateMachine  Machine;
}MYKEY_TYPE;

//PB3 PB6 PB8
/* 宏定义 --------------------------------------------------------------------*/
#define KEY1_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOB
#define KEY1_GPIO_PIN                 GPIO_Pin_3
#define KEY1_GPIO                     GPIOB
#define KEY1_DOWN_LEVEL               0  /* 根据原理图设计，KEY1按下时引脚为低电平，所以这里设置为0 */

#define KEY2_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOB
#define KEY2_GPIO_PIN                 GPIO_Pin_6
#define KEY2_GPIO                     GPIOB
#define KEY2_DOWN_LEVEL               0  /* 根据原理图设计，KEY1按下时引脚为低电平，所以这里设置为0 */

extern  MYKEY_TYPE  MYKEY1;
extern  MYKEY_TYPE  MYKEY2;
void KEY_GPIO_Init( MYKEY_TYPE* mykey );
void KEY_GPIO_DEAL(MYKEY_TYPE* mykey);

#endif  // __BSP_KEY_H__

/*****END OF FILE****/



调用：如果使用的不是操作系统的话，可以让主函数每5ms调用一次即可。本函数的回调函数尽量不要搞成阻塞的。如果使用操作系统，阻塞一些也没啥毛病。。。

void led0_task(void *pvParameters)
{
MYKEY1.Machine.NO_PRO_Deal=callback10;
MYKEY1.Machine.SHOURT_Deal=callback11;
MYKEY1.Machine.DOUBLE_Deal=callback12;
MYKEY1.Machine.LONG_Deal  =callback13;
KEY_GPIO_Init( &MYKEY1 );
MYKEY2.Machine.NO_PRO_Deal=callback20;
MYKEY2.Machine.SHOURT_Deal=callback21;
MYKEY2.Machine.DOUBLE_Deal=callback22;
MYKEY2.Machine.LONG_Deal  =callback23;
KEY_GPIO_Init( &MYKEY2 );
while(1)
{
KEY_GPIO_DEAL(&MYKEY1);
KEY_GPIO_DEAL(&MYKEY2);
}
}

展开全文
• if(state_1 == S_key) //双击 { /*双击按键实现呼吸灯功能*/ state_1 = 0; b_key_led = 1; b_key_smg = 0; seg = 0x00; seg_l = 0x00; } if(state_1 == D_key) //单按 { /*单击实现数码管走时*/ state_1 = 0; b_...
• 原理：将按键这一事件的过程划分成如下几个状态：//stata 函数运行状态//0： 初始状态//1： 第一洗按键按下//2： 第一次长按抬起//3： 第一次短按抬起//4： 第二次按键按下//5： 第二次按键抬起利用定时器记录系统...
• STATE_KIDEL：如果有按键，查表，看是第几个按键。(排除8个IO口中，你不用做按键的那些IO。另外也是keyport中是从0开始的，而记在temp中是从0开始的)。Key_ThisValue=temp+1； 当前键值KeyState=STATTE_KDOWN； 按键...
• 一个按键扫描的程序很经典，有单击 双击 还有长按 都可以自己设置时间参数，而且双击的时候不会出发单击，里面的算法思想很经典，我经常使用可以拿来学习一下··
• no 0#define key_click1#define key_double2#define key_long3#define key_inputP30/***************************************************************************程序功能：一个按键的单击、双击、长按。...
• 利用定时器，外部中断，串口，GPIO完成的一个stm32小项目。
• button drive杰杰自己写的一个按键驱动，支持单双击、连按、长按；采用回调处理按键事件(自定义消抖时间)，使用只需3步，创建按键按键事件与回调处理函数链接映射，周期检查按键。前言前几天写了个按键驱动，参考...
• 不影响使用.// 如有朋友发现问题所在请联系我./*********************************************************/#include #define KEY_IO P1 //按键所连的IO口#define NO_KEY_VALUE 0xf //当按键没有被按下时IO口的值#...
• #include "keyboard.h"/***************************************************************************程序功能：一个按键的单击、双击、长按。三种按键方式，然后做不同的处理。这里以P1口的LED变化作为测试单击：...
• 单击开始，单击 控制面板，然后双击“区域和语言选项”。2. 在语言选项卡上的“文字服务和输入语言”下，单击详细信息。3. 在首选项下，单击语言栏。4,选择“关闭高级文字服务”复选框,,把里面的钩去掉.三.其次设置...
• ## 【按键】[独立按键] - 2：双击

千次阅读 多人点赞 2016-03-29 10:28:55
1）在预设的时间间隔内完成第二次【单击】，按键释放后，响应返回有效键值【双击】。 2）如果第二次按下键并一直按住，当按住的时间超过设定的时间间隔（300ms）后，会响应第一个【单击】，并返回有效键值【单击】...
• #include #include"intrins.h"sbit key=P3^5;sbit LED=P3^4;unsigned char L,value,time,num;bit S,flag;voiddelay_ms(unsigned char z){unsigned int x,y;for(x=z; x>0; x--)for(y=848; y>...
• 上一篇文章记录了TM1638驱动的显示模块的显示功能C语言程序，详见TM1638显示板（8数码管+8LED+8按键）驱动程序（显示功能），本文分享按键的驱动，以及按键的去抖动等操作。 模块如下图： 笔者采用的MCU是STM32F103...
• 在xp系统中，很多使用VC++6.0编译C程序的用户们都经常会遇到C语言程序闪退的问题，在编译器中调试运行的时候一切正常，可将DEBUG中生成的EXE文件拿出来双击运行却发现程序运行完后就闪退了。怎么办?今天小编介绍系统...
• 前言正好工作中用到按键处理，需要处理单击、长按等按键事件，然后就造了这么一个轮子，为了以后更方便地加入其它的项目中使用，遂将其开源到 GitHub 中。后面发现 RT-Thread 软件包里也有一个开源的按键库 ...
• C语言编写的单片机流水灯程序的软件和硬件，可以让八个LED轮流点亮，每个灯点亮和熄灭时间均为1秒。是利用单片机I/O口控制外部设备的简单例子。当然，在你掌握了本程序后，完全可以充分发挥你的想象，改变一下程序...
• 在嵌入式系统尤其是单片机系统中经常用到按键检测和处理，这里提供一个标准的驱动函数模块MultiButton，能够提供按下、弹起、单击、双击、连击、长按等按键事件。 MultiButton 是一个小巧简单易用的事件驱动型按键...
• 当我们写完这个程序 编译完成后单击左上角的叹号运行 可以看到一切正常 按下任意按键后窗口才会消失。很容易就能搞定了，下面就给大家讲解一下C语言程序闪退的快速处理方法：1、我们以最经典的HELLOWOR...
• C语言程序设计上机指导书及答案》由会员分享，可在线阅读，更多相关《C语言程序设计上机指导书及答案(36页珍藏版)》请在人人文库网上搜索。1、姓 名：学 号：专 业：日 期：指导原则：促进学生针对实际问题，用所...
• 第九节：独立按键的双击按键触发。开场白：上一节讲了在定时中断函数里处理独立按键的扫描程序，这种结构的程序我用在了很多项目上。这一节教大家如何实现按键双击触发的功能，这种功能类似鼠标的双击。要教会大家一...
• /*发送和接收程序：即主机和从机可共用此程序程序效果：通过主机发送，从机接收在主机中通过记下按键按下的次数，主机中显示最后按下的六个数值，并发送给从机，从机也显示这六个数值单片机类型：stc89c52完整程序...
• 基于51单片机的独立按键单击、双击，长按，多次按的项目工程一、前言1、基于51单片机的独立按键单击、双击，长按，多次按的项目工程包括用Keil软件编写单片机C语言程序和用Proteus软件仿真单片机外围电路2、基于51...
• 编了个C语言的键盘程序有点问题,请指点下![复制链接]做了个机械手,想用键盘来控制抓,放物品,现在他显示字符时有点错,高手能帮我在keil里跑下,把我的这个错改下吗?谢谢了!原程序如下:(P2.0--P2.7 是段选,P1.0--P1.5是...
• C语言的基本框架的第1章 C语言的基本框架 上机指导本节将提供4个实验的指导，通过本节内容的学习和实践，读者可以更好地了解C语言程序，并熟悉Turbo C 2．0集成环境。【实验1．1】 设计简单菜单界面。1．实验题目...

...