stm32稳定可靠的按键状态机,并注释代码
时间: 2023-07-10 15:09:32 浏览: 172
以下是一个基于状态机的 STM32 按键检测程序,能够实现稳定可靠的按键检测:
```c
/* 定义按键状态 */
typedef enum {
KEY_RELEASED = 0, // 按键松开状态
KEY_PRESSED, // 按键按下状态
KEY_WAITING, // 等待确认状态
KEY_CONFIRMED // 确认按键状态
} KEY_STATE;
/* 定义按键检测结构体 */
typedef struct {
GPIO_TypeDef* GPIOx; // 按键所在的 GPIO 端口
uint16_t GPIO_Pin; // 按键所在的 GPIO 引脚
KEY_STATE state; // 按键状态
uint16_t confirmCnt; // 确认计数器
} KEY_TypeDef;
/* 定义按键检测函数 */
void KEY_Detect(KEY_TypeDef* key)
{
/* 检测按键状态 */
switch (key->state) {
case KEY_RELEASED: // 松开状态
if (HAL_GPIO_ReadPin(key->GPIOx, key->GPIO_Pin) == GPIO_PIN_RESET) {
key->state = KEY_PRESSED; // 检测到按下,状态切换到按下状态
}
break;
case KEY_PRESSED: // 按下状态
if (HAL_GPIO_ReadPin(key->GPIOx, key->GPIO_Pin) == GPIO_PIN_SET) {
key->state = KEY_WAITING; // 检测到松开,状态切换到等待确认状态
key->confirmCnt = 0; // 确认计数器清零
}
break;
case KEY_WAITING: // 等待确认状态
if (HAL_GPIO_ReadPin(key->GPIOx, key->GPIO_Pin) == GPIO_PIN_RESET) {
if (++key->confirmCnt >= 10) { // 按键确认计数器达到 10,则认为按键已经确认
key->state = KEY_CONFIRMED; // 状态切换到确认状态
}
} else {
key->state = KEY_RELEASED; // 按键被松开,状态切换到松开状态
}
break;
case KEY_CONFIRMED: // 确认状态
if (HAL_GPIO_ReadPin(key->GPIOx, key->GPIO_Pin) == GPIO_PIN_SET) {
key->state = KEY_RELEASED; // 状态切换到松开状态
}
break;
default:
break;
}
}
```
使用方法:
1. 在主程序中定义按键结构体数组以及按键引脚、端口等信息:
```c
KEY_TypeDef key1 = {GPIOA, GPIO_PIN_0, KEY_RELEASED, 0};
KEY_TypeDef key2 = {GPIOA, GPIO_PIN_1, KEY_RELEASED, 0};
KEY_TypeDef key3 = {GPIOA, GPIO_PIN_2, KEY_RELEASED, 0};
KEY_TypeDef key4 = {GPIOA, GPIO_PIN_3, KEY_RELEASED, 0};
KEY_TypeDef keys[] = {key1, key2, key3, key4};
```
2. 在主程序的 while 循环中调用按键检测函数:
```c
while (1) {
/* 检测按键状态 */
for (int i = 0; i < sizeof(keys) / sizeof(KEY_TypeDef); i++) {
KEY_Detect(&keys[i]);
if (keys[i].state == KEY_CONFIRMED) {
/* 按键确认,执行相应操作 */
switch (i) {
case 0:
/* do something for key1 */
break;
case 1:
/* do something for key2 */
break;
case 2:
/* do something for key3 */
break;
case 3:
/* do something for key4 */
break;
default:
break;
}
}
}
}
```
注释说明:
1. 定义了一个枚举类型 `KEY_STATE` 表示按键状态,包括松开、按下、等待确认和确认状态。
2. 定义了一个结构体 `KEY_TypeDef` 表示按键,包括按键所在的 GPIO 端口、引脚号、状态以及确认计数器。
3. 在按键检测函数中,使用 switch-case 语句检测按键状态,根据不同的状态进行相应的操作。
4. 在主程序中定义按键结构体数组,并在 while 循环中循环调用按键检测函数,根据每个按键的确认状态执行相应的操作。
阅读全文