Crystalline 发表于 2024-11-2 09:36:26

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

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; // 按键数组

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

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

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

// 初始化第四个按键
btns.gpiox = GPIOA;
btns.pin = GPIO_PIN_0;
btns.level = 1;
btns.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 ^= 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 ^= 1; // 点亮对应的LED
      }
      else if(btn->repeat == 2)
      {
          ucLed ^= 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); // 处理每个按键的状态
}
}


DebugLab 发表于 2024-11-2 10:08:12

就是松开后才允许下一次按下触发,直接重写一个好了,消抖可以定期执行这个函数,用运行其他程序的时间消抖

VCC 发表于 2024-11-3 00:26:50

只有HAL_GPIO_ReadPin(btn->gpiox, btn->pin)这个函数不是不是STC32的,只要把这个改成合适的GPIO状态读取函数即可

其它代码都是通用的
页: [1]
查看完整版本: 怎么把这段状态机代码移植到stc32?