多个按键同时按住,会不会发生冲突。 |
单个按键组合好像有冲突 比如KYE1要长按实现退出功能 但长按动作前面肯定会经过短按(短按—长按—连击)这时短按就会被触发了 |
很管用的东西啊 |
感谢楼主![]() ![]() ![]() |
楼主有点东西 |
打卡学习,小白报道,感谢分享 |
学习学习![]() |
楼主大大,如果按键进水或者卡死了,导致所有程序运行错误。要如何屏蔽掉这个卡死或者进水的按键呢? |
学习了,谢谢分享 |
不错不错 |
不错!!! |
/********************************************* 工程名:状态机按键处理 作者: *********************************************/ //#include <reg51.h> #include <STC15F2K60S2.H> typedef unsigned char uint8; typedef unsigned int uint16; #define KEY_VALUE_1 0x0e #define KEY_VALUE_2 0x0d #define KEY_VALUE_3 0x0b #define KEY_VALUE_4 0x07 #define KEY_NULL 0x0f //定义长按键的TICK数,以及连_发间隔的TICK数 #define KEY_LONG_PERIOD 100 #define KEY_CONTINUE_PERIOD 25 //定义按键返回值状态(按下,长按,连_发,释放) #define KEY_DOWN 0x80 #define KEY_LONG 0x40 #define KEY_CONTINUE 0x20 #define KEY_UP 0x10 //定义按键状态 #define KEY_STATE_INIT 0 #define KEY_STATE_WOBBLE 1 #define KEY_STATE_PRESS 2 #define KEY_STATE_LONG 3 #define KEY_STATE_CONTINUE 4 #define KEY_STATE_RELEASE 5 sbit io_key_1 = P1^1 ; sbit io_key_2 = P1^2 ; sbit io_key_3 = P1^3 ; sbit io_key_4 = P1^4 ; void Timer0_Init(); void KeyInit(void) { io_key_1 = 1 ; io_key_2 = 1 ; io_key_3 = 1 ; io_key_4 = 1; } static uint8 KeyScan(void) { if(io_key_1 == 0) return KEY_VALUE_1; if(io_key_2 == 0) return KEY_VALUE_2; if(io_key_3 == 0) return KEY_VALUE_3; if(io_key_4 == 0) return KEY_VALUE_4; return KEY_NULL ; } void GetKey(uint8 *pKeyValue) { static uint8 s_u8KeyState = KEY_STATE_INIT; static uint8 s_u8KeyTimeCount = 0 ; static uint8 s_u8LastKey = KEY_NULL ; //保存按键释放时候的键值 uint8 KeyTemp = KEY_NULL ; KeyTemp = KeyScan(); //获取键值 switch(s_u8KeyState) { case KEY_STATE_INIT : { if(KEY_NULL != (KeyTemp)) { s_u8KeyState = KEY_STATE_WOBBLE ; } } break ; case KEY_STATE_WOBBLE: //消抖 { s_u8KeyState = KEY_STATE_PRESS ; } break ; case KEY_STATE_PRESS : { if(KEY_NULL != (KeyTemp)) { s_u8LastKey = KeyTemp ; //保存键值,以便在释放按键状态返回键值 KeyTemp |= KEY_DOWN ; //按键按下 s_u8KeyState = KEY_STATE_LONG ; } else { s_u8KeyState = KEY_STATE_INIT ; } } break ; case KEY_STATE_LONG : { if(KEY_NULL != (KeyTemp)) { if(++s_u8KeyTimeCount > KEY_LONG_PERIOD) { s_u8KeyTimeCount = 0 ; KeyTemp |= KEY_LONG ; //长按键事件发生 s_u8KeyState = KEY_STATE_CONTINUE ; } } else { s_u8KeyState = KEY_STATE_RELEASE ; } } break ; case KEY_STATE_CONTINUE : { if(KEY_NULL != (KeyTemp)) { if(++s_u8KeyTimeCount > KEY_CONTINUE_PERIOD) { s_u8KeyTimeCount = 0 ; KeyTemp |= KEY_CONTINUE ; } } else { s_u8KeyState = KEY_STATE_RELEASE ; } } break ; case KEY_STATE_RELEASE : { s_u8LastKey |= KEY_UP ; KeyTemp = s_u8LastKey ; s_u8KeyState = KEY_STATE_INIT ; } break ; default : break ; } *pKeyValue = KeyTemp ; //返回键值 } uint8 KeyValue = KEY_NULL; void main(void) { uint8 temp = 0 ; Timer0_Init(); KeyInit() ; EA = 1 ; while(1) { //Timer0MainLoop() ; //KeyMainLoop(&KeyValue) ; } } void Timer0() interrupt 1 //定时器中断 { //16位自动重装模式,无需重赋初值 GetKey(&KeyValue); if(KeyValue == (KEY_VALUE_1|KEY_DOWN)) P0 = ~1 ; if(KeyValue == (KEY_VALUE_1 |KEY_LONG)) P0 = ~2 ; if(KeyValue == (KEY_VALUE_1 |KEY_CONTINUE)) { P0 ^= 0xf0;} if(KeyValue == (KEY_VALUE_1 |KEY_UP)) P0 = 0xa5 ; } void Timer0_Init() //定时器初始化 { AUXR &= 0x7F; //定时器时钟12T模式,10mS TMOD &= 0xF0; //设置定时器模式 TH0 = 0xDC; //设置定时初值 TL0 = 0x00; //设置定时初值 //TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 =1; EA = 1; } |
实际上应该定时10mS,在定时中断中执行void GetKey(uint8 *pKeyValue)函数吧, |
如果执行程序的时间小于消抖的时间那不是还是进入了case KEY_STATE_PRESS ????不需要设置消抖时间? |
这个看起来不是很理解,可以发一下楼主自己改过以后的源码吗? |
汇编程序,怎么利用键值跳转到子程序呢? |
hboy 发表于 2015-12-10 11:30 把KeyMainLoop(&KeyValue) ;换成GetKey(&KeyValue);即可。 |
为嘛我用就编译不通过![]() |
真的很有用啊! |