历史上的今天
今天是:2025年03月28日(星期五)
2019年03月28日 | stm32按键 长按 短按 函数
2019-03-28 来源:eefocus
在stm32工程中,长按和短按的代码书写, 调用的读取按键状态的底层函数。封装成的按键函数代码。下面是函数的头文件,和.c文件的代码。使用定时器来扫描按键。
#define KEY_ON 1
#define KEY_OFF 0
#define KEY_NULL 0
#define KEY_SHORT 1
#define KEY_LONG 10
#define SHORT_TIME 200
uint8_t Key_state(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
static uint8_t key_value = KEY_NULL;
static uint16_t longtime;
if( (longtime == 0) && (key_value != KEY_NULL)) //当按键状态为长按或者短按时,而longtime 不为零,则按键状态清零
{
key_value = KEY_NULL;
}
if ( time == 5 ) /* 5 * 1 ms = 5ms 定时时间到 */
{
time = 0;
if(KEY_PRESS(GPIOx,GPIO_Pin)) //按键按下
{
longtime++;
}
else //按键松开
{
if((longtime >= 3) && (longtime <= SHORT_TIME)) //短按
{
key_value = KEY_SHORT;
}
else if( longtime > SHORT_TIME ) //长按
{
key_value = KEY_LONG;
}
else //去抖动
{
key_value = KEY_NULL;
}
longtime = 0; //清零
}
}
return key_value;
}
上面的代码,是按键松开才能判断按键的状态,是长按还是短按。在实际项目中我需要,按键按下一段时间后,判断为按键长按,不用松开,返回按键长按。参考网上的代码,使用状态机写了如下代码
#define KEY_PRESS(GPIOx,GPIO_Pin) GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)
#define KEY_INPUT KEY_PRESS(GPIOx,GPIO_Pin) //读取按键状态
#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 //长按的3秒时间
#define SINGLE_KEY_TIME 3 // 短按的消抖时间
#define N_KEY 0 // 无状态
#define S_KEY 1 // 单击
#define L_KEY 10 // 长按
函数的主体部分,代码中按下按键读取到高电平。
unsigned char key_driver(void)
{
static unsigned char key_state = 0; // 按键状态变量
static unsigned int key_time = 0; // 按键计时变量
unsigned char key_press, key_return;
key_return = N_KEY; // 清除 返回按键值
key_press = KEY_INPUT; // 读取当前键值
switch (key_state)
{
case KEY_STATE_0: // 按键状态0:判断有无按键按下
if (key_press == KEY_ON) // 有按键按下
{
key_time = 0; // 清零时间间隔计数
key_state = KEY_STATE_1; // 然后进入 按键状态1
}
break;
case KEY_STATE_1: // 按键状态1:软件消抖(确定按键是否有效,而不是误触)。按键有效的定义:按键持续按下超过设定的消抖时间。
if (key_press == KEY_ON)
{
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_OFF) // 如果按键在 设定的长按时间 内释放,则判定为单击
{
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_OFF)
{
key_state = KEY_STATE_0; // 按键释放后,进入 按键状态0 ,进行下一次按键的判定
}
break;
default: // 特殊情况:key_state是其他值得情况,清零key_state。这种情况一般出现在 没有初始化key_state,第一次执行这个函数的时候
key_state = KEY_STATE_0;
break;
}
return key_return; // 返回 按键值
}
unsigned char key_handle(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
unsigned char key_value;
if ( time == 10 ) /* 10 * 1 ms = 10ms 定时器 */
{
time = 0;
key_value = key_driver(GPIOx,GPIO_Pin);
}
return key_value;
}
在main.c中调用
int main(void)
{
int8_t key_value;
/* led 初始化*/
LED_GPIO_Config();
BASIC_TIM_Init();
Key_GPIO_Config();
while(1)
{
// key_value = Key_state(KEY1_GPIO_PORT,KEY1_GPIO_PIN);
key_value = key_handle(KEY1_GPIO_PORT,KEY1_GPIO_PIN);
if(key_value == KEY_SHORT)
{
LED1_TOGGLE;
}
else if(key_value == KEY_LONG)
{
LED2_TOGGLE;
}
}
}
这样可以实现长按不松手,执行长按的代码。以后遇到好的思想会继续学习,总结下来。
上一篇:STM32的按键部分
下一篇:关于STM32按键妙用详解
史海拾趣
|
摘要:文章综述了混合动力电动汽车的发展和基本结构,在此基础上,结合丰田汽车公司的最新一代混合动力电动汽车Prius THS Ⅱ,介绍了电力电子技术在混合动力电动汽车上的具体应用情况。最后,结合混合动力电动汽车的实际情况,提出了需要重点解决的 ...… 查看全部问答> |
|
非常奇怪的问题: 均使用socket编程 XP服务器和一台WinCE客户,没有问题。 两个WinCE客户的话,早Connect的机器就收不到Server的数据,但Server发送成功。客户端向服务器端发送的话,两台机器却都可以。… 查看全部问答> |
|
如题,在CP15 控制寄存器 c0中 31bit Asynchronous clock 30bit notFastBus select c0的高两位是什么意思,貌似在datasheet中没有找到说明啊??? 现在在调试MMU中遇到很奇怪的问题 在开启MMU后,我专门弄了一个对寄存器的赋值操作,来验证 ...… 查看全部问答> |
|
雅虎已经禁止员工远程办公,称远程办公妨碍合作,降低工作效率。 由于现在有多种电子沟通方式,远程办公能够节省成本;当公司预算紧张时,尤其如此。 然而,从心理学的角度来看,远程办公有很多潜在的缺点。 ...… 查看全部问答> |
|
Android系统和linux内核的关系详解 大家都知道Android是基于Linux内核的操作系统,也曾经和Linux基金会因为内核问题产生过分歧( 可以参考本文 后面的“参考阅读”)。这里主要对android和linux的关系进行分析,参 考http://www.itbenet.net/Ar ...… 查看全部问答> |
|
[LPC54102]详述FFT以及M4上使用DSP FFT库 本帖最后由 weizhongc 于 2015-4-28 01:28 编辑 前几天弄了个频谱显示,本来真的想送给女友的,然后花了好几个晚上做出来了,想想还是算了,好像没什么用。 &nbs ...… 查看全部问答> |
|
采用UIP进行组播和广播时遇到两个问题,一是无法接收组播数据;二是广播数据大于18字节时无法接收 检查组播数据接收时发现EPKTCNT寄存器显示是有数据的,但是UIP_UDP_APPCALL里面uip_newdata()为零表示无数据;因此猜测是uip把数据包丢弃了; 顺 ...… 查看全部问答> |




