Skocz do zawartości

Kurs STM32 - #4 - Sterowanie portami GPIO w praktyce


Komentator

Pomocna odpowiedź

Po pierwsze, świetny kurs!

Po drugie, zastanawiałem się skąd biorą się te 64MHz i dlaczego zmienna SystemCoreClock przyjmuje wartość 72000000 a nie właśnie 64000000. W reference manual znalazłem że sygnał z HSI (8MHz) przed PLL jest dzielony przez 2 natomiast sama pętla PLL może maksymalnie pomnożyć wynik x16 co daje dokładnie 64MHz. To po części wyjaśnia mój pierwszy problem.

Następnie zajrzałem do pliku system_stm32f10x.c tam łatwo znaleźć fragment "odpowiedzialny" za późniejsze ustawienia zegara (linie 116-121, wystarczy odkomentować odpowiednią wartość, default 72MHz). Co więcej ta właśnie wartość przypisywana jest później do zmiennej SystemCoreClock co wyjaśnia dlaczego mamy tam 72000000. I tu pojawia się problem, ponieważ w dalszej części kodu znalazłem fragmenty które dotyczą tylko HSE. Na końcu znajdziemy funkcję SetSysClockTo72 która na początku ma warunek uruchomienia HSE, jeśli to się nie uda zostaje opuszczony cały fragment kodu odpowiedzialny za ustawienia częstotliwości taktowania magistrali i rdzenia. W komentarzach można znaleźć uwagę że jeśli nie zostanie uruchomiony zewnętrzny oscylator (lub wprowadzone jakiekolwiek zmiany) to HSI jest używany jako źródło sygnału zegara ([...] the HSI is used as System clock source [...]). I wreszcie moje pytanie, dlaczego (wnioskując z mojego ostatniego zdania) nie zostajemy z tymi 8MHz tylko otrzymujemy 64MHz?

Z góry dziękuję za pomoc 😉

Ps.: Mam trochę wrażenia jakby ten fragment biblioteki (w sumie to plik start) był przystosowany tylko do zewnętrznego źródła sygnału dla zegara 😃

Edit: W User Manual samego nucleo znalazłem coś takiego jak na załączonym obrazku (strona 22). Z tego wynika że jednak możemy korzystać z HSE, tylko źródłem sygnału będzie programator. Tylko w takim razie dlaczego mamy 64MHz a nie 72MHz? Chyba że jednak jest 72MHz, wtedy wszystko by się zgodziło, niestety w tym momencie nie mam możliwości tego sprawdzić. Trochę się już pogubiłem :/

Link do komentarza
Share on other sites

O maksymalnej częstotliwości 64MHz przy wykorzystaniu HSI znajdziemy informację w Reference Manual-u. Co do ustawień, to jest jak napisałeś - dzielimy HSI przez 2, mnożymy przez 16 i dostajemy oczekiwaną wartość 64MHz.

Plik system_stm32f10x.c zawiera błąd - zmienna SystemCoreClock powinna być inicjalizowana wartością 64000000 zamiast 72000000. W mojej wersji nie ma funkcji SetSysClockTo72, jest natomiast SystemCoreClockUpdate - która jednak nie jest używana.

Najłatwiej byłoby poprawić plik system_stm32f10x.c, może wypadałoby zgłosić błąd do OpenSTM32.

Taktowanie 72MHz jest oczywiście możliwe - są na to co najmniej dwa sposoby. Pierwszy to przylutwanie kwarca 8Mhz - na płytce jest na niego miejsce. Druga opcja to modyfikacja zworek (też przez lutowanie) i wykorzystanie sygnału z programatora.

Pisząc kurs nie chcieliśmy wymagać modyfikacji płytki Nucleo, dlatego zdecydowaliśmy się na wykorzystanie wbudowanego generatora HSI. Nie jest to rozwiązanie idealne. Jeśli ktoś chce i potrafi zmodyfikować płytkę - jak najbardziej można zastosować inne źródło sygnału zegarowego. Jednak w kursie przyjmujemy opcję minimum, którą każdy (nawet po wlutowaniu kwarcu) może wykorzystać - czyli 64MHz i wbudowany generator.

