STM32F103 | libopencm3 |使用中断问题的 GPIO 切换
STM32F103 | libopencm3 | GPIO toggle using interrupt issue
所以,我正在尝试根据按钮的中断来切换 LED。
理想情况下,当按下按钮时,LED 应该切换,即如果它关闭则打开,反之亦然。但是当我执行这段代码时,它会切换 returns 到它的原始状态。
预期结果:
LED 熄灭 » 按下按钮 » LED 亮起
实际结果:
LED 关闭 » 按下按钮 » LED 打开 » LED 关闭
我为去抖动添加了延迟,所以不会出现抖动。此外,按下按钮时 GPIO 的 ODR 在 ISR 中设置,那么在退出 ISR 时如何清除它?
非常感谢您的帮助!谢谢。
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/cm3/nvic.h>
#define LEDPIN (GPIO13)
static void exti_setup(void)
{
/* Enable GPIOA and AFIO clock. */
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_AFIO);
/* Enable EXTI0 interrupt. */
nvic_enable_irq(NVIC_EXTI15_10_IRQ);
/* Set GPIO12 (in GPIO port B) to input */
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT, GPIO12);
/* Configure the EXTI subsystem. */
exti_select_source(EXTI12,GPIOB);
exti_set_trigger(EXTI12, EXTI_TRIGGER_BOTH);
exti_enable_request(EXTI12);
}
static void gpio_setup(void)
{
/* Enable clock for GPIO port C */
rcc_periph_clock_enable(RCC_GPIOC);
/* Set LEDPIN (in GPIO port C) as opendrain output */
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, LEDPIN);
}
void delay(){
int i;
for (i = 0; i < 1000000; i++)
{
__asm__("nop");
}
}
void handler(){
delay();
gpio_toggle(GPIOC, GPIO13);
}
int main(void)
{
gpio_setup();
exti_setup();
while (1) {
__asm__("nop");
}
return 0;
}
void exti15_10_isr()
{
exti_reset_request(EXTI12);
handler();
}
- 不是开漏而是推挽
- Butttons 不应使用 EXTI,因为它会使 去抖动 变得更复杂,经常使 uC 充满中断,请使用定时器中断来读取密钥和去抖动。
正如@dev_eng 正确指出的那样,问题是中断被配置为两个 RISING/FALLING 边缘。
用上升或下降的单边配置解决了我的问题。
所以,我正在尝试根据按钮的中断来切换 LED。
理想情况下,当按下按钮时,LED 应该切换,即如果它关闭则打开,反之亦然。但是当我执行这段代码时,它会切换 returns 到它的原始状态。
预期结果: LED 熄灭 » 按下按钮 » LED 亮起
实际结果: LED 关闭 » 按下按钮 » LED 打开 » LED 关闭
我为去抖动添加了延迟,所以不会出现抖动。此外,按下按钮时 GPIO 的 ODR 在 ISR 中设置,那么在退出 ISR 时如何清除它?
非常感谢您的帮助!谢谢。
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/cm3/nvic.h>
#define LEDPIN (GPIO13)
static void exti_setup(void)
{
/* Enable GPIOA and AFIO clock. */
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_AFIO);
/* Enable EXTI0 interrupt. */
nvic_enable_irq(NVIC_EXTI15_10_IRQ);
/* Set GPIO12 (in GPIO port B) to input */
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT, GPIO12);
/* Configure the EXTI subsystem. */
exti_select_source(EXTI12,GPIOB);
exti_set_trigger(EXTI12, EXTI_TRIGGER_BOTH);
exti_enable_request(EXTI12);
}
static void gpio_setup(void)
{
/* Enable clock for GPIO port C */
rcc_periph_clock_enable(RCC_GPIOC);
/* Set LEDPIN (in GPIO port C) as opendrain output */
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, LEDPIN);
}
void delay(){
int i;
for (i = 0; i < 1000000; i++)
{
__asm__("nop");
}
}
void handler(){
delay();
gpio_toggle(GPIOC, GPIO13);
}
int main(void)
{
gpio_setup();
exti_setup();
while (1) {
__asm__("nop");
}
return 0;
}
void exti15_10_isr()
{
exti_reset_request(EXTI12);
handler();
}
- 不是开漏而是推挽
- Butttons 不应使用 EXTI,因为它会使 去抖动 变得更复杂,经常使 uC 充满中断,请使用定时器中断来读取密钥和去抖动。
正如@dev_eng 正确指出的那样,问题是中断被配置为两个 RISING/FALLING 边缘。
用上升或下降的单边配置解决了我的问题。