|
大体是源于这位大侠的思想
【MultiButton】并发状态事件驱动按键驱动模块,量产产品实践
https://www.amobbs.com/thread-5658940-1-1.html
(出处: amobbs.com 阿莫电子论坛)
不过,改得有点面目全非了
1、不用再定义按键,想要直接注册一个就行(就一个注册函数SL_Regist),但也失去了同一个按键注册多个回调的可能,目前只能注册一个按键注册一个
本来想再改成一个按键可以注册成多个回调的,但要同时定义一个事件,不合算,如果要malloc,这货有问题,有时候明明有空间,就是返回一个负数。。不敢用。遂算了,凑合着用
2、可以同时支持查询方式(SL_GetEvent),支持长按,支持组合(100ms扫一次,两个按键同时按还是比较容易按得到,实测,当然,扫描时间越快就越难)
3、。。好吧,其实原装也可以有这些,我只是想用的时候就仅仅调用一个函数就可以,不要一堆。。
程序小白,欢迎拍砖。。。
底层驱动
- #ifndef __BSP_SLOW_KEY_H
- #define __BSP_SLOW_KEY_H
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "main.h"
-
- //According to your need to modify the constants.
- //#define _SL_CYCLE 5 //ms °´¼üɨÃèʱ¼ä
- #define SL_LONG_TICKS (2000 /_SL_CYCLE)
- typedef enum {
- idSL_UP = 0,
- idSL_LEFT,
- idSL_RIGHT,
- idSL_DOWN,
- idSL_ENTER,
- idSL_ESC,
- idSL_number_of_id,
- }idSL_n;
- //typedef enum {
- // SL_PRESS_DOWN = 0,
- // SL_LONG_PRESS_HOLD,
- // SL_PRESS_UP,
- // SL_number_of_event,
- // SL_NONE_PRESS
- //}SL_Event_n;
- #define SL_PRESS_DOWN 0x01
- #define SL_LONG_PRESS_HOLD 0x02
- #define SL_PRESS_UP 0x04
- #define SL_number_of_event 3
- #define SL_NONE_PRESS 0x00
- typedef void (*SL_Callback)(void*);
- typedef struct _SL {
- uint8_t id;
- uint8_t event;
- uint16_t contCnt;
- uint8_t trg;
- uint8_t cont;
- SL_Callback cb[SL_number_of_event];
- struct _SL* next;
- }SL_t;
- void SL_Init(void);
- void SL_Scan(void);
- int SL_Regist(uint8_t id,uint8_t event,SL_Callback cb);
- uint8_t SL_GetEvent(uint8_t id);
- #ifdef __cplusplus
- }
- #endif
-
- #endif //__BSP_FAST_KEY_H
复制代码
- #include "main.h"
- static const uint8_t tabPORT[] = {0,0,0,0,0,0,}; //按顺序排列要打开的内部电阻Px口(P0 P1 P2 P3 P4 P5 P6 P7)
- static const uint8_t tabPIN[] = {0,1,2,3,4,5,}; //按顺序排列输入引脚号(Px0 Px1 Px2 Px3 Px4 Px5 Px6 Px7)
-
- static SL_t mSL[idSL_number_of_id];
-
- void SL_Init(void)
- {
- uint8_t i;
- memset(mSL, 0, sizeof(mSL));
- for(i=0;i<idSL_number_of_id;i++){
- mSL[i].id = i;
- }
- }
-
- int SL_Regist(uint8_t id,uint8_t event,SL_Callback cb) //链表注册
- {
- if(id>=idSL_number_of_id) return -1; //超出范围
- if(event&SL_PRESS_DOWN) mSL[id].cb[0] = cb;
- if(event&SL_LONG_PRESS_HOLD) mSL[id].cb[1] = cb;
- if(event&SL_PRESS_UP) mSL[id].cb[2] = cb;
- return 0;
- }
- uint8_t SL_GetEvent(uint8_t id)
- {
- static uint8_t eve[idSL_number_of_id];
- if(eve[id]!=mSL[id].event || mSL[id].event==SL_LONG_PRESS_HOLD){ eve[id] = mSL[id].event;
- return eve[id];
- }
- return SL_NONE_PRESS;
- }
- #define EVENT_CB(ev) if(mSL[id].cb[ev])mSL[id].cb[ev]((SL_t*)(&mSL[id])) //回调函数
- void SL_Handler(int id)
- {
- uint8_t keyReadBit = 0xff;
- if(id>=sizeof(tabPIN)) return;
-
- switch(tabPORT[id]){
- case 0:{//P0
- keyReadBit = (P0&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- case 1:{//P1
- keyReadBit = (P1&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- case 2:{//P2
- keyReadBit = (P2&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- case 3:{//P3
- keyReadBit = (P3&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- case 4:{//P4
- keyReadBit = (P4&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- case 5:{//P5
- keyReadBit = (P5&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- case 6:{//P6
- keyReadBit = (P6&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- case 7:{//P7
- keyReadBit = (P7&(0x01<<tabPIN[id])) ^ (0x01<<tabPIN[id]);
- break;}
- default:break;
- }
- mSL[id].trg = keyReadBit & (keyReadBit ^ mSL[id].cont);
- mSL[id].cont = keyReadBit;
- if(mSL[id].trg>0){ //printf("mSL[%d].trg=1\n",id);
- mSL[id].event = (uint8_t)SL_PRESS_DOWN;
- EVENT_CB(0);
- }
- if(mSL[id].cont>0){
- if(mSL[id].contCnt==SL_LONG_TICKS){ //printf("mSL[%d].cont\n",id);
- mSL[id].contCnt++; //只触发一次,如果屏蔽此条就一直触发,做连续动作用,比如连加连减等操作.
- mSL[id].event = (uint8_t)SL_LONG_PRESS_HOLD;
- EVENT_CB(1);
- }
- else{
- mSL[id].contCnt++;
- }
- }
- else{
- if(mSL[id].contCnt>0) mSL[id].contCnt = 0;
- }
- if((mSL[id].trg==0)&&(mSL[id].cont==0)&&(mSL[id].event!=SL_PRESS_UP)){ //printf("mSL[%d].trg=0\n",id);
- mSL[id].event = SL_PRESS_UP;
- EVENT_CB(2);
- }
- }
- void SL_Scan(void)
- {
- int i;
- static uint32_t tick_SL = 0;
- if(Sys_GetTick()-tick_SL>=_SL_CYCLE){ tick_SL = Sys_GetTick();
- for(i=0; i<idSL_number_of_id; i++) {
- SL_Handler(i);
- }
- }
- }
复制代码
回调使用
- SL_Regist(idSL_UP,SL_PRESS_DOWN,cbFn_idSL_UP);
- SL_Regist(idSL_LEFT,SL_PRESS_DOWN|SL_PRESS_UP,cbFn_idSL_LEFT);
- SL_Regist(idSL_RIGHT,SL_PRESS_DOWN|SL_PRESS_UP,cbFn_idSL_RIGHT);
- SL_Regist(idSL_DOWN,SL_PRESS_DOWN|SL_PRESS_UP,cbFn_idSL_DOWN);
- SL_Regist(idSL_ENTER,SL_PRESS_DOWN|SL_PRESS_UP,cbFn_idSL_ENTER);
复制代码
查询方式
- static uint32_t tick = 0;
- if(SL_PRESS_DOWN==SL_GetEvent(idSL_UP)){
- num++;
- }else if(SL_PRESS_DOWN==SL_GetEvent(idSL_DOWN)){
- num--;
- }else if(SL_PRESS_DOWN==SL_GetEvent(idSL_ENTER)){
- return 1;
- }else if(SL_PRESS_DOWN==SL_GetEvent(idSL_ESC)){
- return 1;
- }else if(SL_LONG_PRESS_HOLD==SL_GetEvent(idSL_UP)){
- if(Sys_GetTick()-tick>=100){ tick = Sys_GetTick();
- num++;
- }
- }else if(SL_LONG_PRESS_HOLD==SL_GetEvent(idSL_DOWN)){
- if(Sys_GetTick()-tick>=100){ tick = Sys_GetTick();
- num--;
- }
- }
复制代码 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|