按键的硬件方式为独立按键方法,原理图如下:
上图使用了两个按键,测试平台为:STM8S003,IAR环境
底层代码:
#include "fy_key.h"
void Key_Configuration(void){
GPIO_Init(GPIOD,GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT); //KEY1
GPIO_Init(GPIOD,GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT); //KEY2
}
//只读取初次按键电平状态,在状态机中进一步处理
static u8 Key_ReadPin(void){
if(READ_KEY1)
return KEY1_PRES;
if(READ_KEY2)
return KEY2_PRES;
return KEY_NONE;
}
//返回不同按键的单击、长按、长按保持、长按抬起、无键5种状态
//此函数10ms调用一次
//状态机方式
u8 Key_Scan(void){
static u8 cnt = 0;
static u8 state = 0; //按键初始化状态
static u8 key_value_last=0;//上一次的键值
u8 key_value=0;//本次的键值
u8 key_return=0;
key_value = Key_ReadPin();//读按键值
switch(state){
case 0:{
if(key_value != key_value_last)
state = 1; //有按键按下
}
break;
case 1:{
if(key_value == key_value_last)
state = 2; //消斗之后按键有效
else
state = 0; //认为误触
}
break;
case 2:{ //消斗之后
if(key_value == key_value_last) { //还是按下的状态
state = 3;
}
else{//松开了,短按
state = 0;
key_return = key_value_last|KEY_SHORT; //返回键值短按
}
}
break;
case 3:{ //判断长按短按
if(key_value == key_value_last){
if(++cnt > 150){ //1500ms
cnt = 190;
state = 4;
key_return = key_value_last|KEY_LONG; //返回键值长按
}
}
else{
cnt = 0;
state = 0;
key_return = key_value_last|KEY_SHORT; //返回键值短按
}
}
break;
case 4:{//长按松手检测
if(key_value != key_value_last){ //松开了
cnt = 0;
state = 0;
key_return = key_value_last|KEY_LONG_UP; //返回键值保持
}
else if(++cnt>=200){
cnt = 190;//100ms出发一次
key_return = key_value_last|KEY_HOLD; //返回键值保持
}
}break;
}//switch
key_value_last = key_value; //更新
return key_return;
}
//返回不同按键的单击、双击、三击、长按、保持、长按抬起、无键7种状态
//此函数10ms调用一次
u8 Key_Read(void)
{
static u8 sta = 0;
static u8 cnt = 0;
static u8 key_value_last = KEY_NONE;
u8 key_return = KEY_NONE;
u8 key_value;
key_value = Key_Scan();
switch(sta) {
case 0:{
if(key_value & KEY_SHORT){
key_value_last = key_value; //保存键值
cnt = 0; //第一次单击,不返回,到下个状态判断是否会出现双击
sta = 1;
}
else
key_return = key_value; //对于无键、长按,返回原事件
}
break;
case 1:{
if((key_value & KEY_SHORT) && (key_value == key_value_last)) { //又一次单击,时间间隔小于500ms
key_value_last = key_value; //保存键值
sta = 2;
cnt = 0;//重新计时
}
else if(++cnt >= 50){ //第一次单击后超过500ms 视为单击
key_return = key_value_last; //500ms内没有再次出现单击事件,返回单击事件
sta = 0; //返回初始状态
}
}
break;
case 2:{
if((key_value & KEY_SHORT) && (key_value == key_value_last)){ //再一次单击,时间间隔小于500ms
key_return = (key_value & ~KEY_SHORT) | KEY_THREE; //返回三击事件,回到初始状态
sta = 0;
}
else if(++cnt >= 50){ 第二次单击后超过500ms 视为双击
key_return = (key_value_last & ~KEY_SHORT) | KEY_DOUBLE;
sta = 0; //返回初始状态
}
}
break;
}//switch
return key_return;
}
/*********************************************END OF FILE**********************************************/
|