【发布时间】:2015-12-26 00:30:55
【问题描述】:
我编写了一些代码,每次单击按钮时必须一个接一个地打开 LED(一轮),但有时单击按钮不会点亮下一个 LED,而是从四个 LED 中随机点亮一个。这就像一个或多个 LED 跳过它的轮次。我认为问题是由于时钟速率设置错误或上升/下降 EXTI 触发器设置错误引起的。 板子:STM32DISCOVERY
periph.h
#ifndef PERIPH_H
#define PERIPH_H
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "misc.h"
#include "stm32f4xx_exti.h"
#include "stm32f4xx_syscfg.h"
void Initialize_GPIO_LEDS(void);
void Initialize_GPIO_Button(void);
void Initialize_EXTI0_PA(void);
void Initialize_NVIC(void);
typedef enum
{
GPIO_LED_Green = GPIO_Pin_12,
GPIO_LED_Yellow = GPIO_Pin_13,
GPIO_LED_Red = GPIO_Pin_14,
GPIO_LED_Blue = GPIO_Pin_15
}GPIO_LED_TypeDef;
void GPIO_LED_On(GPIO_LED_TypeDef GPIO_LED_x);
void GPIO_LED_Off(GPIO_LED_TypeDef GPIO_LED_x);
void GPIO_LED_All_On(void);
void GPIO_LED_All_Off(void);
#endif /* PERIPH_H */
periph.c
#include "periph.h"
GPIO_InitTypeDef GPIO_LEDS;
GPIO_InitTypeDef GPIO_Button;
EXTI_InitTypeDef EXTI0_PA;
NVIC_InitTypeDef NVIC_Struct;
void Initialize_GPIO_LEDS(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_LEDS.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_12;
GPIO_LEDS.GPIO_Mode = GPIO_Mode_OUT;
GPIO_LEDS.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_LEDS.GPIO_OType = GPIO_OType_PP;
GPIO_LEDS.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_LEDS);
}
void Initialize_GPIO_Button(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_Button.GPIO_Pin = GPIO_Pin_0;
GPIO_Button.GPIO_Mode = GPIO_Mode_IN;
GPIO_Button.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Button.GPIO_OType = GPIO_OType_PP;
GPIO_Button.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &GPIO_Button);
}
void Initialize_EXTI0_PA(void)
{
EXTI0_PA.EXTI_Line = EXTI_Line0;
EXTI0_PA.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI0_PA.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI0_PA.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI0_PA);
}
void Initialize_NVIC(void)
{
NVIC_Struct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_Struct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Struct);
}
void GPIO_LED_On(GPIO_LED_TypeDef GPIO_LED_x)
{
GPIO_SetBits(GPIOD, GPIO_LED_x);
}
void GPIO_LED_Off(GPIO_LED_TypeDef GPIO_LED_x)
{
GPIO_ResetBits(GPIOD, GPIO_LED_x);
}
void GPIO_LED_All_On(void)
{
GPIO_SetBits(GPIOD, GPIO_LED_Green | GPIO_LED_Yellow | GPIO_LED_Red | GPIO_LED_Blue);
}
void GPIO_LED_All_Off(void)
{
GPIO_ResetBits(GPIOD, GPIO_LED_Green | GPIO_LED_Yellow | GPIO_LED_Red | GPIO_LED_Blue);
}
main.c
#include "cmsis_os.h"
#include "periph.h"
uint8_t led_num = 0;
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) != RESET)
{
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
{
led_num++;
if (led_num == 4) led_num = 0;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
int main (void)
{
Initialize_GPIO_LEDS();
Initialize_GPIO_Button();
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
Initialize_EXTI0_PA();
Initialize_NVIC();
while(1)
{
switch(led_num)
{
case 0 : GPIO_LED_On(GPIO_LED_Green); break;
case 1 : GPIO_LED_On(GPIO_LED_Yellow); break;
case 2 : GPIO_LED_On(GPIO_LED_Red); break;
case 3 : GPIO_LED_On(GPIO_LED_Blue); break;
}
GPIO_LED_All_Off();
}
}
【问题讨论】:
-
不要在 Exti 中断处理程序中使用
GPIO_ReadInputDataBit重新采样按钮。中断处理程序触发的事实意味着 GPIO 线上有一个上升沿。如果按钮释放得足够快,您所做的只是让忽略按钮成为可能。
标签: interrupt keil stm32f4discovery debouncing