Skocz do zawartości

Kurs STM32 - #4 - Sterowanie portami GPIO w praktyce


Komentator

Pomocna odpowiedź

html_mig_img
W poprzedniej części kursu STM32 nauczyliśmy się tworzyć projekt, kompilować oraz uruchamiać prosty program. Niestety był on mało atrakcyjny, bo nie komunikował się ze światem zewnętrznym.Czas więc poznać okno na świat każdego układu, czyli uniwersalne porty wejścia/wyjścia (GPIO).

UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.

Przeczytaj całość »

Poniżej znajdują się komentarze powiązane z tym wpisem.

Link do komentarza
Share on other sites

STM32F103RB nie posiada sprzętowego układu przeciwdziałającemu drganiu styków (debouncer). Na płytce Nucleo znajdziemy filtr RC, który sprzętowo zmniejszy dokuczliwość drgania styków. Natomiast w przypadku podłączania pozostałych mikroswitch-y musimy drganiami zająć się samemu - sprzętowo lub programowo.

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

Jak zrobić poprawnie obsługę przerwań to właśnie jest praca domowa 🙂

A tak serio, temat jest nieco zbyt obszerny na niniejszy kurs - chociaż liczę, że kilka dobrych przykładów się pojawi.

Przerwania w STM32 są dość skomplikowanym tematem. Po pierwsze nie są kolejkowane (tzn. są, ale jest to kolejka 1-elementowa). Jeśli przerwanie nie może być obsłużone natychmiast, bo np. procesor jest w trakcie obsługi innego przerwania, zostanie ono obsłużone w najbliższym możliwym czasie. Jeśli jednak w czasie tego "oczekiwania" przerwanie zostanie wygenerowane ponownie, to zostanie po prostu zgubione.

Dlatego wszystkie dobre poradniki mówią, że procedury obsługi przerwań powinny być możliwie krótkie.

W przypadku STM32 dochodzą jeszcze priorytety przerwań oraz możliwość wywłaszczenia procedury obsługi przerwania przez przerwanie o wyższym priorytecie.

Link do komentarza
Share on other sites

Dla osób które posiadają, tak jak ja, Nucleo seria z STM32F3xx, polecam:

http://www.st.com/web/en/resource/technical/document/application_note/DM00073522.pdf

Dokument opisuje jak przejść z STM32F1xx na STM32F3xx

Tak wygląda migająca dioda po przystosowaniu dla STM32F3xx

#include "stm32f30x.h"


void delay(int time)
{
	int i;
	for (i = 0; i<time*4000; i++){}
}

int main(void)
{
GPIO_InitTypeDef gpio;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

   GPIO_StructInit(&gpio);
   gpio.GPIO_Pin = GPIO_Pin_5;
   gpio.GPIO_Mode =  GPIO_Mode_OUT;
   gpio.GPIO_OType =  GPIO_OType_PP;
   GPIO_Init(GPIOA, &gpio);

   while (1) {
           GPIO_SetBits(GPIOA, GPIO_Pin_5);
           delay(100);
           GPIO_ResetBits(GPIOA, GPIO_Pin_5);
           delay(400);
       }
}

Mam pytanie, ustawiłem pin 5 jako wyjście

 gpio.GPIO_Mode =  GPIO_Mode_OUT;

i dioda mrugała, jednak w przykładzie dla STM32F1xx wyjście jest typu push-pull, więc dodałem jeszcze:

 gpio.GPIO_OType =  GPIO_OType_PP;

słusznie czy nie? bo nie widzę różnicy w działaniu.

Link do komentarza
Share on other sites

kulawikm, dzięki za czujność 🙂 Napiszę do Treker-a, żeby zmienił, ja już nie mam takich uprawnień. Na usprawiedliwienie mogę tylko napisać, że cały program powinien działać bez problemu. W początkowych wersjach tekstu używałem, podobnie jak przykłady od ST, długich nazw zmiennych - i jak widać tutaj zostało po staremu.

Link do komentarza
Share on other sites

No to czas na podsumowanie mojej nauki:)

Po pierwsze, wg. mnie jest drobna literówka, mianowicie zmienna SystemCoreClock jest w pliku system_stm32f10x.c, a nie system_stm32f10x.h 🙂

Druga rzecz: Podczas rozwiązywania zadań domowych, zauważyłem że użycie triggera EXTI_Trigger_Rising_Falling "symuluje" zastosowanie filtru (w porównaniu do triggera EXTI_Trigger_Rising)

No i na koniec załączam zadania domowe (mam nadzieję, że można) 🙂

zadanie_4.1.c

zadanie_4.2.c

zadanie_4.3.c

zadanie_4.4.c

Link do komentarza
Share on other sites

Gumili, fajnie że chciało Ci się rozwiązać zadania 🙂

Co do zmiennej SystemCoreClock, to nie jest literówka.

W języku C rozróżniamy deklarację i definicję, zmiennej, czy też funkcji.

Deklaracja informuje kompilator, co nazwa (identyfikator) będzie oznaczała. Przykładowo zmienną o określonym typie. Definicja przydziela pamięć dla zmiennej, albo określa treść funkcji.

