如果我可以在项目中实现长按和短按按钮,这将派上用场。我正在使用STM32F4 Discovery Kit并在C语言中对其进行编程。我准备了一个引脚作为外部输入,我修改了中断处理程序。
我暂时将其设置为触发下降和上升。我没有明显的方法来检测长短推动。有什么办法吗?
答案 0 :(得分:2)
一种选择是在按下按钮后立即启动计时器,并在释放按钮后停止计时器。根据计时器中经过的滴答声数量,您可以采取正确的操作,但是您需要确定滴答声阈值,以区分长按和短按。
作为上述建议的改进。您可以将其配置为IO中断源,而不必将按钮所连接的引脚配置为GPIO。此方法也有助于您解决声标问题。
答案 1 :(得分:1)
是的,这很好,这是STM32上的Interrupt处理程序中的一种解决方案。
全局变量:
static uint32_t lastUserButtonI = 700;
static uint32_t lastUserButtonRisingI = 700;
static uint32_t lastUserButtonFallingI = 700;
在HAL_GPIO_EXTI_Callback()
中:
uint32_t now = HAL_GetTick();
uint8_t rising = HAL_GPIO_ReadPin(Button_GPIO_Port, pButton);
if ((lastEdge == rising) ||
(rising == 0 && ((now - lastUserButtonFallingI) <= 200)) ||
(rising == 1 && ((now - lastUserButtonRisingI) <= 200))) {
DBG_PRINTF("CANCELLING, %u\n", (uint)now);
} else {
if (rising == 1) {
DEBUG_MSG("RISING\n");
lastUserButtonRisingI = now;
} else {
DEBUG_MSG("FALLING\n");
lastUserButtonFallingI = now;
}
DBG_PRINTF("Button Press Gesture, %u\n", (uint)now);
uint32_t diff = lastUserButtonFallingI - lastUserButtonRisingI;
if (rising == 0 && diff >= 10 && diff <= 500) {
// Single press
DEBUG_MSG("SINGLE PRESS\n");
}
if (rising == 0 && diff >= 2000 && diff <= 8000) {
// Long press
DEBUG_MSG("LONG PRESS\n");
}
}
lastEdge = rising;
lastUserButtonI = now;
答案 2 :(得分:0)
首先EXTI中断对按钮非常不利。您应该使用计时器中断并定期检查按钮的状态。即使您有一个电容器,用老化按钮进行抖动也可能不够用。
您可以看到我的按钮库-长,短和双击,任意数量的按钮
答案 3 :(得分:0)
1。我想创建一个不会同时中断主回流和长按和短按状态的按钮读取结构。难道不是为此按下了一个按钮? BT_User_State变量保存数据集,长按按钮,短按按钮?我定义了两个单独的BT_User_Flag_ShortPress和BT_User_Flag_LongPress变量来保存数据,以及一个将在持续时间内保存的BT_User_Time变量。
typedef enum{
Flag_Reset,
Flag_Set
} Button_Flag;
typedef enum{
Button_Released,
Button_Pressed
} Button_State;
Button_State BT_User_State = Button_Released;
Button_Flag BT_User_Flag_ShortPress = Flag_Reset;
Button_Flag BT_User_Flag_LongPress = Flag_Reset;
uint16_t BT_User_Time = 0;
2。每1ms还有一个计时器。完成此操作后,计时器溢出:
if(HAL_GPIO_ReadPin(BT_User_GPIO_Port, BT_User_Pin) == GPIO_PIN_SET)
{
BT_User_State = Button_Pressed;
BT_User_Time++;
}
else
{
if(BT_User_Time >= 750)
{
BT_User_Flag_LongPress = Flag_Set;
}
else if (BT_User_Time >= 50)
{
BT_User_Flag_ShortPress = Flag_Set;
}
BT_User_Time = 0;
BT_User_State = Button_Released;
}
3。如果在进行剪切时按下按钮,则将按钮状态更改为“已打印”,并添加了保存持续时间的变量1。 如果在进行剪切时未按下按钮,则首先检查包含该值的变量,从大值开始,并设置必要的标志。我终于重置了保存持续时间的变量,并将按钮状态更改为“已删除”。
在主循环中:
if(BT_User_Flag_ShortPress == Flag_Set && BT_User_State == Button_Released)
{
HAL_GPIO_TogglePin(LD_Blue_GPIO_Port, LD_Blue_Pin);
BT_User_Flag_ShortPress = Flag_Reset;
}
if(BT_User_Flag_LongPress == Flag_Set && BT_User_State == Button_Released)
{
HAL_GPIO_TogglePin(LD_Red_GPIO_Port, LD_Red_Pin);
BT_User_Flag_LongPress = Flag_Reset;
}