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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.