Przykłady deklaracji:

extern int x;

void magic_function(void);

Przykłady definicji:

int x = 5;

void magic_function(void)
{
 printf("%d\n", x);
}

Definicja jest jednocześnie deklaracją. Deklaracji używa się, żeby móc używać danego typu/funkcji jeszcze przed jej zdefiniowaniem. Przykładowo możemy wywołać funkcję, którą zadeklarowaliśmy, ale jej kod jest zdefiniowany później. Co ważne definicja danego obiektu może wystąpić tylko raz w całym programie (inaczej wystąpi błąd podczas linkowania). Natomiast deklaracje mogą pojawiać się wielokrotnie.

Najczęściej deklaracje umieszczane są w plikach o rozszerzeniu .h. Dzięki temu pozostałe moduły mogą odwoływać się do tych identyfikatorów, nawet jeśli nie zostały jeszcze zdefinowane.

W plikach z kodem .c umieszczane są definicje (oczywiście pasujace do wcześniejszych deklaracji).

[ Dodano: 27-09-2015, 11:45 ]

Jak chodzi o EXTI_Trigger_Rising_Falling i EXTI_Trigger_Rising to różnica nie polega na filtracji, ale wykrywaniu zbocza sygnału.

Jeśli przycisk jest zwolniony, to na wejściu procesora pojawia się sygnał wysoki (logiczne 1, czyli 3.3V). Gdy naciskamy przycisk, zwieramy pin do masy, stan zmienia się na niski (logiczne 0, inaczej 0V). Zmiana ze stanu wysokiego na niski to zbocze opadające. Może być wykryte jeśli reagujemy na zdarzenie EXTI_Trigger_Falling.

Jeśli po pewnym czasie zwolnimy przycisk, stan zmieni się z niskiego na wysoki, co odpowiada pojawieniu się zbocza narastającego, czyli EXTI_Trigger_Rising.

Ustawienie flagi EXTI_Trigger_Rising_Falling pozwala na wykrywanie obu zboczy, czyli zarówno przyciskania, jak i zwalniania przycisku.

Przygotowując ćwiczenia myślałem, że będzie więcej problemów z drgajacymi stykami. Jednak filtr RC skutecznie temu przeciwdziała. Proponuję więc małą zmianę w pracy domowej - podłącz zewnętrzny mikroswitch i porównaj działanie układu 🙂

[ Dodano: 27-09-2015, 11:51 ]

A do aktualnej wersji zadań - czy jeśli kilka razy naciskasz przycisk, program zawsze zachowuje się poprawnie?

Przykładowo po naciśnięciu 4 razy program 4.1 powinien sterować diodamy w tym samym kierunku co wcześniej, czy zawsze tak jest?

Podobnie program 4.2 - czy szybko naciskając 4 razy, zawsze zapalimy odpowiednią diodę?

Link do komentarza
Share on other sites

Mam problem z obsługą przerwań w moim STM32F303RE, nie mogę zlokalizować problemu, wszystko wykonałem zgodnie z kursem, zmieniając oczywiście pod STM32F3, np.:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //Aktywacja funkcji alternatywnych
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource13); //wybór linii i portu

W pętlę while włożyłem kod z przesuwającą się diodą LED na linijce świetlnej, żeby móc obserwować pracę mikrokontrolera. Po naciśnięciu przycisku główny program się zatrzymuje i na tym koniec. Dioda LED na płytce Nucleo nie zapala się. Wygląda to tak jakby przerwanie zostało wywołane i mikrokontroler w nim pozostał.

Gdzie może być błąd? Czy dla STM32F3 obsługa przerwań jest inna? Zastosowałem wszystkie wymagane zmiany według dokumentu:

http://www.st.com/web/en/resource/technical/document/application_note/DM00073522.pdf

Link do komentarza
Share on other sites

Witam!

Dziś zacząłem bawić się nową płytką (STM32F0 Discovery) i napotkałem na taki błąd:

../src/main.c: In function 'main':
../src/main.c:14:28: error: 'RCC_APB2Periph_GPIOC' undeclared (first use in this function)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // uruchomienie zegara modulu GPIO
                           ^
../src/main.c:14:28: note: each undeclared identifier is reported only once for each function it appears in
../src/main.c:18:22: error: 'GPIO_Mode_Out_PP' undeclared (first use in this function)
    gpio.GPIO_Mode = GPIO_Mode_Out_PP; // jako wyjscie
                     ^
make: *** [src/main.o] Error 1

Oczywiście zmieniłem port diody na taki jest w mojej płytce. Czy błędy te wynikają z faktu iż mój układ bazuje na M0 a nie na M3?

__________

Komentarz dodany przez: Treker

Pamiętaj na przyszłość, aby kody i logi umieszczać w tagach , tym razem poprawiłem 🙂

Link do komentarza
Share on other sites

Porty GPIO STM32F0 znajdują się na szynie AHB (dokumentacja). Dodatkowo, biblioteki STM32F3 i STM32F0 różnią się między sobą, nie ma tutaj "GPIO_Mode_Out_PP".

Poniżej przykładowa inicjalizacja pinu 8 portu C

 
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOC, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
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.