蓝桥杯知识点杂乱小结

 指针的基本了解 

枚举+结构体+定时器完成状态机用于按键检测以及消抖

 我们仔细看这上面的宏定义代码,是不是很麻烦,所以c语言就有了一个新的概念,枚举,枚举可以达成和下面一样的效果

在默认情况下第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。我们在这个实例中把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。不过可以强行修改值

         当然关于枚举的定义我们有下面两种方式

// 按键状态枚举
//typedef 是 C 语言中的关键字,用于为已有的数据类型定义一个新的名称(别名)
typedef enum {
    KEY_STATE_IDLE,     // 空闲(未按下)
    KEY_STATE_DEBOUNCE, // 消抖检测中
    KEY_STATE_PRESSED,  // 已确认按下
    KEY_STATE_RELEASE   // 等待释放
} KeyState;

// 单个按键的数据结构
typedef struct {
    GPIO_TypeDef *GPIOx;   // GPIO端口(如 GPIOB)
    uint16_t GPIO_Pin;     // 引脚号(如 GPIO_PIN_0)
    KeyState state;        // 当前状态
    uint8_t is_pressed;    // 按键是否被按下(供外部读取)
    uint32_t press_time;   // 按下时间(用于长按检测)
} Key;

// 定义所有按键(假设4个按键)
Key keys[] = {
    {GPIOB, GPIO_PIN_0, KEY_STATE_IDLE, 0, 0}, // KEY1
    {GPIOB, GPIO_PIN_1, KEY_STATE_IDLE, 0, 0}, // KEY2
    {GPIOB, GPIO_PIN_2, KEY_STATE_IDLE, 0, 0}, // KEY3
    {GPIOA, GPIO_PIN_0, KEY_STATE_IDLE, 0, 0}  // KEY4
};

了解了枚举我们就可以写以上代码,这样我们就有了新的框架,下面是使用方法

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM3) {
        for (int i = 0; i < 4; i++) {
            Key *key = &keys[i];
            uint8_t current_level = HAL_GPIO_ReadPin(key->GPIOx, key->GPIO_Pin);

            switch (key->state) {
                //---------------- 空闲状态 -------------------
                case KEY_STATE_IDLE:
                    if (current_level == GPIO_PIN_RESET) {  // 检测到低电平(可能按下)
                        key->state = KEY_STATE_DEBOUNCE;    // 进入消抖检测
                    }
                    break;

                //---------------- 消抖检测 -------------------
                case KEY_STATE_DEBOUNCE:
                    if (current_level == GPIO_PIN_RESET) {  // 持续低电平,确认按下
                        key->state = KEY_STATE_PRESSED;
                        key->is_pressed = 1;                // 标记按键已按下
                        key->press_time = HAL_GetTick();    // 记录按下时间戳
                    } else {                                // 电平恢复,视为抖动
                        key->state = KEY_STATE_IDLE;
                    }
                    break;

                //---------------- 已按下状态 -----------------
                case KEY_STATE_PRESSED:
                    if (current_level == GPIO_PIN_SET) {    // 检测到高电平(释放)
                        key->state = KEY_STATE_RELEASE;
                    } else {
                        // 此处可扩展长按检测(例如持续按下超过 2s)
                        // if (HAL_GetTick() - key->press_time > 2000) { ... }
                    }
                    break;

                //---------------- 释放检测 -------------------
                case KEY_STATE_RELEASE:
                    if (current_level == GPIO_PIN_SET) {    // 确认释放
                        key->state = KEY_STATE_IDLE;
                        key->is_pressed = 0;                // 清除按下标记
                    }
                    break;
            }
        }
    }
}

这种状态机的方法延时时间近似一个中断周期,若需要加时间,可以在最前面添加逻辑,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值