一个按键,分为长按和短按的中间层。 #ifndef__KEY_H__ #define__KEY_H__ #include"../heard/include.h" structkey_struct { _UBYTEIO_ValueReadLase; _UBYTEIO_ValueReadNow; _UBYTEIO_ValueCnt; _UBYTEIO_ValueNow; _UBYTEIO_ValueLast; _UBYTEIO_Value; _UBYTEIO_ValueActionLast; _UBYTEIO_ValueActionNow; }; /***************************按键驱动相关********************************/ #defineKEY_COLUMN2_DirectionTRISCbits.TRISC1 #defineKEY_COLUMN2PORTCbits.RC1 #defineKEY_ROW2_DirectionTRISBbits.TRISB0 #defineKEY_ROW2PORTBbits.RB0 #defineKEY_IO_Init()do{ KEY_COLUMN2_Direction=OUTPUT_PIN; KEY_COLUMN2=0; TRISBbits.TRISB0=INPUT_PIN; }while(0) #defineKEY_IO_Value()(KEY_ROW2)//返回按键IO口值 /***************************配置相关***********************************/ #defineKEY_READ_TIMERS10//消抖次数 #defineKET_LongTimers200//长按时间=N*心跳时间 #defineKEY_NormalValue0x01//按键常态值 /***************************相关函数************************************/ voidKEY_Init(void);//初始化函数 voidKEY_ReadValue(void);//放到心跳定时器中 //按键状态 #defineKEY_InvalidState0 #defineKEY_ShortState1 #defineKEY_LongState2 _UBYTEKEY_ReturnState(void);//用户调用,返回按键状态 //清除按键状态,当用户调用KEY_ReturnState(), //执行完相应动作后,需要调用此函数清除按键状态, //否则,如果硬件驱动按键状态没有改变,则会重复执行。 voidKEY_ClearFlag(void); #endif #include"../heard/key.h" staticstructkey_structkey_value; static_UWORDKET_LongTimersCnt; voidKEY_Init(void) { KEY_IO_Init(); KET_LongTimersCnt=0; key_value.IO_ValueReadLase=KEY_NormalValue; key_value.IO_ValueReadNow=KEY_NormalValue; key_value.IO_ValueCnt=0; key_value.IO_ValueNow=KEY_NormalValue; key_value.IO_ValueLast=KEY_NormalValue; key_value.IO_Value=KEY_InvalidState; key_value.IO_ValueActionLast=KEY_InvalidState; key_value.IO_ValueActionNow=KEY_InvalidState; } voidKEY_ReadValue(void) { key_value.IO_ValueReadNow=KEY_IO_Value(); if(key_value.IO_ValueReadNow != key_value.IO_ValueReadLase) { key_value.IO_ValueReadLase=key_value.IO_ValueReadNow; key_value.IO_ValueCnt=0; return; } key_value.IO_ValueCnt++; if(key_value.IO_ValueCnt>=KEY_READ_TIMERS) { key_value.IO_ValueCnt=0; key_value.IO_ValueNow=key_value.IO_ValueReadNow; } if(key_value.IO_ValueNow != KEY_NormalValue) { if(KET_LongTimersCnt else { KET_LongTimersCnt=0; } if(KET_LongTimersCnt>=KET_LongTimers) { key_value.IO_Value=KEY_LongState; if(key_value.IO_Value != key_value.IO_ValueActionLast)//防止按键一直按着,重复判定按键状态 { key_value.IO_ValueActionLast=key_value.IO_Value; key_value.IO_ValueActionNow=key_value.IO_Value; } } else { if((key_value.IO_ValueLast!=KEY_NormalValue) && (key_value.IO_ValueNow==KEY_NormalValue)) { if(key_value.IO_Value!=KEY_LongState)//防止按键松开,误认为短按 { key_value.IO_Value=KEY_ShortState; if(key_value.IO_Value != key_value.IO_ValueActionLast)//防止按键一直按着,重复判定按键状态 { key_value.IO_ValueActionLast=key_value.IO_Value; key_value.IO_ValueActionNow=key_value.IO_Value; } } } else { if((key_value.IO_ValueLast==KEY_NormalValue) && (key_value.IO_ValueNow==KEY_NormalValue)) { key_value.IO_Value=KEY_InvalidState; if(key_value.IO_Value != key_value.IO_ValueActionLast)//防止按键一直按着,重复判定按键状态 { key_value.IO_ValueActionLast=key_value.IO_Value; if(!key_value.IO_ValueActionNow)//防止按键函数来不及动作,状态被清除 key_value.IO_ValueActionNow=key_value.IO_Value; } } } } key_value.IO_ValueLast = key_value.IO_ValueNow; } _UBYTEKEY_ReturnState(void) { returnkey_value.IO_ValueActionNow; } voidKEY_ClearFlag(void) { key_value.IO_ValueActionNow = KEY_InvalidState; } |
感谢分享~楼主分享的都很实用。 之前也写过一个按键的状态机,返回按下事件,松开事件,长按事件,短按事件等,可以配置按键个数,每个按键的防抖时间,长短按识别时间,电平定义,IO的操作留了操作函数接口。是公司的项目代码不便分享,我回头重写一个和大家一起讨论啊 |
好的,等发上来,通知我,一起讨论下。我发的程序,都是把驱动层函数接口留出来,不直接在中间层调用,一般都定义成宏函数,然后给应用层提供接口函数,屏蔽掉内部实现。 |
只有小组成员才能发言,加入小组>>
请问下图大疆lightbridge2遥控器主板电源芯片型号是什么?
4636 浏览 1 评论
使用常见的二极管、三极管和mos做MCU和模组的电平转换电路,但是模组和MCU无法正常通信,为什么?
522浏览 2评论
为了提高USIM卡电路的可靠性和稳定性,在电路设计中须注意的点有哪些?
542浏览 2评论
618浏览 2评论
569浏览 2评论
812浏览 2评论
电子发烧友网
电子发烧友开云(中国)官方