STM32独立按键之长按、短按
内容如题:
1. 独立按键(软件消抖)
芯片引脚初始化为上拉输入
#define KEY_L_STATE LL_GPIO_IsInputPinSet(KEY_L_PORT, KEY_L_PIN)
#define KEY_R_STATE LL_GPIO_IsInputPinSet(KEY_R_PORT, KEY_R_PIN)
#define KEY_ENTER_STATE LL_GPIO_IsInputPinSet(KEY_ENTER_PORT, KEY_ENTER_PIN)
uint8_t Key_Scan(void)
{
static uint8_t Up_Flag=1;
if((Up_Flag)&&((KEY_L_STATE==0)||(KEY_R_STATE==0)||(KEY_ENTER_STATE==0)))//在按键抬起的状态下有按键按下
{
LL_mDelay(50);//消抖
Up_Flag=0;//标记有按键已经按下,只有等待再次抬起才能触发
if(KEY_L_STATE==0)return 1;
else if(KEY_R_STATE==0)return 2;
else if(KEY_ENTER_STATE==0)return 3;
}
else if((KEY_L_STATE==1)&&(KEY_R_STATE==1)&&(KEY_ENTER_STATE==1))
Up_Flag=1;//只有当所有按键都是默认状态,再置位按键抬起标志
return 0;
}
int main(void)
{
key=Key_Scan();
if(key==1)
{
//...
}
else if(key==2)
{
//....
}
}
2. 按键长按、短按:
首先初始化一个TIM作为长按时间的计数器
void MX_TIM4_Init(void)
{
LL_TIM_InitTypeDef TIM_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);
/* TIM4 interrupt Init */
NVIC_SetPriority(TIM4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),2, 0));
NVIC_EnableIRQ(TIM4_IRQn);
TIM_InitStruct.Prescaler = 3600;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 1000;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM4, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM4);
LL_TIM_SetClockSource(TIM4, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM4, LL_TIM_TRGO_UPDATE);
LL_TIM_DisableMasterSlaveMode(TIM4);
}
定义一个结构体,把按键引脚定义为上拉输入
typedef struct{
uint8_t Key_Press; //按键按下标志
uint8_t L1_S_Flag; //Key1短按标志
uint8_t L1_L_Flag; //Key1长按标志
uint8_t L1_C_Flag; //Key1点击标志
uint8_t L2_S_Flag; //Key2短按标志
uint8_t L2_L_Flag; //Key2长按标志
uint8_t L2_C_Flag; //Key2点击标志
uint8_t L12_L_Flag; //Key1和2长按标志
uint8_t KeyUp_Flag; //判断点击事件时按键松开标志
}Key_State;
在TIM4中断中处理按键的长按、短按
void TIM4_IRQHandler(void)
{
/* USER CODE BEGIN TIM4_IRQn 0 */
if(LL_TIM_IsActiveFlag_UPDATE(TIM4)) //5ms进入中断一次
{
LL_TIM_ClearFlag_UPDATE(TIM4); //清除更新中断
/*****************************KEY1长短按处理*****************************************/
if(LL_GPIO_IsInputPinSet(GPIOE, KEY1_Pin)==0) //按键按下
{
Press_Times1++;
printf("Press_Times1-->%d\r\n",Press_Times1);
}
else //松开按键
{
if((Press_Times1>1)&&(Press_Times1<20)) //按键按下时长 5ms<t<100ms
{
KeyState.L2_S_Flag=1; //标记为短按
KeyState.L2_L_Flag=0;
}
else if(Press_Times1>20) //按键按下时长超过100ms
{
KeyState.L2_S_Flag=0; //标记为长按
KeyState.L2_L_Flag=1;
if(KeyState.L1_L_Flag)
{
KeyState.L12_L_Flag=1;
KeyState.L1_L_Flag=0;
KeyState.L2_L_Flag=0;
}
}
else
{
KeyState.L2_S_Flag=0; //忽略
KeyState.L2_L_Flag=0;
}
Press_Times1=0; //清空计数
}
/*****************************KEY0长短按处理*****************************************/
if(LL_GPIO_IsInputPinSet(GPIOE, KEY0_Pin)==0) //按键按下
{
Press_Times0++;
printf("Press_Times0-->%d\r\n",Press_Times0);
}
else //松开按键
{
if((Press_Times0>1)&&(Press_Times0<20)) //按键按下时长 5ms<t<100ms
{
KeyState.L1_S_Flag=1; //标记为短按
KeyState.L1_L_Flag=0;
}
else if(Press_Times0>20) //按键按下时长超过100ms
{
KeyState.L1_S_Flag=0; //标记为长按
KeyState.L1_L_Flag=1;
if(KeyState.L2_L_Flag)
{
KeyState.L12_L_Flag=1;
KeyState.L1_L_Flag=0;
KeyState.L2_L_Flag=0;
}
}
else
{
KeyState.L1_S_Flag=0; //忽略
KeyState.L1_L_Flag=0;
}
Press_Times0=0; //清空计数
}
/****************************KEY1和KEY2同时长按**************************************/
}
/* USER CODE END TIM4_IRQn 0 */
/* USER CODE BEGIN TIM4_IRQn 1 */
/* USER CODE END TIM4_IRQn 1 */
}
使用:
while (1)
{
/* USER CODE END WHILE */
if(KeyState.L1_S_Flag)
{
printf("KEY2短按事件...\r\n");
KeyState.L1_S_Flag=0;
}
else if(KeyState.L1_L_Flag)
{
printf("KEY2长按事件...\r\n");
KeyState.L1_L_Flag=0;
}
//else if()。。。。。
}