【问题标题】:How to code latch switch function using STM32?如何使用STM32编写锁存开关功能?
【发布时间】:2021-01-15 14:32:12
【问题描述】:

我正在寻找使用 STM32 获得锁存开关功能的代码。 我尝试过的以下代码在 stm32 中工作,但只有一个没有闩锁的按钮功能。

while (1)
{
      if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)== GPIO_PIN_RESET )
      {
          HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
      }
      else
      {
          HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);       
      }         
} 

有人可以帮我在第一次按下按钮时使 GPIOA、GPIO_PIN_5 引脚始终为高电平,而在第二次按下按钮时始终使 GPIOA、GPIO_PIN_5 引脚为低电平吗?

该功能将类似于下面的视频https://www.youtube.com/watch?v=zzWzSPdxA0U

提前谢谢大家。

【问题讨论】:

  • 如果您需要帮助,第一步:格式化代码。
  • 这里有几件事,请分享有问题的GPIO/s的初始化代码。如果我没有这些,我无法有效地给你一个好的答案。逻辑似乎是有道理的;但是,根据开关的不同,您需要进行一些去抖动以防止意外切换输出。您几乎不应该对这样的开关进行采样,并根据第一个示例做出合乎逻辑的决定。我也很好奇,这些引脚的硬件设置是什么?这将决定如何设计一个数字滤波器/去抖代码,以提供您想要的行为。
  • @JamesNovorita 尽管你说的一切都是正确的,但这段代码似乎更像是学习如何编程/使用电子产品的人,所以直接的样本和具体的并不重要。

标签: stm32 gpio


【解决方案1】:

代码有几个问题。没有记忆功能,您正在以最大速度阅读按钮。

通过睡眠一段时间以允许人类反应速度和按钮噪音来解决此问题。您还需要一个变量来存储之前的状态。

while (1)
{
      if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)== GPIO_PIN_RESET )
      {
          static bool state = false;
          if(state == false)
          {
              state = true;
              HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
          }
          else
          {
              state = false
              HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);
          }
          while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)== GPIO_PIN_RESET){} // wait for button to be released, otherwise it will keep toggling every 500ms 
      }
      delay_ms(500);
} 

这是 C++ 代码,因为它使用 boolint 的值 10 可用于 C。

所做的是声明变量state 并将其保存在堆内存中,因为static 关键字。 (而不是在外部if 语句的范围退出时将被破坏的堆栈内存)它被初始化为false,然后在您按下按钮时更新。

【讨论】:

  • 你的功能和 OP 一样糟糕。要切换,您需要先等待按钮释放,然后再按一次必须切换 LED。目前它只有“工作”,因为你有极长的延迟。按住按钮,你会发现它很糟糕。
  • @P__JsupportswomeninPoland 完全正确,现在将修复
【解决方案2】:

可能的(粗略)解决方案:

#include <stdbool.h>

#define BUTTON_DOWN() (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET)
#define LED(on) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, (on) ? GPIO_PIN_SET : GPIO_PIN_RESET)

static bool _pressed_before = false;
static bool _led = false;

/* somewhere in main loop */
{
    const bool pressed = BUTTON_DOWN();
    if (pressed && !_pressed_before) { /* button pressed? */
        _led = !_led; /* toggle LED state */
        LED(_led);
    }
    _pressed_before = pressed; /* remember state */
}

一些注意事项:
您可以使用外部 GPIO 中断(搜索 GPIO EXTI),而不是不断地轮询状态。并且几乎总是需要在按钮引脚(RC 滤波器)上使用硬件去抖动和/或使用软件去抖动来防止错误检测到边缘。 - 另外:这个问题并不是真正的 STM32 / 硬件特定的,因此您可以通过在这些主题上更广泛地搜索网络来找到更一般的答案。

【讨论】:

  • external GPIO interrupt 最糟糕的方式
  • 使用 EXTI 中断来捕获按钮按下事件可提供最佳的输入延迟,并且可以直接使用。根据应用程序,最好不要轮询状态,尤其是。当按钮按下应该尽快处理,并且应该对硬件级别有直接影响(例如,在 ISR 中的寄存器中翻转一个位,不需要外部处理程序)。 - 您能否详细说明一下为什么您认为这是“最糟糕的方式”?
  • st possible input latency 是的 - 这对人类所压制的东西很重要:D
  • 在某些情况下,对按钮事件使用中断当然会有优势。如果主循环每隔一秒读取一次引脚,因为它正在处理一个时间紧迫的任务,那么在 ISR 中处理按钮按下事件或者设置一个在代码中其他地方处理的标志可能会很好。
猜你喜欢
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 2011-01-31
  • 2021-09-23
  • 1970-01-01
  • 2011-05-12
  • 1970-01-01
  • 2012-12-11
相关资源
最近更新 更多