[ Dodano: 15-10-2015, 21:19 ]

Płytka Nucleo występuje w (co najmniej) dwóch wersjach. Starsza, czyli 01 nie ma domyślnie podłączonego sygnału zegarowego z programatora.

Link do komentarza
Share on other sites

Wydaje mi się że rozumiem, choć dalej nie rozwiązałem swojego pierwszego "problemu" 😅

W pliku system_stm32f10x.c nie jestem w stanie znaleźć funkcji która odpowiada za zmianę mnożnika na 16 i ustawienie HSI jako źródła dla PLL. Jedyne o udało mi się znaleźc to informacje że w przypadku nieuruchomienia HSE układ będzie korzystał z wewnętrznego generatora. Z tego powinno wynikać ??? że układ będzie korzystał z pierwotnych 8MHz. Chyba że automatycznie mnożnik just ustawiany na 16, ale to odpowiada 1111 w PLLMULL w CFGR który natomiast jest zerowany w SystemInit a nie widzę żadnego miejsca gdzie potem byłaby ta wartość zmieniana. Więc dalej pozostaje pytanie dlaczego 64 a nie 8 MHz?

Chyba że ja mam jakąś dziwną wersję całej biblioteki 😖

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

Nie wiem, jaką masz wersję biblioteki, ale patrząc po nazwach funkcji używamy innych wersji. Plik który pobiera OpenSTM32 ma następujący początek:

/**
 ******************************************************************************
 * @file    system_stm32f10x.c
 * @author  MCD Application Team
 * @version V1.2.0
 * @date    11-April-2014
 * @brief   CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.

Jak chodzi o konfigurację, to jest w nim deklaracja PLL_SOURCE_HSI:

#define PLL_SOURCE_HSI          // HSI (~8 MHz) used to clock the PLL, and the PLL is used as system clock source

A dalej w kodzie znajdziemy:

static void SetSysClock(void)
{
 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

#ifdef PLL_SOURCE_HSI  
 /* At this stage the HSI is already enabled */

 /*  PLL configuration: PLLCLK = HSI/2 * 16 = 64 MHz */
 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL));
 RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL16);

#else /* PLL_SOURCE_HSE_BYPASS or PLL_SOURCE_HSE */  

Czyli dokładnie to co powinno być. Mam wrażenie, że używasz wersji dla STM32-Discovery, w niej chyba były funkcje o których pisałeś. I domyślną konfiguracją jest wtedy kwarc 8MHz.

Link do komentarza
Share on other sites

A więc rozwiązałeś moją sprawę 😉

Rzeczywiście w mojej bibliotece tych funkcji nie było. Problem był w tym że przy tworzeniu projektu wybrałem po prostu uC STM32F103RB a nie płytkę nucleo. Kiedy stworzyłem nowy projekt wszystko było tak jak opisujesz.

Dziękuję za szybką i konkretną pomoc!

Link do komentarza
Share on other sites

Chcę się upewnić, że dobrze rozumiem odnośnie przerwań.

Numer linii EXTI musi być zgodny z numerem pinu, tak?

np.

GPIO_Pin_3 -> EXTI_Line5

GPIO_Pin_10 -> EXTI_Line10 itd.

I w takim razie nie da się pod różne linie EXTI ustawić pinów o takim samym numerze z różnych portów, tak?

Link do komentarza
Share on other sites

STM32F103 ma co najmniej nietypowe (dziwne) rozwiązanie jak chodzi o wejścia EXTI. Niby można obsługiwać przerwanie na każdym pinie, ale jak słusznie zauważyłeś, nie można jednocześnie obsługiwać przerwań od pinów o tych samych numerach na różnych portach.

W Reference Manual-u znajdziemy ładny obrazek:

