找回密码
 立即注册
查看: 254|回复: 2

怎么把这段状态机代码移植到stc32?

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:173
  • 最近打卡:2025-05-01 12:26:51
已绑定手机

17

主题

81

回帖

382

积分

中级会员

积分
382
发表于 2024-11-2 09:36:26 | 显示全部楼层 |阅读模式
typedef struct
{
  GPIO_TypeDef *gpiox;     // 指向 GPIO 端口的指针,例如 GPIOA、GPIOB 等。
  uint16_t pin;            // 指定 GPIO 引脚,例如 GPIO_PIN_0、GPIO_PIN_1 等。
  uint16_t ticks;          // 用于计时的变量,通常用于去抖动处理。
  uint8_t level;           // 当前按键的电平状态,高电平或低电平。
  uint8_t id;              // 按键的唯一标识符,可以用于区分不同的按键。
  uint8_t state;           // 按键的当前状态,可能用于表示按键是否被按下或释放。
  uint8_t debouce_cnt;     // 按键去抖动计数器,用于防止按键抖动引起的误触发。
  uint8_t repeat;          // 按键重复按下的次数。
} button;

button btns[4]; // 按键数组

// 按键初始化函数
void key_init(void)
{
  // 初始化第一个按键
  btns[0].gpiox = GPIOB;    // 指定GPIO端口
  btns[0].pin = GPIO_PIN_0; // 指定引脚
  btns[0].level = 1;        // 设置初始电平
  btns[0].id = 0;           // 设置按键ID

  // 初始化第二个按键
  btns[1].gpiox = GPIOB;
  btns[1].pin = GPIO_PIN_1;
  btns[1].level = 1;
  btns[1].id = 1;

  // 初始化第三个按键
  btns[2].gpiox = GPIOB;
  btns[2].pin = GPIO_PIN_2;
  btns[2].level = 1;
  btns[2].id = 2;

  // 初始化第四个按键
  btns[3].gpiox = GPIOA;
  btns[3].pin = GPIO_PIN_0;
  btns[3].level = 1;
  btns[3].id = 3;
}

// 按键任务处理函数
void key_task(button *btn)
{
  // 读取按键当前电平
  uint8_t gpio_level = HAL_GPIO_ReadPin(btn->gpiox, btn->pin);

  // 如果按键状态大于 0,则递增计时器
  if (btn->state > 0)
    btn->ticks++;

  // 如果当前电平与按键记录的电平不同,进行去抖动处理
  if (btn->level != gpio_level)
  {
    // 计数达到 3 次,确认电平变化
    if (++(btn->debouce_cnt) >= 3)
    {
      btn->level = gpio_level; // 更新电平
      btn->debouce_cnt = 0;    // 重置去抖动计数器
    }
  }
  else
  {
    btn->debouce_cnt = 0; // 电平没有变化,重置去抖动计数器
  }

  // 按键状态机
  switch (btn->state)
  {
    case 0:                // 初始状态
      if (btn->level == 0) // 等待按键按下
      {
        btn->ticks = 0;           // 重置计时器
        btn->repeat = 1;          // 初始按键重复计数
        btn->state = 1;           // 进入按键按下状态
      }
      break;
    case 1:                // 按键按下状态
      if (btn->level != 0) // 等待按键松开
      {
        if (btn->ticks >= 30) // 按键长按
        {
          ucLed[btn->id] ^= 1; // 执行长按后的操作
          btn->state = 0;        // 返回初始状态
        }
        else
        {
          btn->ticks = 0; // 重置计时器
          btn->state = 2; // 进入按键释放状态
        }
      }
      else if (btn->ticks >= 30) // 按键长按
      {

        btn->repeat = 0; // 防止释放的时候再次触发单击事件
      }
      break;
    case 2:                 // 按键释放状态
      if (btn->ticks >= 15) // 计时器达到阈值
      {
        btn->state = 0; // 返回初始状态
        if(btn->repeat == 1)
        {
          ucLed[btn->id+4] ^= 1; // 点亮对应的LED
        }
        else if(btn->repeat == 2)
        {
          ucLed[btn->id] ^= 1; // 点亮对应的LED
        }
      }
      else
      {
        if (btn->level == 0) // 按键再次按下
        {
          btn->repeat++;  // 递增重复计数
          btn->ticks = 0; // 重置计时器
          btn->state = 1; // 返回按键按下状态
        }
      }
      break;
    }
}



// 按键状态处理函数
void key_state(void)
{
  for (uint8_t i = 0; i < 4; i++) // 遍历所有按键
  {
    key_task(&btns[i]); // 处理每个按键的状态
  }
}


回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-11-2 10:08:12 | 显示全部楼层
就是松开后才允许下一次按下触发,直接重写一个好了,消抖可以定期执行这个函数,用运行其他程序的时间消抖
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:123
  • 最近打卡:2025-04-19 16:12:35
已绑定手机

60

主题

777

回帖

4001

积分

论坛元老

自定义头衔

积分
4001
发表于 2024-11-3 00:26:50 | 显示全部楼层
只有HAL_GPIO_ReadPin(btn->gpiox, btn->pin)这个函数不是不是STC32的,只要把这个改成合适的GPIO状态读取函数即可

其它代码都是通用的
联系我请点击左下角的【回复】按钮,否则我收不到消息提
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 13:10 , Processed in 0.152839 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表