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

做外贸业务去哪些网站肥城市区seo关键词排名

做外贸业务去哪些网站,肥城市区seo关键词排名,徐州网站建设培训,app公司是做什么的常见的按键判定程序,如正点原子按键例程,只能判定单击事件,对于双击、长按等的判定逻辑较复杂,且使用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.hengruixuexiao.com/news/11054.html

相关文章:

  • 校园网站设计参考文献58同城如何发广告
  • 请问哪里可以做网站广告开户南京seo
  • 什么是市场营销什么是网络营销搜索引擎优化的主要工作有
  • 乐清建站公司烟台网络推广
  • wordpress搜图插件连云港网站seo
  • ps制作博客网站界面谷歌浏览器下载手机版app
  • 网站开发专业分析短视频代运营合作方案
  • 个人域名做邮箱网站汕头网站建设方案外包
  • 广州专业网站建设网页设计服务建网站需要哪些步骤
  • 做网站有什么软件吗seo查询优化
  • pcms网站开发怎么找平台推广自己的产品
  • wordpress博客软件搜索引擎优化宝典
  • 做网站之前要先购买服务器吗百度seo点击排名优化
  • 成都前几年网站建设公司网址大全是ie浏览器吗
  • 做视频解析网站违法不seo综合查询平台
  • 做兼职一般去哪个网站百度爱采购平台登录
  • 做网站做手机app要学什么软件今日头条军事新闻
  • 台州网站建设 网站制作 网站设计个人发布信息免费推广平台
  • 网站报名系统怎么做百度应用商店下载安装
  • 江苏苏州网站建设上海优化外包
  • 网页设计与网站建设实训目的培训网登录入口
  • 用discuz做的网站宁波seo外包推广排名
  • 微信公众号模板去哪找seo关键词快速排名前三位
  • 济南 网站制作抖音账号权重查询
  • 惠州网站建设 英语6线上营销推广方案模板
  • 个人网站可以备案做网络优化的公司排名
  • html5网页设计软件什么公司适合做seo优化
  • 室内设计效果图接单泽成seo网站排名
  • 写作网站签约都要上传身份证吗湛江百度网站快速排名
  • 外贸商城网站建设网站推广方案范文