Skocz do zawartości

[STM32] Losowe gaszenie diody - zastosowanie przerwania


yukimikoto

Pomocna odpowiedź

Dzień dobry.

Napisałam taki program w CUBEMXIde:

 

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();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

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

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda4_GPIO_Port, dioda4_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
		    HAL_GPIO_WritePin(diod1_GPIO_Port, diod1_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda2_GPIO_Port, dioda2_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda3_GPIO_Port, dioda3_Pin, GPIO_PIN_RESET);
		/* USER CODE END WHILE */

  }
  /* USER CODE END 3 */
}


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Port)
{
	if (GPIO_Port == przycisk_Pin)
	{

		HAL_GPIO_WritePin(diod1_GPIO_Port, diod1_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(dioda2_GPIO_Port, dioda2_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(dioda3_GPIO_Port, dioda3_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(dioda4_GPIO_Port, dioda4_Pin, GPIO_PIN_SET);

	}
}

Program miał zaświecić cztery diody po kliknięciu przycisku, a następnie odczekać 2000 ms i po kolei gasić diody. Niestety, program gasi je w sposób losowy, za każdym kliknięciem przycisku, inaczej. Dlaczego tak się dzieje?

 

Pozdrawiam

Link do komentarza
Share on other sites

Pętla główna programu wykonuje się w kółko, nie jest w żaden sposób „blokowana". Oznacza to inne zachowanie diod w zależności od tego, kiedy wystąpi przerwanie.

Przykład (zaznaczyłem miejsce, gdzie zakładam, że naciśnięto przycisk):

			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda4_GPIO_Port, dioda4_Pin, GPIO_PIN_RESET);
			// Przypuścmy, że w tym momencie wykonuje się przerwanie
			HAL_Delay(1000);
		    	HAL_GPIO_WritePin(diod1_GPIO_Port, diod1_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda2_GPIO_Port, dioda2_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda3_GPIO_Port, dioda3_Pin, GPIO_PIN_RESET);

W takiej sytuacji po wciśnięciu przycisku nastąpi procedura przerwania – lamki się zaświecą, po 1 sekundzie zaczną gasnąć (z odstępem jednosekundowym) zaczynając od „diod1".

Przerwanie może wystąpić w zasadzie w dowolnym momencie wykonywania pętli głównej programu.  Zauważ, że w żaden sposób nie badasz tego, czy diody zostały zaświecone, tylko je gasisz. Chyba najlepszą metodą odmierzania czasów są timery, jeśli chcesz jednak jak najmniej modyfikować swój kod, to najprościej chyba jest wstawić zmienną globalną do kodu, ustawiać ją w przerwaniu, a badać jej stan (i zerować) w pętli głównej, czyli coś takiego:

  while (1)
  {
    if(zmiennaGlobalna)
    {
			HAL_Delay(2000);
			HAL_GPIO_WritePin(dioda4_GPIO_Port, dioda4_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
		   	HAL_GPIO_WritePin(diod1_GPIO_Port, diod1_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda2_GPIO_Port, dioda2_Pin, GPIO_PIN_RESET);
			HAL_Delay(1000);
			HAL_GPIO_WritePin(dioda3_GPIO_Port, dioda3_Pin, GPIO_PIN_RESET);
      			zmiennaGlobalna = 0;
    }
//    else
//    {
//      		HAL_Delay(10);
//    }
  }

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Port)
{
	if (GPIO_Port == przycisk_Pin)
	{
		zmiennaGlobalna = 1;
		HAL_GPIO_WritePin(diod1_GPIO_Port, diod1_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(dioda2_GPIO_Port, dioda2_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(dioda3_GPIO_Port, dioda3_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(dioda4_GPIO_Port, dioda4_Pin, GPIO_PIN_SET);

	}
}

W ten sposób zaczynasz gasić diody dopiero wtedy, gdy zostały zaświecone. Ale tak, jak wspomniałem, są lepsze sposoby do tego typu rzeczy.

Inną, potencjalną przyczyną problemów mogą być również drgania styków – czy jednokrotne naciśnięcie przycisku powoduje wygenerowanie jednego przerwania?

  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.