基于标准库 PB1按键上升沿触发中断 用状态机读取按键长按短按状态值的程序
时间: 2023-07-29 12:06:02 浏览: 161
状态机查询按键的程序
以下是基于标准库的PB1按键上升沿触发中断,并通过状态机读取按键长按短按状态值的程序:
```c
#include "stm32f10x.h"
#define KEY_STATE_IDLE 0 // 按键空闲状态
#define KEY_STATE_PRESS 1 // 按键按下状态
#define KEY_STATE_RELEASE 2 // 按键释放状态
#define KEY_STATE_LONG 3 // 按键长按状态
#define KEY_LONG_TIME 500 // 按键长按时间阈值(单位:ms)
uint8_t KeyState = KEY_STATE_IDLE; // 按键状态
uint8_t LongPressFlag = 0; // 长按标志
uint32_t KeyPressTime = 0; // 按键按下时间
void EXTI1_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line1) != RESET) // 判断是否是PB1中断
{
EXTI_ClearITPendingBit(EXTI_Line1); // 清除中断标志位
if (KeyState == KEY_STATE_IDLE) // 如果按键处于空闲状态
{
KeyState = KEY_STATE_PRESS; // 切换到按键按下状态
KeyPressTime = HAL_GetTick(); // 记录按键按下时间
}
}
}
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
// 使能GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 配置PB1为输入引脚,上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 使能AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// 配置EXTI1中断线为中断模式,上升沿触发
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 使能EXTI1中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
while (1)
{
switch (KeyState)
{
case KEY_STATE_IDLE: // 按键空闲状态
LongPressFlag = 0; // 清除长按标志
break;
case KEY_STATE_PRESS: // 按键按下状态
if ((HAL_GetTick() - KeyPressTime) > KEY_LONG_TIME) // 如果按键按下时间超过阈值
{
KeyState = KEY_STATE_LONG; // 切换到按键长按状态
LongPressFlag = 1; // 设置长按标志
}
else
{
KeyState = KEY_STATE_RELEASE; // 切换到按键释放状态
}
break;
case KEY_STATE_RELEASE: // 按键释放状态
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == RESET) // 如果按键仍然被按下
{
KeyState = KEY_STATE_PRESS; // 切换回按键按下状态
KeyPressTime = HAL_GetTick(); // 更新按键按下时间
}
else
{
KeyState = KEY_STATE_IDLE; // 切换到按键空闲状态
}
break;
case KEY_STATE_LONG: // 按键长按状态
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == RESET) // 如果按键仍然被按下
{
LongPressFlag = 1; // 设置长按标志
}
else
{
KeyState = KEY_STATE_IDLE; // 切换到按键空闲状态
}
break;
default:
break;
}
if (LongPressFlag) // 如果按键被长按
{
// 执行长按功能
}
else if (KeyState == KEY_STATE_RELEASE) // 如果按键被短按
{
// 执行短按功能
}
}
}
```
在上述程序中,定义了四种按键状态:按键空闲状态、按键按下状态、按键释放状态和按键长按状态。在PB1中断处理函数中,如果按键处于空闲状态,则切换到按键按下状态,并记录按键按下时间。在状态机中,根据按键状态的不同,分别进行相应的处理。如果按键被长按,则设置长按标志;如果按键被松开,则读取按键状态并执行相应的功能。这里默认使用了HAL库函数进行时间计时,可以根据实际情况选择使用其他计时方式。
阅读全文