当前位置: 首页 > news >正文

网站做qq链接代码推广代运营公司

网站做qq链接代码,推广代运营公司,免费图片尺寸在线修改,个人或主题网站建设实验体会常见的按键判定程序,如正点原子按键例程,只能判定单击事件,对于双击、长按等的判定逻辑较复杂,且使用main函数循环扫描的方式,容易被阻塞,或按键扫描函数会阻塞其他程序的执行。使用定时器设计状态机可以规…

常见的按键判定程序,如正点原子按键例程,只能判定单击事件,对于双击、长按等的判定逻辑较复杂,且使用main函数循环扫描的方式,容易被阻塞,或按键扫描函数会阻塞其他程序的执行。使用定时器设计状态机可以规避这一问题。

本文在博主 老子姓李! 程序的基础上添加连按功能,整合双击功能并补充双击二次按下消抖,添加可调消抖时间,扩展为多按键,修改在定时器运行状态机,在主函数判断,并尽可能多的添加注释方便阅读。。
参考博主文章【源码详解-按键状态机-简洁易懂】1.单个按键实现短按长按的功能(基于STM32)

功能介绍

本程序功能:
使用定时器状态机实现按键单击、双击、长按、连按功能。消抖时间可调,长按时间可调,双击判定时间可调,连按单击间隔可调。无延时不阻塞,稳定触发。移植只需修改读IO函数,结构体初始化和宏定义时间参数即可。

注:

  1. 在定时器状态机判定产生事件标志,在主函数处理并清除事件标志。
  2. 单击、长按、双击事件为抬起时触发。
  3. 使能双击会稍微滞后单击事件的判定,可以选择是否使能双击判定。
  4. 可选择是否使能长按判定。
  5. 连按功能是指长按一定时间不松后,间隔较短时间多次触发快速单击事件,松开后结束。“快速单击”为单独事件,不与单击、长按事件冲突。

代码

头文件 my_key.h

#ifndef ___MY_KEY_H__
#define ___MY_KEY_H__#define KEY_DEBOUNCE_TIME 10      //消抖时间
#define KEY_LONG_PRESS_TIME 500   //长按判定时间
#define KEY_QUICK_CLICK_TIME 100  //连按时间间隔
#define KEY_DOUBLE_CLICK_TIME 200 //双击判定时间#define KEY_PRESSED_LEVEL 0 //按键被按下时的电平
#define TOTAL_KEYS 5        //物理按键数量//按键事件
typedef enum
{KEY_Event_Null,        //空事件KEY_Event_SingleClick, //单击KEY_Event_LongPress,   //长按KEY_Event_QuickClick,  //连击KEY_Event_DoubleClick, //双击
} KEY_EventList_TypeDef;//按键动作
typedef enum
{KEY_Action_Press,   //按住KEY_Action_Release, //松开
} KEY_Action_TypeDef;//按键状态
typedef enum
{KEY_Status_Idle,             //空闲KEY_Status_Debounce,         //消抖KEY_Status_ConfirmPress,     //确认按下KEY_Status_ConfirmPressLong, //确认长按KEY_Status_WaitSecondPress,  //等待再次按下KEY_Status_SecondDebounce,   //再次消抖KEY_Status_SecondPress,      //再次按下
} KEY_StatusList_TypeDef;// 按键引脚的电平
typedef enum
{KKEY_PinLevel_Low,KEY_PinLevel_High,KEY_PinLevel_Unknow,
} KEY_PinLevel_TypeDef;//按键配置
typedef struct
{uint8_t KEY_Label;                 //按键标号uint16_t KEY_Count;                //按键按下计时KEY_Action_TypeDef KEY_Action;     //按键动作,按下或释放KEY_StatusList_TypeDef KEY_Status; //按键状态KEY_EventList_TypeDef KEY_Event;   //按键事件
} KEY_Configure_TypeDef;extern KEY_Configure_TypeDef KeyConfig[TOTAL_KEYS];
extern KEY_EventList_TypeDef key_event[TOTAL_KEYS];
extern uint8_t double_click_mode;
extern uint8_t long_press_mode;void KEY_ReadStateMachine(KEY_Configure_TypeDef *KeyCfg);#endif

源文件 my_key.c

