写一个4个按键的STM32标准库的C语言按键处理程序,要区分长按短按及连按
时间: 2024-02-24 15:56:11 浏览: 104
STM32单片机实现短按长按操作(按键状态机)
以下是一个4个按键的STM32标准库的C语言按键处理程序示例,使用按键消抖和计时器技术,区分长按短按及连按:
```c
#include "stm32f10x.h"
#include "delay.h"
#define BUTTON_UP_Pin GPIO_Pin_0
#define BUTTON_UP_GPIO_Port GPIOA
#define BUTTON_DOWN_Pin GPIO_Pin_1
#define BUTTON_DOWN_GPIO_Port GPIOA
#define BUTTON_LEFT_Pin GPIO_Pin_2
#define BUTTON_LEFT_GPIO_Port GPIOA
#define BUTTON_RIGHT_Pin GPIO_Pin_3
#define BUTTON_RIGHT_GPIO_Port GPIOA
#define LONG_PRESS_TIME 1000 // 长按时间阈值,单位为毫秒
#define PRESS_INTERVAL_TIME 200 // 连按时间间隔阈值,单位为毫秒
volatile uint8_t button_up_state = 0; // 按键状态变量,初始为未按下
volatile uint8_t button_down_state = 0;
volatile uint8_t button_left_state = 0;
volatile uint8_t button_right_state = 0;
// 按键消抖函数
uint8_t debounce(uint8_t pin_state)
{
static uint16_t cnt = 0;
static uint8_t state = 0;
if (pin_state != state)
{
cnt = 0;
state = pin_state;
}
else
{
if (cnt < 10)
cnt++;
if (cnt == 10)
return state;
}
return 2; // 返回2表示未稳定状态
}
// 延时函数,用于精确计时
void delay_ms(uint16_t ms)
{
uint16_t i;
while (ms--)
{
i = 1000;
while (i--)
{
__nop(); // STM32嵌入式系统推荐使用的空指令
}
}
}
int main(void)
{
// 初始化GPIO口和按键消抖状态
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStruct.GPIO_Pin = BUTTON_UP_Pin | BUTTON_DOWN_Pin | BUTTON_LEFT_Pin | BUTTON_RIGHT_Pin;
GPIO_Init(GPIOA, &GPIO_InitStruct);
button_up_state = debounce(GPIO_ReadInputDataBit(BUTTON_UP_GPIO_Port, BUTTON_UP_Pin));
button_down_state = debounce(GPIO_ReadInputDataBit(BUTTON_DOWN_GPIO_Port, BUTTON_DOWN_Pin));
button_left_state = debounce(GPIO_ReadInputDataBit(BUTTON_LEFT_GPIO_Port, BUTTON_LEFT_Pin));
button_right_state = debounce(GPIO_ReadInputDataBit(BUTTON_RIGHT_GPIO_Port, BUTTON_RIGHT_Pin));
// 初始化计时器2
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitStruct.TIM_Prescaler = 7199; // 时钟预分频,使计数器频率为10kHz
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 999; // 计数器自动重载值
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
// 游戏主循环
while (1)
{
// 处理按键事件
uint8_t up_state = debounce(GPIO_ReadInputDataBit(BUTTON_UP_GPIO_Port, BUTTON_UP_Pin));
uint8_t down_state = debounce(GPIO_ReadInputDataBit(BUTTON_DOWN_GPIO_Port, BUTTON_DOWN_Pin));
uint8_t left_state = debounce(GPIO_ReadInputDataBit(BUTTON_LEFT_GPIO_Port, BUTTON_LEFT_Pin));
uint8_t right_state = debounce(GPIO_ReadInputDataBit(BUTTON_RIGHT_GPIO_Port, BUTTON_RIGHT_Pin));
if (up_state != 2 && up_state != button_up_state)
{
button_up_state = up_state;
if (button_up_state == 0)
{
printf("用户按下了上箭头键!\n");
}
}
if (down_state != 2 && down_state != button_down_state)
{
button_down_state = down_state;
if (button_down_state == 0)
{
printf("用户按下了下箭头键!\n");
}
}
if (left_state != 2 && left_state != button_left_state)
{
button_left_state = left_state;
if (button_left_state == 0)
{
printf("用户按下了左箭头键!\n");
}
}
if (right_state != 2 && right_state != button_right_state)
{
button_right_state = right_state;
if (button_right_state == 0)
{
printf("用户按下了右箭头键!\n");
}
}
// 稍作延时
delay_ms(20);
}
}
// 计时器2中断处理函数
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
static uint16_t cnt = 0;
static uint16_t press_duration = 0;
static uint16_t press_interval = 0;
if (button_up_state == 0 || button_down_state == 0 || button_left_state == 0 || button_right_state == 0)
{
cnt++;
press_duration++;
if (cnt == 500) // 每500ms输出一次长按时间
{
cnt = 0;
if (press_duration >= LONG_PRESS_TIME)
{
printf("用户长按了按键!\n");
}
press_duration = 0;
}
}
else
{
press_duration = 0;
if (press_interval < PRESS_INTERVAL_TIME)
press_interval++;
else
press_interval = 0;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
```
这个程序会初始化4个GPIO口和计时器2,并使用按键消抖和计时器技术,区分长按短按及连按。当用户按下其中一个按键时,程序会输出相应的提示信息。长按时间超过阈值时,程序会输出长按提示信息。连续按键时间间隔小于阈值时,程序会忽略后续按键事件。你可以在这个基础上进行修改和扩展,实现更复杂的按键处理功能。
阅读全文