LED blinkt auch wenn ich die Taste nicht drücke

Ich habe ein Programm in Keil geschrieben, das eine LED über einen externen GPIO-Interrupt blinkt. So habe ich es in STM32CubeMX konfiguriert:

Zuerst habe ich RCC aktiviert und konfiguriert, wie Sie sehen können, und PA0 für den externen Interrupt und PB1 als Ausgang konfiguriert.

Abbildung 1

Für die Taktquelle habe ich sie so konfiguriert, wie Sie unten sehen können.

Figur 2

Und für Pins

Figur 3

Figur 4

Ich habe das Kontrollkästchen "EXTI Line 0 and Line 1 interrupt" aktiviert. Ich bin mir nicht sicher, ob das Aktivieren dieses Kontrollkästchens erforderlich ist.

Abbildung5

Nach der Konfiguration habe ich den folgenden Quellcode generiert (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

/**
  * @}
  */ 

/**
  * @}
*/ 

Für die Handhabung des externen GPIO-Interrupts habe ich die Datei ‚stm32f0xx_it.c‘ geöffnet und HAL_GPIO_TogglePin(GPIOB , GPIO_PIN_1)dazwischen platziert, HAL_NVIC_ClearPendingIRQ(EXTI0_1_IRQn)und HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0)dann lautet der Interrupt-Quellcode wie folgt:

/* 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);
}

Ich habe die HEX-Datei korrekt erstellt und auf die MCU heruntergeladen (ohne Probleme oder Fehler). Jetzt, wenn ich es ausführe, gibt es ein Problem. Die LED blinkt schnell, auch wenn ich die Taste nicht drücke. Aussehen:

Abbildung6

Abbildung7

Warum? Auch wenn ich die Taste drücke, wird die LED umgeschaltet, aber sie blinkt zwischen jedem Drücken. Es sieht so aus, als ob etwas den Zustand des PB1-Pins ändert. Was ist das Problem? Wie kann ich es korrigieren?

Ich habe diese Serie von Prozessoren noch nie verwendet, aber Sie haben bemerkt, dass GPIO_InitStruct.Pull = GPIO_NOPULLSie das möglicherweise ändern müssen, um es auf Masse zu ziehen (falls verfügbar) oder einen externen Widerstand verwenden, um es auf Masse zu ziehen. Ich bin mir nicht sicher, ob es andere Probleme geben könnte, aber das ist einen Versuch wert.
@ PeterJ Danke Peter für die Antwort. Ich habe es schon probiert. Ich meine, ich habe bereits einen internen Widerstand hochgezogen (für Geräusche), aber das funktioniert nicht. In ST-Tutorials verwenden sie niemals einen Pull-up-Widerstand.

Antworten (1)

Sie müssen entweder den internen Pullup- / Pulldown-Widerstand des Chips verwenden oder Ihren eigenen Widerstand bereitstellen.

Sie können den Eingang auch gleichzeitig entprellen, indem Sie einen weiteren kleineren Widerstand und einen kleinen Kondensator hinzufügen:

schematisch

Simulieren Sie diese Schaltung – Mit CircuitLab erstellter Schaltplan

Die Betriebstheorie lautet, dass bei geöffnetem Schalter der Pullup / Pulldown den Eingangsstift auf einen bekannten Wert "zieht". Wenn Ihr Schalter den Pin mit Masse verbindet, verbindet ein Pullup-Widerstand den Pin mit + v C C wenn der Schalter nicht gedrückt wird. Wenn der Schalter gedrückt wird, werden sowohl der Pin als auch der Widerstand mit Masse verbunden, so dass der Pin bekommt 0 v und ein kleiner Strom (einige mA je nach Spannung und Widerstand) fließt durch den Widerstand.

Vielen Dank. Wenn ich es heruntergezogen habe (durch einen externen Widerstand, wie Sie in Abbildung dargestellt haben), funktioniert es richtig !!! gut gemacht!
Außerdem habe ich jetzt ein einfaches Problem, es ist Bounce! Wie kann ich es entprellen?
In einigen Fällen verwenden sie für 5 V 10 nf zum Entprellen, aber meine MCU arbeitet mit 3,3 V. Ist Ihrer Meinung nach der 10nf-Kondensator dafür geeignet?
Normalerweise verwende ich 10K Pullup, 100nF Kondensator und 100Ω Entladewiderstand.
"Entladewiderstand"? Wozu dient dieser Widerstand?
Es entlädt den Kondensator langsam und erzeugt einen sanften Übergang, wenn Sie die Taste drücken.
Wenn Sie den Kondensator und den Entladewiderstand im obigen Schema hinzufügen, ist dies eine großartige Antwort.