1、初始化IO口与按键
//按键初始化函数
void KEY_Init(void) //IO初始化
{
Key_Init KeyInit[KEY_NUM]=
{
{GPIO_Mode_IPU, GPIOB, GPIO_Pin_1, RCC_APB2Periph_GPIOB}, // 初始化旋转编码器SW-PB1
};
Creat_Key(KeyInit); // 调用按键初始化函数
}
static BitAction KEY_ReadPin(Key_Init Key) //按键读取函数
{
return (BitAction)GPIO_ReadInputDataBit(Key.GPIOx,Key.GPIO_Pin_x);
}
void Creat_Key(Key_Init* Init)
{
uint8_t i;
GPIO_InitTypeDef GPIO_InitStructure[KEY_NUM];
for(i = 0;i < KEY_NUM;i++)
{
Key_Buf[i].Key = Init[i]; // 按钮对象的初始化属性赋值
RCC_APB2PeriphClockCmd(Key_Buf[i].Key.RCC_APB2Periph_GPIOx, ENABLE);//使能相应时钟
GPIO_InitStructure[i].GPIO_Pin = Key_Buf[i].Key.GPIO_Pin_x; //设定引脚
GPIO_InitStructure[i].GPIO_Mode = Key_Buf[i].Key.GPIO_Mode; //设定模式
GPIO_Init(Key_Buf[i].Key.GPIOx, &GPIO_InitStructure[i]); //初始化引脚
// 初始化按钮对象的状态机属性
Key_Buf[i].Status.KEY_SHIELD = ENABLE;
Key_Buf[i].Status.KEY_COUNT = 0;
Key_Buf[i].Status.KEY_LEVEL = Bit_RESET;
if(Key_Buf[i].Key.GPIO_Mode == GPIO_Mode_IPU) // 根据模式进行赋值
Key_Buf[i].Status.KEY_DOWN_LEVEL = Bit_RESET;
else
Key_Buf[i].Status.KEY_DOWN_LEVEL = Bit_SET;
Key_Buf[i].Status.KEY_STATUS = KEY_NULL;
Key_Buf[i].Status.KEY_EVENT = KEY_NULL;
Key_Buf[i].Status.READ_PIN = KEY_ReadPin; //赋值按键读取函数
}
}
2、建立按键各类结构体
typedef struct // 构造按键初始化类
{
GPIOMode_TypeDef GPIO_Mode; // 初始化按键模式
GPIO_TypeDef* GPIOx; // 初始化按键口
uint16_t GPIO_Pin_x; // 初始化按键引脚好
uint32_t RCC_APB2Periph_GPIOx; // 初始化时钟
}Key_Init;
typedef struct _KEY_COMPONENTS // 状态机类
{
FunctionalState KEY_SHIELD; //按键屏蔽,DISABLE(0):屏蔽,ENABLE(1):不屏蔽
uint8_t KEY_COUNT; //按键长按计数
BitAction KEY_LEVEL; //最终按键状态,按下Bit_SET(1),抬起Bit_RESET(0)
BitAction KEY_DOWN_LEVEL; //按下时,按键IO实际的电平
KEY_STATUS_LIST KEY_STATUS; //按键状态
KEY_STATUS_LIST KEY_EVENT; //按键事件
BitAction (*READ_PIN)(Key_Init Key);//读IO电平函数
}KEY_COMPONENTS;
typedef struct // 按键类
{
Key_Init Key; // 继承初始化父类
KEY_COMPONENTS Status; // 继承状态机父类
}Key_Config;
typedef enum _KEY_STATUS_LIST // 按键状态
{
KEY_NULL = 0x00, // 无动作
KEY_SURE = 0x01, // 确认状态
KEY_UP = 0x02, // 按键抬起
KEY_DOWN = 0x03, // 按键按下
KEY_LONG = 0x04, // 长按
}KEY_STATUS_LIST;
typedef enum // 按键注册表
{
BM_SW,
KEY_NUM, // 必须要有的记录按钮数量,必须在最后
}KEY_LIST;
3、按键动作的判断
Key_Config Key_Buf[KEY_NUM]; // 创建按键数组
void ReadKeyStatus(void)
{
uint8_t i;
Get_Key_Level();
for(i = 0;i < KEY_NUM;i++)
{
switch(Key_Buf[i].Status.KEY_STATUS)
{
//状态0:没有按键按下
case KEY_NULL:
if(Key_Buf[i].Status.KEY_LEVEL == Bit_SET)//有按键按下
{
Key_Buf[i].Status.KEY_STATUS = KEY_SURE;//转入状态1
Key_Buf[i].Status.KEY_EVENT = KEY_NULL;//空事件
}
else
{
Key_Buf[i].Status.KEY_EVENT = KEY_NULL;//空事件
}
break;
//状态1:按键按下确认
case KEY_SURE:
if(Key_Buf[i].Status.KEY_LEVEL == Bit_SET)//确认和上次相同
{
Key_Buf[i].Status.KEY_STATUS = KEY_DOWN;//转入状态2
Key_Buf[i].Status.KEY_EVENT = KEY_DOWN;//按下事件
Key_Buf[i].Status.KEY_COUNT = 0;//计数器清零
}
else
{
Key_Buf[i].Status.KEY_STATUS = KEY_NULL;//转入状态0
Key_Buf[i].Status.KEY_EVENT = KEY_NULL;//空事件
}
break;
//状态2:按键按下
case KEY_DOWN:
if(Key_Buf[i].Status.KEY_LEVEL != Bit_SET)//按键释放,端口高电平
{
Key_Buf[i].Status.KEY_STATUS = KEY_NULL;//转入状态0
Key_Buf[i].Status.KEY_EVENT = KEY_UP;//松开事件
}
else if((Key_Buf[i].Status.KEY_LEVEL == Bit_SET)
&& (++Key_Buf[i].Status.KEY_COUNT >= KEY_LONG_DOWN_DELAY)) //超过KEY_LONG_DOWN_DELAY没有释放
{
Key_Buf[i].Status.KEY_STATUS = KEY_LONG;//转入状态3
Key_Buf[i].Status.KEY_EVENT = KEY_LONG;//长按事件
Key_Buf[i].Status.KEY_COUNT = 0;//计数器清零
}
else
{
Key_Buf[i].Status.KEY_EVENT = KEY_NULL;//空事件
}
break;
//状态3:按键连续按下
case KEY_LONG:
if(Key_Buf[i].Status.KEY_LEVEL != Bit_SET)//按键释放,端口高电平
{
Key_Buf[i].Status.KEY_STATUS = KEY_NULL;//转入状态0
Key_Buf[i].Status.KEY_EVENT = KEY_UP;//松开事件
}
else if((Key_Buf[i].Status.KEY_LEVEL == Bit_SET)
&& (++Key_Buf[i].Status.KEY_COUNT >= KEY_LONG_DOWN_DELAY)) //超过KEY_LONG_DOWN_DELAY没有释放
{
Key_Buf[i].Status.KEY_EVENT = KEY_LONG;//长按事件
Key_Buf[i].Status.KEY_COUNT = 0;//计数器清零
}
else
{
Key_Buf[i].Status.KEY_EVENT = KEY_NULL;//空事件
}
break;
default:
break;
}
}
}