多按键的状态机扫描

基于stm32的hal库实现

要增加按键只需要在GetKEY()中添加相应按键返回,头文件中增加相应宏定义

源文件

#include "key.h"




uint8_t GetKEY(void)
{
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2) == RESET)//读取相应IO口电平
    {
        return KEY1_DOWN;//按键0被按下
    }
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3) == RESET)
    {
        return KEY2_DOWN;//按键1被按下
    }
    if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) == RESET)
    {
        return KEY3_DOWN;//按键2被按下
    }
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2) == RESET)//读取相应IO口电平
    {
        return KEY1_DOWN;//按键0被按下
    }
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3) == RESET)
    {
        return KEY2_DOWN;//按键1被按下
    }
    if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) == RESET)
    {
        return KEY3_DOWN;//按键2被按下
    }
    return NO_KEY;
}
/****************************************************************************
* 名    称:uint8_t ReadKeyStatus(void)
* 功    能:按键状态函数
* 入口参数:无
* 出口参数:返回某个按键的状态
* 说    明:移植时候,这个函数不需要做任何修改
* 调用方法:无
****************************************************************************/
uint8_t ReadKeyStatus(void)
{
    static uint8_t KeyState = KEY_UP;//按键状态
    static uint8_t KeyPrev = NO_KEY; //上一次按键值
    static int TimeCount = 0;		 //按键按下计时
    uint8_t KeyPress = NO_KEY;		 //按键值
    uint8_t KeyReturn = KEY_UP;		 //返回按键状态

    KeyPress = GetKEY();//得到被按下的按键

    switch(KeyState)
    {
        //状态0:没有按键按下
    case KEY_UP:
        if(KeyPress != NO_KEY)//有按键按下
        {
            KeyState = KEY_SURE;//转入状态1
            KeyPrev = KeyPress;//记录按键值
        }
        break;
        //状态1:按键按下确认
    case KEY_SURE:
        if(KeyPress == KeyPrev)//确认和上次相同
        {
            KeyState = KEY_DOWN;//转入状态2
            TimeCount = 0;//计数器清零
        }
        else
        {
            KeyState = KEY_UP;//转入状态0
        }
        break;
        //状态2:按键按下
    case KEY_DOWN:
        if(KeyPress != KeyPrev)//按键释放,端口高电平
        {
            KeyState = KEY_UP;//转入状态0
            KeyReturn = KEY_DOWN | KeyPrev;//返回单次按下(或运算可以得到是哪个按键处于什么状态)
        }
        else if((KeyPress == KeyPrev) && (++TimeCount >= 50)) //超过50*10ms没有释放
        {
            KeyState = KEY_LONG;//转入状态3
            TimeCount = 0;//计数器清零
            KeyReturn = KEY_LONG | KeyPrev;//返回连续按下
        }
        break;
        //状态3:按键连续按下
    case KEY_LONG:
        if(KeyPress != KeyPrev)//按键释放,端口高电平
        {
            KeyState = KEY_UP;//转入状态0
            KeyReturn = KEY_UP;
        }
        else if((KeyPress == KeyPrev) && (++TimeCount >= 50)) //超过50*10ms没有释放
        {
            KeyReturn = KEY_LONG | KeyPrev;//返回连续按下
            TimeCount = 0;//计数器清零
        }
        else//在50*10ms内释放
        {
            KeyReturn = KEY_UP;
        }
        break;
    }

    return KeyReturn;
}

头文件

#ifndef _KEY_H
#define _KEY_H

#include "main.h"

#define NO_KEY			0x00
#define KEY1_DOWN		0x01
#define KEY2_DOWN		0x02
#define KEY3_DOWN		0x03
#define KEY4_DOWN		0x04
#define KEY5_DOWN		0x05
#define KEY6_DOWN		0x05

#define KEY_UP			0xA0
#define KEY_SURE		0xB0
#define KEY_DOWN		0xC0
#define KEY_LONG		0xD0

#define KEY1_ONE_DOWN	0xC1
#define KEY2_ONE_DOWN	0xC2
#define KEY3_ONE_DOWN	0xC3
#define KEY4_ONE_DOWN	0xC4
#define KEY5_ONE_DOWN	0xC5
#define KEY6_ONE_DOWN	0xC6

#define KEY1_LONG_DOWN	0xD1
#define KEY2_LONG_DOWN	0xD2
#define KEY3_LONG_DOWN	0xD3
#define KEY4_LONG_DOWN	0xD4
#define KEY5_LONG_DOWN	0xD5
#define KEY6_LONG_DOWN	0xD6


uint8_t GetKEY(void);
uint8_t ReadKeyStatus(void);



#endif

调用实例

if(ReadKeyStatus() == KEY1_ONE_DOWN)
{	
	//do something	
}

版权声明:本文为qq_39512995原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。