Skocz do zawartości

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


przem312

Pomocna odpowiedź

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?

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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 🙂

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

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.

Link do komentarza
Share on other sites

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 🙁

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.