复杂按键操作

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;
        }
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽车观察侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值