IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 一款轻量级支持短按、长按、双击等功能的按键例程 -> 正文阅读

[嵌入式]一款轻量级支持短按、长按、双击等功能的按键例程

这个例程来源于杰理的SDK,只做了部分修改,方便移植到各个项目里面,具有短按、短按抬起、长按、长按抬起、连按、多击功能。

#ifndef _KEY_H
#define _KEY_H
#include "sys.h"

#define KEY0        HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3)  //KEY0按键PH3
#define KEY1        HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2)  //KEY1按键PH2
#define KEY2        HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) //KEY2按键PC13
#define WK_UP       HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)  //WKUP按键PA0

#define NO_KEY                  	0xff //无按键//

/*双击允许间隔时间*/
#define KEY_DOUBLE_CLICK_MAX_CNT    35  //25*10ms//
#define KEY_DOUBLE_CLICK_MIN_CNT    5   //5*10ms//


 /*按键门槛值*/
#define KEY_BASE_CNT            4   //消抖时间//
#define KEY_LONG_CNT        	50  //长按时间//
#define KEY_HOLD_CNT            50  //连按时间//
#define KEY_SHORT_CNT           7   //短按时间//

/*按键状态*/
#define KEY_SHORT_UP            0x1
#define KEY_LONG                0x2
#define KEY_HOLD                0x3
#define KEY_DOUBLE_CLICK        0x4
#define KEY_THREE_CLICK         0x5
#define	KEY_LONG_UP				0X6
#define	KEY_SHORT				0X7


extern volatile u8 g_cur_key_num;
extern volatile u8 g_cur_key_status;

void KEY_Init(void);//IO初始化
u8 Get_Key_Value(void);
void Key_Event_Handle(uint8_t key_status, uint8_t key_num);
void Key_Scan(void);
#endif

#include "key.h"

volatile u8 g_cur_key_num;
volatile u8 g_cur_key_status;

//按键初始化函数
void KEY_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();           //开启GPIOC时钟
    __HAL_RCC_GPIOH_CLK_ENABLE();           //开启GPIOH时钟
    
    GPIO_Initure.Pin=GPIO_PIN_0;            //PA0
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLDOWN;        //下拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
    
    GPIO_Initure.Pin=GPIO_PIN_13;           //PC13
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);
    
    GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3
    HAL_GPIO_Init(GPIOH,&GPIO_Initure);
}

u8 Get_Key_Value(void)
{
	u8 key_num = NO_KEY;
	
	if (KEY0) {
		key_num = 1;
	}
	else if (KEY1)
	{
		key_num = 2;
	}
	else if (KEY2)
	{
		key_num = 3;
	}
	else if (WK_UP)
	{
		key_num = 4;
	}

	return key_num;
}


void Key_Event_Handle(uint8_t key_status, uint8_t key_num)
{
	g_cur_key_status = key_status;
	g_cur_key_num = key_num;
}

void Key_Scan(void)
{
	uint8_t key_status = 0, cur_key = NO_KEY, back_last_key = 0;
	static uint8_t s_filter_value = NO_KEY, s_filter_cnt = 0;
	static uint8_t s_last_key = NO_KEY, s_click_delay_cnt = 0, s_click_cnt = 0,s_notify_value = NO_KEY;
	static uint16_t s_press_cnt = 0;

	//清零按键值及其状态
	g_cur_key_status = 0;
	g_cur_key_num = NO_KEY;

	cur_key = Get_Key_Value(); //获取按键值//

    //消抖/
	if (cur_key != s_filter_value && s_filter_cnt) { //当前按键与上一次按键不同//
		s_filter_cnt = 0;
		s_filter_value = cur_key;
		return;
	}
	if (s_filter_cnt < KEY_BASE_CNT) {
		s_filter_cnt++;
		return;
	}

	if (cur_key != s_last_key) {
		if (cur_key == NO_KEY) { //按键被抬起  s_last_key != NO_KEY//

			if (s_press_cnt >= KEY_LONG_CNT) {
				key_status = KEY_LONG_UP;
				back_last_key = s_last_key;
				goto notify;
			}
			s_click_delay_cnt = 1; //按键等待下次连击开始//
		}
		else { //按键被按下 s_last_key = NO_KEY//
			s_press_cnt = 1;
			if (cur_key != s_notify_value) { //当前单击/连击与上次按键值不等//
				s_notify_value = cur_key;
				s_click_cnt = 1;
			}
			else {
				s_click_cnt++; //连击次数累加
			}
		}
		goto scan_end;
	}
	else {
		if (cur_key == NO_KEY) { //没有按键按下//
			if (s_click_cnt > 0) {

				if (s_click_delay_cnt >= KEY_DOUBLE_CLICK_MAX_CNT) { //按键抬起,判断单击/连击次数
					s_click_delay_cnt = 0;
					switch (s_click_cnt) {
						case 1: //单击//
							key_status = KEY_SHORT_UP;
							break;
						case 2: //双击//
							key_status = KEY_DOUBLE_CLICK;
							break;
						case 3: //三击//
							key_status = KEY_THREE_CLICK;
							break;
						default:
							break;
					}
					back_last_key = s_notify_value;
					goto notify;
				} else {
					s_click_delay_cnt++;
					goto scan_end;  //按键抬起延时时间未到,返回
				}
			} else {
				goto scan_end;  //没有按键需要处理
			}
		}
		else { //长按,连按//
			s_press_cnt++;

			if (s_press_cnt == KEY_LONG_CNT) { //长按//
				key_status = KEY_LONG;
			}
			else if (s_press_cnt == (KEY_LONG_CNT+KEY_HOLD_CNT)) {  //连按//
				key_status = KEY_HOLD;
				s_press_cnt = KEY_LONG_CNT;
			}
			else {
				goto scan_end;
			}
			back_last_key = cur_key;
			goto notify;
		}
	}

notify:

	s_notify_value = NO_KEY;
	s_click_cnt = 0;
	Key_Event_Handle(key_status, back_last_key);  //按键值及其状态转换
scan_end:

	s_last_key = cur_key;
}

这个例程不仅仅支持普通的IO按键,AD按键等其他类型的也都可以移植,只是获取按键值的函数不同罢了。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 00:15:52  更:2022-04-01 00:15:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:22:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码