7 votos

El LED parpadea incluso cuando no presiono el botón

He escrito un programa en Keil que hace parpadear un LED a través de una interrupción GPIO externa. Así es como lo he configurado en STM32CubeMX:

Al principio, habilité y configuré RCC como puedes ver y configuré PA0 para interrupción externa y PB1 como salida.

figure1

Para la fuente de reloj, lo configuré como se puede ver a continuación.

figure2

Y para Pins

figure3

figure4

He marcado la casilla "Interrupción de la línea 0 y la línea 1 de EXTI". No estoy seguro de que sea necesario marcar esta casilla.

figure5

Después de la configuración, he generado el código fuente de abajo (main.c):

/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* System interrupt init*/
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

  /* Initialize all configured peripherals */
  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* USER CODE BEGIN 3 */
  /* Infinite loop */
  while (1)
  {

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);

  __SYSCFG_CLK_ENABLE();

}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __GPIOF_CLK_ENABLE();
  __GPIOA_CLK_ENABLE();
  __GPIOB_CLK_ENABLE();

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PB1 */
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */ 

/**
  * @}
*/ 

Para manejar la interrupción GPIO externa, abrí el archivo 'stm32f0xx_it.c' y coloqué HAL_GPIO_TogglePin(GPIOB , GPIO_PIN_1) entre HAL_NVIC_ClearPendingIRQ(EXTI0_1_IRQn) y HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0) entonces el código fuente de la interrupción es este:

/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"
#include "stm32f0xx.h"
#include "stm32f0xx_it.h"

/* External variables --------------------------------------------------------*/

/******************************************************************************/
/*            Cortex-M4 Processor Interruption and Exception Handlers         */ 
/******************************************************************************/

/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
  HAL_IncTick();
  HAL_SYSTICK_IRQHandler();
}

/**
* @brief This function handles EXTI Line 0 and Line 1 interrupts.
*/
void EXTI0_1_IRQHandler(void)
{
  HAL_NVIC_ClearPendingIRQ(EXTI0_1_IRQn);
  HAL_GPIO_TogglePin(GPIOB , GPIO_PIN_1);
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

He construido el archivo HEX correctamente y lo he descargado en la MCU (sin ningún problema ni error). Ahora, cuando lo ejecuto, hay un problema. El LED parpadea rápidamente incluso cuando no presiono el botón. Mira:

figure6

figure7

¿Por qué? Además, cuando pulso el botón, el LED cambia de estado pero parpadea entre cada pulsación. Parece que algo cambia el estado del pin PB1. ¿Cuál es el problema? ¿Cómo puedo corregirlo?

2 votos

Nunca he utilizado esa serie de procesadores, pero me he dado cuenta de que tienen GPIO_InitStruct.Pull = GPIO_NOPULL puede que tengas que cambiarlo para tirar a tierra (si está disponible) o utilizar una resistencia externa para tirar a tierra. No estoy seguro de si podría haber otros problemas, pero vale la pena intentarlo.

0 votos

@PeterJ Gracias Peter por la respuesta. Ya lo he probado. Me refiero a que ya Pulled-up resistencia interna (por el ruido), pero que no funciona. en tutoriales ST, nunca utilizan resistencia pull-up.

7voto

user4245 Puntos 324

Usted debe Utiliza la resistencia interna de pullup / pulldown del chip, o suministra tu propia resistencia.

También puedes, al mismo tiempo, rebotar la entrada añadiendo otra resistencia más pequeña y un pequeño condensador:

schematic

simular este circuito - Esquema creado con CircuitLab

La teoría de funcionamiento es que cuando el interruptor está abierto el pullup / pulldown "tira" del pin de entrada a un valor conocido. Si su interruptor conecta el pin a tierra, entonces una resistencia pullup conectará el pin a \$+V_{CC}\$ cuando el interruptor no está siendo presionado. Cuando el interruptor está pulsado, tanto el pin como la resistencia están conectados a tierra, por lo que el pin recibe \$0V\$ y una pequeña corriente (unos pocos mA dependiendo del voltaje y la resistencia) fluye a través de la resistencia.

0 votos

Gracias. Cuando lo bajé (por una resistencia externa como ilustraste en la figura), funciona correctamente!!! ¡bien hecho!

0 votos

También tengo un simple problema ahora, ¡es el rebote! ¿Cómo puedo desbaratarla?

2 votos

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X