Skocz do zawartości

[C] [STM32] Samoczynnie wykonują się przerwania zewnętrzne


Pomocna odpowiedź

Napisano

Witam,
mam zbudowane menu na klawiaturze czteroprzyciskowej, której obsługę zaprogramowałem w przerwaniach EXTI. Przykładowy przycisk defioniowany jest w następujący sposób:

#ifdef KB1
//Konfiguracja NVIC - ustawienia priorytetow przerwania EXTI0 Dla przycisku OK (KB1)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);                //Wybor modelu grupowania przerwan

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;               //Wybor konfigurowanego IRQ
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;      //Priorytet grupowy
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;             //Podpriorytet
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //Wlaczenie obslugi IRQ
NVIC_Init(&NVIC_InitStructure);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource0);    //Ustawienie zrodla przerwania

//Konfiguracja przerwania EXTI0 na linie 0
EXTI_InitStructure.EXTI_Line = EXTI_Line0;                     //Wybor linii
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;            //Ustawienie generowania przerwania (a nie zdarzenia)
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;        //Wyzwalanie zboczem opadajacym (wcisniecie przycisku)
EXTI_InitStructure.EXTI_LineCmd = ENABLE;                      //Wlaczenie przerwania
EXTI_Init(&EXTI_InitStructure);
#endif

Problem polega na tym, że gdy uruchamia się urządzenie (w sumie niezależnie od tego czy przez reset w debuggerze, hard reset czy przywrócenie zasilania) program przeskakuje wszystkie możliwe przerwania i je wykonuje. Skutkuje to tym, że jeden przycisk, odpowiadający za start pomiaru (jest to urządzenie mierzące przy napięciu sieciowym) od włączenia zasilania jest odpalany. Wszystko niestety póki co montowane jest na płytkach uniwersalnych łączonych kenarem, więc nie wykluczam zimnych lutów. Co może być przyczyną takiego stanu rzeczy?

Dzięki za zainteresowanie 😉

Procedura przerwania:

void EXTI0_IRQHandler(void)
{
 if (EXTI_GetITStatus(EXTI_Line0) != RESET)
 	 {
	 if(submenu==0)
	 	 {
		 submenu=1;
		 if(pozycja==0)
		 	 {
			 	 submenu=0;
			 	 onPomiar=1;
		 	 }
		 else{
			 	 opcja=pozycja;
			 	 pozycja=0;
		 	 }
	 	 }
 	 }
EXTI_ClearITPendingBit(EXTI_Line0);   //wyzeruj flage obslugi przerwania
}

W niej zaimplementowałem poruszanie się po menu. Wydawało mi się to sensowniejsze niż wyciąganie na zewnątrz zmiennych do nieskończonej pętli.

Sam klawisz miałem z początku zdefiniowany jako IN_FLOATING z pull-upem do 3v3, potem, by wyeliminować możliwość zbierania się ładunku na lucie (wtedy dotknięcie czymkolwiek metalowym płytki skutkowało przerwaniem...) zastosowałem wewnętrzny pullup. Zegary dla wejść mam skręcone do 2MHz.

Hejo 🙂

Po pierwsze czyszczenie flagi raczej powinno się znajdować wewnątrz warunku istnienia przerwania, taki zabieg kosmetyczny - bez sensu czyścić flagę, jak jest ona pusta. Następnie warto też ustawić w pamięci tablicę wektorów przerwań:

#ifdef  VECT_TAB_RAM
 	NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else
 	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif

Aha, częstym błędem jest też, że ludzie zapominają włączyć zegar dla funkcji alternatywnych: RCC_APB2Periph_AFIO, przynajmniej ja usilnie na początku o tym zapominałem 😋 Daj znać, czy cokolwiek pomogło, jeśli nie to będziemy myśleć dalej 🙂

Niestety nic nie pomogło. Próbowałem też oznaczyć trigger na zbocze narastające. Ale też nic to nie dało. zaczynam tracić koncepcje 😉

W takim razie na podstawie tego kawałka kodu co pokazałeś ja nie widzę błędu programistycznego. Może spróbuj napisać bardzo prymitywny program tylko i wyłącznie z obsługą przycisków i wrzuć to do funkcji, bo makra czasami bywają zawodne.

A jakbyś miał oscyloskop (wiem, wiem, burżujsko, ale może akurat masz dostęp) to sprawdź, czy na pewno nic się nie dzieje na pinie PD0.

Następnie warto też ustawić w pamięci tablicę wektorów przerwań:

Jakiś konkretny powód ? Jeśli kolega nie ma w planach bootloadera jest to zabieg zbyteczny czy modyfikacji adresu funkcji przerwań na inne w czasie działania programu. Nie ma sensu przenosić ją do RAM. Domyślnie jest to i tak początek flash.

przem312 - Twoim przyjacielem powinień raczej zostać Timer niż Exti. Zobacz że drgania zestyków mogą trwać ponad kilka ms i mieć różny rozkład częstotliwości i napięcia w czasie. Skręcenie zegara GPIO do 2MHz niewiele się zda. Trzeba próbkować sygnał. Powiedzmy minimum 20 ms dwie próbki określą stabilność stanu.

Jeśli chcesz, możesz zbierać informację z GPIO nie wykorzystując w ogóle przerwania, wystarczy zaprzęgnąć DMA z GPIO do RAM oraz Timer do próbkowania i sprawdzasz tylko w głównym programie.

Korzystanie z tej śmiesznej biblioteki ST to... słaby pomysł. Szczególnie w przerwaniach, to już przynajmniej mogłeś wywołać ten rejestr normalnie 🙁

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