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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 按键实现短按长按(按下多少秒触发)等功能 -> 正文阅读

[嵌入式]按键实现短按长按(按下多少秒触发)等功能

实现流程

1:定义了7个按键对象,并且给这7个按键分配的了对应的7个触发事件(同一个按键的单
击和长按都属于不同按键对象)
2:按下按键->进入防抖->判断计数器返回的计数时间->根据时间来判断按键按下事件对应标志置1
3:process函数根据置 1 的事件,进入完成对应功能,把标志归 0 ,让按键的state = KEY_RESET或其他

.H

#ifndef  __KEY_H
#define  __KEY_H
#include "HAL_device.h" 
#include "HAL_conf.h"



typedef unsigned char 		uint8_t;
typedef unsigned short int 	uint16_t;
typedef unsigned int   		uint32_t;

#define  PIN_STATE(n)  GPIO_ReadInputDataBit(GPIOA, n)

enum key_state{  //定义按键状态
	UP	 = 0,
	DOWN = 1,
	KEY_RESET = 2,
	KEY_LONG_PRESS = 3,
	KEY_LOCK = 4
};

typedef struct event{  //按键需要触发的情况
	
	uint8_t set_click;  //当按键触发之后,就将此标志置1,代表此按键或者组合按键被触发
	uint8_t set_press_2s;
	uint8_t set_redc_press_3s;
	uint8_t set_redc_press_7s;
	uint8_t set_redc_click;
	uint8_t set_add_click;
	uint8_t freeze_clicked;
	uint8_t defrost_press_2s;
	uint8_t add_redc_press_3s;

}s_key_event;

typedef struct key_menber{  //按键对象类型
	uint16_t id;
	uint8_t state;
}s_key_m;

typedef struct key{  //按键的对象
	s_key_m key_1;
	s_key_m key_2;
	s_key_m key_3;
	s_key_m key_4;
	s_key_m key_23;
	s_key_m key_24;
	s_key_m key_34;
}s_key;


/******************************************/
void key_init(void);

void key_process(void);


#endif

#include  "key.h"
#include "counter_delay.h"
#include "stdio.h"

#define  ENTER_WAIT   60  //触发防抖延时
#define  BACK_WAIT    60  //退出防抖延时

#if 1
#define KEY_NUM  7  //定义按键数量
s_key key;  //按键结构体,存放所有按键
s_key_event 			key_event = {0}; //按键需要触发的事件

void key_state(void);

void key_init(void){	
	uint8_t i;
	s_key_m * ptr = NULL;
	ptr = (s_key_m *)&key;
	
	for(i = 0;i < KEY_NUM ;i++){  ///给按键分配Id
		(ptr+i)->id = (0xF1 + i);
		(ptr+i)->state = UP;
	}
	
}