Jak widać linie są podłączone przez multiplekser i dlatego mamy takie zachowanie.

Link do komentarza
Share on other sites

Na STM32F411RE jest to samo.

Chwilę zajęło mi znalezienie przyczyny nie działania przerwania.

Numer i port pinu (B5) zmieniłem pod swoją płytkę, ale zostawiłem EXTI_Line13.

Zmyliło mnie to, że w trybie debugowania przerwanie działało, a w trybie normalnej pracy już nie. Potem rozkminiając kod linijka po linijce zauważyłem, że jedyne powiązanie pomiędzy EXTI a pinem to SYSCFG_EXTILineConfig w którym nie podaje się, którego EXTI to ma dotyczyć.

Ten reference manual to od konkretnego modelu uC czy od biblioteki? Nie mogę się jeszcze połapać w dokumentacji ST.

BTW. Dzięki za kurs.

Link do komentarza
Share on other sites

Link do tej dokumentacji był części #3: http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/CD00171190.pdf

Tytuł: "RM0008

Reference manual

STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx advanced ARM-based 32-bit MCUs"

Punkt 10.2.5 - "External interrupt/event line mapping".

Ogólnie jest to moim zdaniem najlepsza dokumentacja mikrokontrolera. Działa na poziomie rejestrów, ale biblioteka StdPeriph jest tak niskopoziomowa, że nie stanowi to problemu (najwyżej można pomijać podrozdziały opisujące kolejne bity każdego rejestru). Opisywane moduły peryferyjne działają identycznie, niezależnie czy konfigurowane bit po bicie, czy za pomocą funkcji biblioteki.

Wersja RM dla STM32F411RE jest tutaj: http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00119316.pdf

Nawet numeracja rozdziałów się zgadza jak chodzi o przerwania, podpunkt 10.2.5 opisuje to samo jak w przypadku STM32F103

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

Spotkał się ktoś z takim problemem ?

pojawia się podczas próby uruchomienia pierwszego programu do sterowania diodą led (Dokładniej koniec etapu 3), kompilacja przebiega bez problemu, dopiero uruchomienie powoduje błąd...

Zdjęcie okna programu, może tu coś jest nie tak 🙂

Po otwarciu nowego projektu, usunąłem folder Utility tak jak w kursie #3, dopiero później zacząłem działać 🙂 Ktoś potrafi pomóc 🙂?

Link do komentarza
Share on other sites

Po tym opisie ciężko cokolwiek podpowiedzieć - Eclipse wyraźnie pisze, jest błąd. Może byłoby łatwiej gdybyś coś więcej napisał. Np. jakiej płytki używasz, jak utworzyłeś projekt, czy wg. instrukcji kursu. Poza tym jak pojawia się komunikat o błędzie (pierwszy screenshot), warto nacisnąć przycisk "Details". Może wtedy czegoś więcej uda się dowiedzieć.

Link do komentarza
Share on other sites

Po rozwinięciu "Details"

Co do dokładniejszych informacji:

Płytka Nucleo STM32F103 - Płytka z kursu zestaw rozszerzony (Botland)

Całość wykonuję krok po kroku tak jak w kursie. Próbowałem już różnych opcji, z zapisywaniem projektu przed kompilacją, bez zapisywania, opcji run configurations, run->debug, nic nie działa. Każdą z opcji robiłem przy nowym projekcie żeby poprzednie działania nie miały wpływu, chociaż sam nie wiem czy to mogło coś zmienić. Jeśli brakuje jeszcze jakiś informacji to pisz śmiało, zaraz dodam.

Link do komentarza
Share on other sites

Dokładnie tak, dlatego to mnie dziwi, że do tego momentu wszystko działało jak w opisie kursu. Początkowo myślałem, że może ja coś źle przepisałem/nie widzę swojego błędu więc skopiowałem cały kod z kursu i najzwyczajniej wkleiłem do siebie ale dalej to samo ;/

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.