-
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;
#define KEY0 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define KEY2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define KEY3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
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;
}
}
更多相关内容 -
【按键】[独立按键] - 单击,双击,三击以及N击
2021-05-23 06:52:52单击后,马上返回按键值单击后,释放之后,返回按键值单击后,按住不放,多次返回按键值但是在其上面扩展双击和三击以及多击程序时,遇到了麻烦(其实就是不会啦),于是在网上看了某个老师的经典按键程序,...下面这段是引言,和按键程序实质内容没有任何关系,可以当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
…未完待续
-
各种按键状态的检测程序
2010-06-03 09:55:45检测长按 短按 连击等各种状态按键检测程序,使用C语言编写 -
长按键C语言程序
2021-05-19 13:07:29长按键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 _ADDMIN_FAST_DEVIDER (15)
//此值用于按钮短按后,按钮检测函数的执行频率
#define _ADDMIN_LONG_DEVIDER (_ADDMIN_FAST_DEVIDER * 3)
//此值用于设置蜂鸣器鸣响时间
#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;
}
//这个按钮是可以重复进入的, 长按后先低频率动作, 当动作几次后再高频率动作
AddCntr = IsKeyDown(_PIN(_TO_KEY_ADD), _KEY_ADD)? AddCntr + 1 : 0;
if((temp = (AddCntr >= _KEY_LONG_CNTR)) || AddCntr >= _KEY_SHORT_CNTR)
{
...
}
//同上
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;
}
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。
参与讨论
请登录...
登录后参与讨论
-
C语言处理按键的 单击(短按),长按,双击,多击 处理
2020-01-08 22:30:32(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 ; if(GPIO_ReadInputDataBit(mykey->keyset.GPIOx,mykey->keyset.Pin)==KEY_PUSH)State_now= KEY_STATES_PUSH; //读取当前按键状态 (*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 ; if(GPIO_ReadInputDataBit(mykey->keyset.GPIOx,mykey->keyset.Pin)==KEY_PUSH)State_now= KEY_STATES_PUSH; //读取当前按键状态 (*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); vTaskDelay(5); } }
-
单片机按键程序单击双击长按有不同功能(c语言源程序)
2021-05-19 13:07:27if(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_... -
51单片机按键检测源程序(实现单击、双击、长按等功能)
2021-05-25 03:04:54原理:将按键这一事件的过程划分成如下几个状态://stata 函数运行状态//0: 初始状态//1: 第一洗按键按下//2: 第一次长按抬起//3: 第一次短按抬起//4: 第二次按键按下//5: 第二次按键抬起利用定时器记录系统... -
分析一个按键程序(长按 短按 双击)
2021-05-19 15:35:39STATE_KIDEL:如果有按键,查表,看是第几个按键。(排除8个IO口中,你不用做按键的那些IO。另外也是keyport中是从0开始的,而记在temp中是从0开始的)。Key_ThisValue=temp+1; 当前键值KeyState=STATTE_KDOWN; 按键... -
按键单击+双击+长按.rar
2015-06-24 21:27:54一个按键扫描的程序很经典,有单击 双击 还有长按 都可以自己设置时间参数,而且双击的时候不会出发单击,里面的算法思想很经典,我经常使用可以拿来学习一下·· -
【单片机笔记】单个按键实现单击、双击、长按的实现
2021-05-20 06:26:19no 0#define key_click1#define key_double2#define key_long3#define key_inputP30/***************************************************************************程序功能:一个按键的单击、双击、长按。... -
stm32 按键实现短按,长按,双击,组合,hold
2018-03-28 10:02:15利用定时器,外部中断,串口,GPIO完成的一个stm32小项目。 -
纯C语言写的按键驱动,将按键逻辑与按键处理事件分离~
2021-05-19 13:55:17button drive杰杰自己写的一个按键驱动,支持单双击、连按、长按;采用回调处理按键事件(自定义消抖时间),使用只需3步,创建按键,按键事件与回调处理函数链接映射,周期检查按键。前言前几天写了个按键驱动,参考... -
单片机检测按键短击,连击c程序
2021-05-20 09:32:51不影响使用.// 如有朋友发现问题所在请联系我./*********************************************************/#include #define KEY_IO P1 //按键所连的IO口#define NO_KEY_VALUE 0xf //当按键没有被按下时IO口的值#... -
51单片机实现单按键单击、双击、长按功能
2021-05-20 08:26:05#include "keyboard.h"/***************************************************************************程序功能:一个按键的单击、双击、长按。三种按键方式,然后做不同的处理。这里以P1口的LED变化作为测试单击:... -
c语言如何实现组合键
2021-05-20 04:15:41单击开始,单击 控制面板,然后双击“区域和语言选项”。2. 在语言选项卡上的“文字服务和输入语言”下,单击详细信息。3. 在首选项下,单击语言栏。4,选择“关闭高级文字服务”复选框,,把里面的钩去掉.三.其次设置... -
【按键】[独立按键] - 2:双击
2016-03-29 10:28:551)在预设的时间间隔内完成第二次【单击】,按键释放后,响应返回有效键值【双击】。 2)如果第二次按下键并一直按住,当按住的时间超过设定的时间间隔(300ms)后,会响应第一个【单击】,并返回有效键值【单击】... -
用stc15w101单片机写的按键单击双击长按程序,怎么加上休眠功能?
2021-05-23 03:04:58#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驱动显示板(8数码管+8LED+8按键)单片机C语言程序(按键功能)
2021-11-23 23:40:09上一篇文章记录了TM1638驱动的显示模块的显示功能C语言程序,详见TM1638显示板(8数码管+8LED+8按键)驱动程序(显示功能),本文分享按键的驱动,以及按键的去抖动等操作。 模块如下图: 笔者采用的MCU是STM32F103... -
系统之家xp系统C语言程序闪退的解决方法
2021-05-19 11:55:52在xp系统中,很多使用VC++6.0编译C程序的用户们都经常会遇到C语言程序闪退的问题,在编译器中调试运行的时候一切正常,可将DEBUG中生成的EXE文件拿出来双击运行却发现程序运行完后就闪退了。怎么办?今天小编介绍系统... -
灵活的按键处理程序 FlexibleButton
2021-05-25 08:50:44前言正好工作中用到按键处理,需要处理单击、长按等按键事件,然后就造了这么一个轮子,为了以后更方便地加入其它的项目中使用,遂将其开源到 GitHub 中。后面发现 RT-Thread 软件包里也有一个开源的按键库 ... -
用C语言编写单片机流水灯程序
2021-05-20 06:55:24用C语言编写的单片机流水灯程序的软件和硬件,可以让八个LED轮流点亮,每个灯点亮和熄灭时间均为1秒。是利用单片机I/O口控制外部设备的简单例子。当然,在你掌握了本程序后,完全可以充分发挥你的想象,改变一下程序... -
C语言实现事件驱动型按键驱动模块MultiButton
2021-03-04 09:07:07在嵌入式系统尤其是单片机系统中经常用到按键检测和处理,这里提供一个标准的驱动函数模块MultiButton,能够提供按下、弹起、单击、双击、连击、长按等按键事件。 MultiButton 是一个小巧简单易用的事件驱动型按键... -
xp系统C语言程序闪退的解决方法
2021-05-24 03:14:17当我们写完这个程序 编译完成后单击左上角的叹号运行 可以看到一切正常 按下任意按键后窗口才会消失。很容易就能搞定了,下面就给大家讲解一下C语言程序闪退的快速处理方法:1、我们以最经典的HELLOWOR... -
C语言程序设计上机指导书及答案
2021-05-19 11:53:54《C语言程序设计上机指导书及答案》由会员分享,可在线阅读,更多相关《C语言程序设计上机指导书及答案(36页珍藏版)》请在人人文库网上搜索。1、姓 名:学 号:专 业:日 期:指导原则:促进学生针对实际问题,用所... -
从业将近十年!手把手教你单片机程序框架(连载)
2021-05-19 12:03:43第九节:独立按键的双击按键触发。开场白:上一节讲了在定时中断函数里处理独立按键的扫描程序,这种结构的程序我用在了很多项目上。这一节教大家如何实现按键双击触发的功能,这种功能类似鼠标的双击。要教会大家一... -
双机通信(C语言、主机和从机共用程序)
2021-05-19 18:01:19/*发送和接收程序:即主机和从机可共用此程序程序效果:通过主机发送,从机接收在主机中通过记下按键按下的次数,主机中显示最后按下的六个数值,并发送给从机,从机也显示这六个数值单片机类型:stc89c52完整程序... -
基于51单片机的独立按键单击、双击,长按,多次按的项目工程
2020-07-28 10:56:25基于51单片机的独立按键单击、双击,长按,多次按的项目工程一、前言1、基于51单片机的独立按键单击、双击,长按,多次按的项目工程包括用Keil软件编写单片机C语言程序和用Proteus软件仿真单片机外围电路2、基于51... -
编了个C语言的键盘程序有点问题,请指点下!
2021-05-19 19:35:32编了个C语言的键盘程序有点问题,请指点下![复制链接]做了个机械手,想用键盘来控制抓,放物品,现在他显示字符时有点错,高手能帮我在keil里跑下,把我的这个错改下吗?谢谢了!原程序如下:(P2.0--P2.7 是段选,P1.0--P1.5是... -
C语言的基本框架的.doc
2021-05-21 08:15:41C语言的基本框架的第1章 C语言的基本框架 上机指导本节将提供4个实验的指导,通过本节内容的学习和实践,读者可以更好地了解C语言程序,并熟悉Turbo C 2.0集成环境。【实验1.1】 设计简单菜单界面。1.实验题目...