void key_state(void){
//**************按键1	
	if( !PIN_STATE(GPIO_Pin_4)){
		//防抖延时
		if(key.key_1.state != KEY_RESET){
			if( timer_state(key.key_1.id) == TIMING_END){

				start_once_timer(DEFROST_PRESS_2S_ID , 8000, LOCK_TIMNG);
				key.key_1.state = DOWN;
			}
			else{
				start_timer(key.key_1.id,ENTER_WAIT,LOCK_TIMNG);
			}
		}
		if(key.key_1.state == DOWN){
			u32 count_value = timer_count_value(DEFROST_PRESS_2S_ID);
			if((count_value >= 2000)&&(count_value <= 8000)&&(show_state == Normal_show_state)){
				key_event.defrost_press_2s = 1;  //触发事件
				printf("按键2秒");
				BUZZER_ON(KEY_S);
				close_timer(DEFROST_PRESS_2S_ID, DESTROYED);
			}
		}
	}
	else{
		if(key.key_1.state == DOWN){ //松开按键,判断事件类型
			u32 counter = timer_count_value(DEFROST_PRESS_2S_ID);
			if(counter <= 500){
				key_event.freeze_clicked = 1; //触发事件
				BUZZER_ON(KEY_S)
				printf("制冷");
			}
			close_timer(DEFROST_PRESS_2S_ID,DESTROYED);
			key.key_1.state = UP;
		}

		key.key_1.state = UP;
		close_timer(key.key_1.id ,DESTROYED);  //挂起定时器
	}
//**************单点按键2
	if((!PIN_STATE(GPIO_Pin_5))&&(PIN_STATE(GPIO_Pin_6))&&(PIN_STATE(GPIO_Pin_7))){
		//设置防抖延时
		if(key.key_2.state != KEY_RESET){
			if( timer_state(key.key_2.id) == TIMING_END){ //进入事件计时
				start_once_timer(SET_KEY_EVENT_ID, 8000, LOCK_TIMNG);
				key.key_2.state = DOWN;
			}
			else{
				start_timer(key.key_2.id,ENTER_WAIT,LOCK_TIMNG);
			}
		}
		if(key.key_2.state == DOWN){
			u32 count_value = timer_count_value(SET_KEY_EVENT_ID);
			if((count_value >= 2000)&&(count_value <= 8000)&&(show_state == Normal_show_state)){
				key_event.set_press_2s = 1; //触发事件
				printf("仅设置键2S");
				BUZZER_ON(KEY_S)
				close_timer(SET_KEY_EVENT_ID, DESTROYED);
			}
		}
	}
	else{
		if((key.key_2.state == DOWN)&&(PIN_STATE(GPIO_Pin_6))&&(timer_state(BACK_PROTECT_TIME_ID) == DESTROYED)){ //松开按键,判断事件类型
			u32 count_value = timer_count_value(SET_KEY_EVENT_ID);
			if(count_value <= 500U){
				key_event.set_click = 1; //触发事件
				BUZZER_ON(KEY_S);
				printf("单击设置键");
			}
			close_timer(SET_KEY_EVENT_ID, DESTROYED);
		}
		key.key_2.state = UP;
		close_timer(key.key_2.id ,DESTROYED);  //挂起定时器
	}
#if 1
/****************/
	if( (!PIN_STATE(GPIO_Pin_5))&&(!PIN_STATE(GPIO_Pin_6))&&(PIN_STATE(GPIO_Pin_7))){
		//设置 (-) 防抖延时
		if(key.key_23.state != KEY_RESET){
			if( timer_state(key.key_23.id) == TIMING_END){ //进入事件计时
					start_once_timer(SET_REDC_PRESS_7S, 15000 , LOCK_TIMNG);
					key.key_23.state = DOWN;
			}
			else{
				start_timer(key.key_23.id,ENTER_WAIT,LOCK_TIMNG);
			}
		}
		if(key.key_23.state == DOWN){
			u32 counter = timer_count_value(SET_REDC_PRESS_7S);
			if((counter >= 3000)&&(counter <= 7000)&&(show_state == Normal_show_state)){
				key_event.set_redc_press_3s = 1; //触发事件
				printf("SET- 3");
				BUZZER_ON(KEY_S);
				close_timer(SET_REDC_PRESS_7S,DESTROYED);
			}
			else if((counter >= 7000)&&(show_state == Menu_show_state)){
				key_event.set_redc_press_7s = 1; //触发事件
				printf("SET- 7");
				BUZZER_ON(KEY_S);
				close_timer(SET_REDC_PRESS_7S,DESTROYED);
			}
		}
	}
	else{
		if(key.key_23.state == DOWN){ //松开按键,判断事件类型
			u32 counter = timer_count_value(SET_REDC_PRESS_7S);
			if(counter <= 500){
				key_event.set_redc_click = 1; //触发事件
				BUZZER_ON(KEY_S);
				printf("SET-");
			}
			close_timer(SET_REDC_PRESS_7S,DESTROYED);
			key.key_23.state = UP;
			start_once_timer(BACK_PROTECT_TIME_ID, 200, LOCK_TIMNG);
		}
		key.key_23.state = UP;
		close_timer(key.key_23.id ,DESTROYED);  //挂起定时器
	}
/****************/
	if( (!PIN_STATE(GPIO_Pin_5))&&(PIN_STATE(GPIO_Pin_6)&&(!PIN_STATE(GPIO_Pin_7)))){
		//设置 (+) 防抖延时
		if( timer_state(key.key_24.id) == TIMING_END){ //进入事件计时
				key.key_24.state = DOWN;
		}
		else{
			start_timer(key.key_24.id,ENTER_WAIT,LOCK_TIMNG);
		}
	}
	else{
		if(key.key_24.state == DOWN){ //松开按键,判断事件类型
				key_event.set_add_click = 1; //触发事件
				printf("SET+");
				BUZZER_ON(KEY_S);
				start_once_timer(BACK_PROTECT_TIME_ID, 200, LOCK_TIMNG);
		}
		key.key_24.state = UP;
		close_timer(key.key_24.id ,DESTROYED);  //挂起定时器
	}
#endif
//**************按键3	
	if( (!PIN_STATE(GPIO_Pin_6))&&(PIN_STATE(GPIO_Pin_5))){
		//减少防抖延时
		if((key.key_3.state != KEY_RESET)&&(key.key_3.state != KEY_LONG_PRESS)){
			if( timer_state(key.key_3.id) == TIMING_END){
				key.key_3.state = DOWN;
				BUZZER_ON(KEY_S);
				close_timer(key.key_3.id ,DESTROYED);  //挂起定时器
			}
			else{
				start_timer(key.key_3.id,ENTER_WAIT,LOCK_TIMNG);
			}
		}
		else if(key.key_3.state == KEY_RESET){
			if(timer_state(RDC_LONG_PRESS_ID) == TIMING_END){
				if((show_state == Set_show_state)||(show_state == Set_temp_show_state)){  //只有设置数值才支持长按
					key.key_3.state = KEY_LONG_PRESS;
				}
				close_timer(RDC_LONG_PRESS_ID,DESTROYED);
			}
			else{
				start_timer(RDC_LONG_PRESS_ID, 700, LOCK_TIMNG);
			}
		}
		else if(key.key_3.state == KEY_LONG_PRESS){
			delay_ms(90);
		}
	}
	else{
		key.key_3.state = UP;
		close_timer(RDC_LONG_PRESS_ID,DESTROYED);
		close_timer(key.key_3.id ,DESTROYED);  //挂起定时器
	}
//**************按键4	
	if( (!PIN_STATE(GPIO_Pin_7))&&(PIN_STATE(GPIO_Pin_5))){
		//增加防抖延时
		if((key.key_4.state != KEY_RESET)&&(key.key_4.state != KEY_LONG_PRESS)){
			if( timer_state(key.key_4.id) == TIMING_END){
				key.key_4.state = DOWN;
				BUZZER_ON(KEY_S);
				close_timer(key.key_4.id ,DESTROYED);  //销毁定时器
			}
			else{
				start_timer(key.key_4.id,ENTER_WAIT,LOCK_TIMNG);
			}
		}
		else if(key.key_4.state == KEY_RESET){
			if(timer_state(ADD_LONG_PRESS_ID) == TIMING_END){
				if((show_state == Set_show_state)||(show_state == Set_temp_show_state)){  //只有设置数值才支持长按
					key.key_4.state = KEY_LONG_PRESS;
				}
				close_timer(ADD_LONG_PRESS_ID,DESTROYED);
			}
			else{
				start_timer(ADD_LONG_PRESS_ID, 700, LOCK_TIMNG);
			}
		}
		else  if(key.key_4.state == KEY_LONG_PRESS){
			delay_ms(90);
		}
	}
	else{
		key.key_4.state = UP;
		close_timer(ADD_LONG_PRESS_ID,DESTROYED);
		close_timer(key.key_4.id ,DESTROYED);  //销毁定时器
	}
/******锁屏按键组合********/
	if((!PIN_STATE(GPIO_Pin_6))&&(!PIN_STATE(GPIO_Pin_7))&&(PIN_STATE(GPIO_Pin_5))){
		if(timer_state(key.key_34.id) == TIMING_END){
			start_once_timer(ADD_REDC_PRESS_ID,3400,LOCK_TIMNG);
			key.key_34.state = DOWN;
		}
		else{
			start_timer(key.key_34.id, ENTER_WAIT, LOCK_TIMNG);
		}
		if(key.key_34.state == DOWN){
			u32 count = timer_count_value(ADD_REDC_PRESS_ID);
			if(count >=3000){
				key_event.add_redc_press_3s = 1; //触发事件
				BUZZER_ON(KEY_S);
				close_timer(ADD_REDC_PRESS_ID, DESTROYED);
			}
		}
	}
	else{
		key.key_34.state = UP;
		close_timer(key.key_34.id, DESTROYED);
		close_timer(ADD_REDC_PRESS_ID, DESTROYED);
	}
}