#include "my_key.h"//单独封装函数方便移植
static KEY_PinLevel_TypeDef KEY_ReadPin(uint8_t key_label)
{switch (key_label){case 1:return (KEY_PinLevel_TypeDef)HAL_GPIO_ReadPin(K1_GPIO_Port, K1_Pin);case 2:return (KEY_PinLevel_TypeDef)HAL_GPIO_ReadPin(K2_GPIO_Port, K2_Pin);case 3:return (KEY_PinLevel_TypeDef)HAL_GPIO_ReadPin(K3_GPIO_Port, K3_Pin);case 4:return (KEY_PinLevel_TypeDef)HAL_GPIO_ReadPin(K4_GPIO_Port, K4_Pin);case 5:return (KEY_PinLevel_TypeDef)HAL_GPIO_ReadPin(K5_GPIO_Port, K5_Pin);// case X://   return (KEY_PinLevel_TypeDef)HAL_GPIO_ReadPin(KX_GPIO_Port, KX_Pin);}return KEY_PinLevel_Unknow;
}KEY_Configure_TypeDef KeyConfig[TOTAL_KEYS] = {{1, 0, KEY_Action_Release, KEY_Status_Idle, KEY_Event_Null},{2, 0, KEY_Action_Release, KEY_Status_Idle, KEY_Event_Null},{3, 0, KEY_Action_Release, KEY_Status_Idle, KEY_Event_Null},{4, 0, KEY_Action_Release, KEY_Status_Idle, KEY_Event_Null},{5, 0, KEY_Action_Release, KEY_Status_Idle, KEY_Event_Null},// {X, 0, KEY_Action_Release, KEY_Status_Idle, KEY_Event_Null},
};KEY_EventList_TypeDef key_event[TOTAL_KEYS] = {KEY_Event_Null};
uint8_t double_click_mode = 0; //双击模式
uint8_t long_press_mode = 1;   //长按模式
//按键状态处理
void KEY_ReadStateMachine(KEY_Configure_TypeDef *KeyCfg)
{//按键动作读取if (KEY_ReadPin(KeyCfg->KEY_Label) == KEY_PRESSED_LEVEL){KeyCfg->KEY_Action = KEY_Action_Press;}else{KeyCfg->KEY_Action = KEY_Action_Release;}//状态机switch (KeyCfg->KEY_Status){//状态:空闲case KEY_Status_Idle:if (KeyCfg->KEY_Action == KEY_Action_Press) //动作:按下{KeyCfg->KEY_Status = KEY_Status_Debounce; //状态->消抖KeyCfg->KEY_Event = KEY_Event_Null;       //事件->无}else //动作:默认动作,释放{KeyCfg->KEY_Status = KEY_Status_Idle; //状态->空闲KeyCfg->KEY_Event = KEY_Event_Null;   //事件->无}break;//状态:消抖case KEY_Status_Debounce:if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count >= KEY_DEBOUNCE_TIME)) //动作:消抖时间已到,保持按下{KeyCfg->KEY_Count = 0;                        //计数清零KeyCfg->KEY_Status = KEY_Status_ConfirmPress; //状态->确认按下KeyCfg->KEY_Event = KEY_Event_Null;           //事件->无}else if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count < KEY_DEBOUNCE_TIME)) //动作:时间未到,保持按下{KeyCfg->KEY_Count++;                      //消抖计数KeyCfg->KEY_Status = KEY_Status_Debounce; //状态->维持KeyCfg->KEY_Event = KEY_Event_Null;       //事件->无}else //动作:消抖时间未到,释放,判定为抖动{KeyCfg->KEY_Count = 0;                //计数清零KeyCfg->KEY_Status = KEY_Status_Idle; //状态->空闲KeyCfg->KEY_Event = KEY_Event_Null;   //事件->无}break;//状态:确认按下case KEY_Status_ConfirmPress:if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count >= KEY_LONG_PRESS_TIME)) //动作:长按时间已到,保持按下{KeyCfg->KEY_Count = KEY_QUICK_CLICK_TIME;         //计数置数,生成第一次连按事件KeyCfg->KEY_Status = KEY_Status_ConfirmPressLong; //状态->确认长按KeyCfg->KEY_Event = KEY_Event_Null;               //事件->无}else if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count < KEY_LONG_PRESS_TIME)) //动作:时间未到,保持按下{KeyCfg->KEY_Count++;                          //长按计数KeyCfg->KEY_Status = KEY_Status_ConfirmPress; //状态->维持KeyCfg->KEY_Event = KEY_Event_Null;           //事件->无}else //动作:长按时间未到,释放{if (double_click_mode) //双击模式{KeyCfg->KEY_Count = 0;                           //计数清零KeyCfg->KEY_Status = KEY_Status_WaitSecondPress; //状态->等待再按KeyCfg->KEY_Event = KEY_Event_Null;              //事件->无}else{KeyCfg->KEY_Count = 0;                     //计数清零KeyCfg->KEY_Status = KEY_Status_Idle;      //状态->空闲KeyCfg->KEY_Event = KEY_Event_SingleClick; //事件->单击****}}break;//状态:确认长按case KEY_Status_ConfirmPressLong:if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count >= KEY_QUICK_CLICK_TIME)) //动作:连按时间已到,保持按下{KeyCfg->KEY_Count = 0;                            //计数清零KeyCfg->KEY_Status = KEY_Status_ConfirmPressLong; //状态->维持KeyCfg->KEY_Event = KEY_Event_QuickClick;         //事件->连按****}else if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count < KEY_QUICK_CLICK_TIME)) //动作:时间未到,保持按下{KeyCfg->KEY_Count++;                              //连按计数KeyCfg->KEY_Status = KEY_Status_ConfirmPressLong; //状态->维持KeyCfg->KEY_Event = KEY_Event_Null;               //事件->无}else //动作:长按下后释放{if (long_press_mode) //长按模式{KeyCfg->KEY_Count = 0;                   //计数清零KeyCfg->KEY_Status = KEY_Status_Idle;    //状态->空闲KeyCfg->KEY_Event = KEY_Event_LongPress; //事件->长按****}else //非长按模式{KeyCfg->KEY_Count = 0;                     //计数清零KeyCfg->KEY_Status = KEY_Status_Idle;      //状态->空闲KeyCfg->KEY_Event = KEY_Event_SingleClick; //事件->单击****}}break;//状态:等待是否再次按下case KEY_Status_WaitSecondPress:if ((KeyCfg->KEY_Action != KEY_Action_Press) && (KeyCfg->KEY_Count >= KEY_DOUBLE_CLICK_TIME)) //动作:双击等待时间已到,保持释放{KeyCfg->KEY_Count = 0;                     //计数清零KeyCfg->KEY_Status = KEY_Status_Idle;      //状态->空闲KeyCfg->KEY_Event = KEY_Event_SingleClick; //事件->单击****}else if ((KeyCfg->KEY_Action != KEY_Action_Press) && (KeyCfg->KEY_Count < KEY_DOUBLE_CLICK_TIME)) //动作:时间未到,保持释放{KeyCfg->KEY_Count++;                             //双击等待计数KeyCfg->KEY_Status = KEY_Status_WaitSecondPress; //状态->维持KeyCfg->KEY_Event = KEY_Event_Null;              //事件->无}else //动作:双击等待时间内,再次按下{KeyCfg->KEY_Count = 0;                          //计数清零KeyCfg->KEY_Status = KEY_Status_SecondDebounce; //状态->再次消抖KeyCfg->KEY_Event = KEY_Event_Null;             //事件->无}break;//状态:再次消抖case KEY_Status_SecondDebounce:if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count >= KEY_DEBOUNCE_TIME)) //动作:消抖时间已到,保持按下{KeyCfg->KEY_Count = 0;                       //计数清零KeyCfg->KEY_Status = KEY_Status_SecondPress; //状态->确认再次按下KeyCfg->KEY_Event = KEY_Event_Null;          //事件->无}else if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count < KEY_DEBOUNCE_TIME)) //动作:时间未到,保持按下{KeyCfg->KEY_Count++;                            //消抖计数KeyCfg->KEY_Status = KEY_Status_SecondDebounce; //状态->维持KeyCfg->KEY_Event = KEY_Event_Null;             //事件->无}else //动作:消抖时间未到,释放,判定为抖动{KeyCfg->KEY_Count = 0;                //计数清零KeyCfg->KEY_Status = KEY_Status_Idle; //状态->空闲KeyCfg->KEY_Event = KEY_Event_Null;   //事件->无}break;//状态:再次按下case KEY_Status_SecondPress:if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count >= KEY_LONG_PRESS_TIME)) //动作:长按时间已到,保持按下{if (long_press_mode) //长按模式{KeyCfg->KEY_Count = 0;                            //计数清零KeyCfg->KEY_Status = KEY_Status_ConfirmPressLong; //状态->确认长按KeyCfg->KEY_Event = KEY_Event_SingleClick;        //事件->先响应单击}else //非长按模式{KeyCfg->KEY_Count = 0;                       //计数清零KeyCfg->KEY_Status = KEY_Status_SecondPress; //状态->维持KeyCfg->KEY_Event = KEY_Event_Null;          //事件->无}}else if ((KeyCfg->KEY_Action == KEY_Action_Press) && (KeyCfg->KEY_Count < KEY_LONG_PRESS_TIME)) //动作:长按时间未到,保持按下{KeyCfg->KEY_Count++;                         //计数KeyCfg->KEY_Status = KEY_Status_SecondPress; //状态->维持KeyCfg->KEY_Event = KEY_Event_Null;          //事件->无}else //动作:按下后释放{KeyCfg->KEY_Count = 0;                     //计数清零KeyCfg->KEY_Status = KEY_Status_Idle;      //状态->空闲KeyCfg->KEY_Event = KEY_Event_DoubleClick; //事件->双击}break;}if (KeyCfg->KEY_Event != KEY_Event_Null) //事件记录key_event[KeyCfg->KEY_Label] = KeyCfg->KEY_Event;
}

定时器中断和主函数调用
中断周期为1ms

uint32_t tim_cnt = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim->Instance == htim1.Instance){tim_cnt++;if (tim_cnt % 1 == 0) // 1ms{KEY_ReadStateMachine(&KeyConfig[KEY_1]);KEY_ReadStateMachine(&KeyConfig[KEY_2]);KEY_ReadStateMachine(&KeyConfig[KEY_3]);KEY_ReadStateMachine(&KeyConfig[KEY_4]);KEY_ReadStateMachine(&KeyConfig[KEY_5]);}}
}//调用
int main(void)
{long_press_mode = 1;	 //使能长按模式double_click_mode = 1; //使能双击模式while (1){if (key_event[KEY_1] == KEY_Event_SingleClick) //单击{something1();}if (key_event[KEY_2] == KEY_Event_LongPress) //长按{something2();}if ((key_event[KEY_3] == KEY_Event_QuickClick) || (key_event[KEY_3] == KEY_Event_SingleClick)) //连按{something3();}if (key_event[KEY_4] == KEY_Event_DoubleClick) //双击{something4();}memset(key_event, KEY_Event_Null, sizeof(key_event)); //清除事件}
}
http://www.dinnco.com/news/58484.html

