*语言:C语言。
*开发板:国信长天STM32G431开发板。
*使用库函数:HAL库。
*按键引脚图如下:
*引脚配置如下:
*定时器配置如下:
*代码如下:(注释乱码了,复制时请使用ANSI)
/*¶¨Ê±Æ÷¼ÆʱɨÃè°´¼üµ¥»÷£¬Ë«»÷ºÍ³¤°´*/
/*
µ¥»÷£º1 , 2 , 3 , 4
Ë«»÷£º11 , 12 , 13 , 14
³¤°´£º21 , 22 , 23 , 24
*/
uint8_t counter ;
typedef struct KEYStruct
{
uint8_t Num ; //°´¼ü×îÖÕ·µ»ØÖµ
uint8_t NumSave ; //°´¼ü¶à»÷ʱ´¢´æÊý¾Ý
uint8_t Key_TimeCounter ; //°´¼ü³¤°´Ê±¼Æʱ
uint8_t W_TouchCounter_Flag ; //ÊÇ·ñ¿ªÆôË«»÷¼ä¸ô¼Æʱ
uint8_t W_Touch_TimeCounter ; //Ë«»÷¼ä¸ô¼Æʱ
} KEYStruct ;
KEYStruct KeyStruct ;
uint8_t Key_Num( void ) //ɨÃèËĸö°´¼üµÄ״̬
{
uint8_t KEYNUM = 0 ;
if( HAL_GPIO_ReadPin( GPIOB , GPIO_PIN_0 ) == RESET )
{
KEYNUM = 1 ;
}else
if( HAL_GPIO_ReadPin( GPIOB , GPIO_PIN_1 ) == RESET )
{
KEYNUM = 2 ;
}else
if( HAL_GPIO_ReadPin( GPIOB , GPIO_PIN_2 ) == RESET )
{
KEYNUM = 3 ;
}else
if( HAL_GPIO_ReadPin( GPIOA , GPIO_PIN_0 ) == RESET )
{
KEYNUM = 4 ;
}
return KEYNUM ;
}
void HAL_TIM_PeriodElapsedCallback( TIM_HandleTypeDef *htim )
{
static uint8_t Key_NowSta = 0 , Key_LastSta = 0 ;
if( htim->Instance == TIM3 )
{
counter ++ ;
counter %= 10 ;
if( counter == 0 ) //ÿ100ms¼ì²âÒ»´Î°´¼ü
{
Key_LastSta = Key_NowSta ;
Key_NowSta = Key_Num() ;
if( KeyStruct.W_TouchCounter_Flag == 1 && KeyStruct.W_Touch_TimeCounter < 200 )
{
KeyStruct.W_Touch_TimeCounter ++ ;
} //Ë«»÷¼Æʱ
if( Key_NowSta == Key_LastSta && Key_NowSta != 0 && KeyStruct.Key_TimeCounter < 200 )
{
KeyStruct.Key_TimeCounter ++ ;
} //³¤°´¼Æʱ
else
{
if( Key_NowSta == 0 && Key_LastSta != 0 ) //¼ì²âµ½°´¼ü±»°´ÏÂ
{
if( KeyStruct.Key_TimeCounter >= 15 )
{
KeyStruct.Num = Key_LastSta + 20 ;
}//ÅжÏÊÇ·ñ°´¼üÐÐΪÊdz¤°´
else
{
KeyStruct.W_TouchCounter_Flag = 1 ;
if( KeyStruct.W_Touch_TimeCounter <= 2 ) //Ë«»÷¼ä¸ôÐèҪСÓÚ3£¨300ms£©
{
if( KeyStruct.NumSave == 0 )
{
KeyStruct.NumSave = Key_LastSta ;
KeyStruct.W_Touch_TimeCounter = 0 ;
} //´¢´æÊ״ε¥»÷ʱµÄÊýÖµ
else
{
if( KeyStruct.NumSave == Key_LastSta )
{
KeyStruct.NumSave = KeyStruct.NumSave + 10 ;
} //ÈôÅжÏΪ˫»÷Ôò¸üд¢´æÊý¾Ý
}
}
}//ÅжÏÊÇ·ñ°´¼üÐÐΪÊÇË«»÷
KeyStruct.Key_TimeCounter = 0 ;
}
if( KeyStruct.W_TouchCounter_Flag == 1 && KeyStruct.W_Touch_TimeCounter >= 3 )
{
KeyStruct.Num = KeyStruct.NumSave ;
KeyStruct.W_TouchCounter_Flag = 0 ;
KeyStruct.W_Touch_TimeCounter = 0 ;
KeyStruct.NumSave = 0 ;
} //³¬¹ý¼ä¸ôʱ¼äÔòÖ±½Ó¼ÇΪµ¥»÷£¬ÈôË«»÷£¬Ôò½«¸üÐÂÊý¾ÝÔØÈëNum
}
}
}
}
调用时在主函数中extern KEYStruct KeyStruct,读取其中Num的值即可
总体思路就是:
在定时器中重复记录按键的返回值,如果此次的返回值为0而上一次的返回值不为0,则判断为按键已被按下并松手。
在定时器中重复记录按键的返回值,如果此次的返回值为0且上一次的返回值也为0,则判断为按键正在被长按,开启长按计时,等待松手时检测计时是否满足长按时长的要求。
在定时器中重复记录按键的返回值,如果检测到按键被按下并松手,则开启双击计时,当计时处于一定数值内时再次被按下,则判断为双击;若超时仍未有按键按下,则判断为单击。
4.第一次按键松开时,NumSave储存第一次按键值,若第二次按键值与之相同,则判断为双击,三击同理。
如有问题的不清楚请多多指教,下次尽量把代码注释补上。