void key_process(void){
	key_state(); //按键状态读取
	//进入按键任务
#if 1
	if((key.key_4.state == DOWN)||(key.key_4.state == KEY_LONG_PRESS)){  //支持数字长按连续切换的按键
		//printf("+键 ");
		/**功能代码区-BEGAIN-**/
		
		/**功能代码区-END-**/
		if(key.key_4.state != KEY_LONG_PRESS){
			key.key_4.state = KEY_RESET;
		}
		start_timer(key.key_4.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
	}
	if((key.key_3.state == DOWN)||(key.key_3.state == KEY_LONG_PRESS)){  //支持数字长按连续切换的按键
		//printf("-键 ");
		/**功能代码区-BEGAIN-**/
		
		/**功能代码区-END-**/
		if(key.key_3.state != KEY_LONG_PRESS){
			key.key_3.state = KEY_RESET;
		}
		start_timer(key.key_3.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
	}

	
#endif

	
#if 1

//设置按键------------------------------------------------------------------------/
	if(key_event.set_click){  //点击事件
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/

		key.key_2.state = KEY_RESET;//防止连续触发		
		key_event.set_click = 0;
		close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
	}
	if(key_event.set_press_2s){
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/

		key.key_2.state = KEY_RESET;//防止连续触发		
		key_event.set_press_2s = 0;
		close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
	}
	if(key_event.set_redc_press_3s){
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/

		key.key_23.state = KEY_RESET;
		key_event.set_redc_press_3s = 0;
		close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
	}
	if(key_event.set_redc_press_7s){
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/

		key.key_23.state = KEY_RESET;
		key_event.set_redc_press_7s = 0;
		close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
	}
	if(key_event.set_redc_click){
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/

		key.key_23.state = KEY_RESET;
		key_event.set_redc_click = 0;
		close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
	}
	if(key_event.set_add_click){
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/

		key.key_24.state = KEY_RESET;
		key_event.set_add_click = 0;
	}
/*---------------------------------------------------------*/	

#endif
	if(key_event.freeze_clicked == 1){
		//printf("制冷键 ");
		/**功能代码区-BEGAIN-**/
		
		/**功能代码区-END-**/
		key_event.freeze_clicked = 0;
		key.key_1.state = KEY_RESET;
		start_timer(key.key_1.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
	}
	if(key_event.defrost_press_2s == 1){
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/
		key_event.defrost_press_2s = 0;
		key.key_1.state = KEY_RESET;
		start_timer(key.key_1.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
	}
	if(key_event.add_redc_press_3s){
		/**功能代码区-BEGAIN-**/

		/**功能代码区-END-**/
		key_event.add_redc_press_3s = 0;
		key.key_34.state = KEY_RESET;
	}
}

#endif

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:36:52  更:2022-04-09 18:39:28 
 
开发: 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 4:25:34-

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