相关文章:

  • 那些网站可以做兼职百度广告上的商家可靠吗
  • p2p网站建设方案策划书seo内容优化方法
  • 做盗版网站 国外服务器吗seo课程总结怎么写
  • 欧米茄手表价格及图片官方网站百度怎么搜索图片
  • 找建设网站公司哪家好网络网站推广
  • 海城网站建设星巴克seo网络推广
  • 公司的网站如何进行修改布局百度seo排名优化软件化
  • 修改wordpress代码加快打开速度西安网站建设方案优化
  • 如何手机创建网站新闻10条摘抄大全
  • 视频网站建设费用百度平台商家
  • 网站备案 途径教育培训学校
  • 苏州网址云seo
  • 3g医院网站模板在百度做广告多少钱
  • 网站怎么做下载功能如何推销自己的产品
  • 想要将网站信息插到文本链接怎么做软文街官方网站
  • 中国建造师官方网站查询百度门店推广
  • 网站刚做好怎么做优化重庆seo整站优化外包服务
  • 男女做那个是的视频网站seo云优化是什么意思
  • 国务院 政府网站建设的意见谈谈你对seo概念的理解
  • 商城网站怎么做推广方案seo助力网站转化率提升
  • 宣城市建设银行网站seo站长工具查询
  • wordpress更改域名 后台八宿县网站seo优化排名
  • 网站后端怎么做企业网络营销策略分析
  • 上传文件网站根目录热门关键词查询
  • cms开发是什么意思拼多多关键词怎么优化
  • 上海网站制作公司河南省郑州市金水区
  • 校园微网站建设方案ppt模板谷歌浏览器网页版
  • 网页设计草图大学生品牌seo培训
  • WordPress文章资讯主题做网络优化哪家公司比较好
  • phpcms可以做网站吗百度如何快速收录网站