Przez moje szkolenia z programowania STM32 przeszły już tysiące osób. W ostatnim czasie coraz częściej widzę zamieszanie związane z różnymi sposobami tworzenia projektów w STM32CubeIDE i STM32CubeMX. Dla osób początkujących bywa to szczególnie utrudniające start.
W tym cyklu pokażę trzy najważniejsze metody rozpoczęcia pracy:
- Start from MCU – od gołego mikrokontrolera
- Start from Board – od płytki Nucleo
- Model z CubeIDE v2.0 – zewnętrzny CubeMX + import projektu
Całość opieram na płytce NUCLEO-G474RE oraz wersjach:
- STM32CubeIDE v1.19.0
- STM32CubeIDE v2.0.0
- STM32CubeMX v6.16.1
Dlaczego to ważne?
Narzędzia STM32CubeIDE i STM32CubeMX oferują kilka sposobów rozpoczęcia pracy z projektem: od wyboru mikrokontrolera, od konkretnej płytki rozwojowej, aż po workflow z wykorzystaniem zewnętrznego CubeMX i importu projektu do IDE.
Rozwój ekosystemu STM32 wprowadził dodatkowe elementy, takie jak Board Support Package (BSP) oraz różnice w integracji CubeMX między kolejnymi wersjami STM32CubeIDE.
W tym przewodniku pokazuję trzy najczęściej stosowane metody startu, tworząc w każdej z nich prosty projekt (mrugający LED) i wskazując różnice w strukturze projektu, konfiguracji oraz sposobie pracy.
Różnice CubeIDE v1.19.0 vs v2.0.0
W STM32CubeIDE v1.x konfigurator STM32CubeMX jest zintegrowany bezpośrednio w środowisku IDE: otwarcie pliku .ioc uruchamia CubeMX w tym samym oknie, a generowanie kodu odbywa się bez opuszczania IDE.
W STM32CubeIDE v2.0 model pracy został zmieniony: STM32CubeMX jest instalowany i uruchamiany jako osobne narzędzie, a integracja odbywa się poprzez pliki .ioc oraz import projektu do IDE. Takie podejście ułatwia niezależne aktualizowanie konfiguratora oraz skalowanie wsparcia dla nowych rodzin mikrokontrolerów, natomiast wymaga zwrócenia większej uwagi na skojarzenia plików i spójność wersji narzędzi w środowisku pracy.
Kluczowe różnice:
- Integracja: v1.x = wszystko w jednym oknie; v2.0 = osobny CubeMX +import do IDE.
- Wsparcie: v1.19.0 bez nowych MCU; v2.0 skalowalny pod przyszłe układy.
- Workflow: v1.x prostszy na start; v2.0 wymaga zarządzania powiązaniami plików i importowania projektu z CubeMX.
Pierwszy krok w STM32CubeIDE v1.19.0 – wspólne repozytorium
W pierwszej kolejności warto ustalić wspólną ścieżkę dla pakietów HAL używanych przez wszystkie wersje STM32CubeIDE oraz STM32CubeMX, szczególnie jeśli pracujemy równolegle na kilku instalacjach narzędzi.
Pozwala to uniknąć wielokrotnego pobierania tych samych pakietów firmware, które w przypadku bardziej rozbudowanych rodzin mikrokontrolerów mogą zajmować nawet ponad 1 GB.
STM32CubeMX pobiera pakiety jako archiwa ZIP, a następnie je rozpakowuje, nie usuwając plików źródłowych. W razie potrzeby można ręcznie usunąć archiwa, aby zwolnić miejsce.
Gdzie znajdziemy opcje podania ścieżki repozytorium HAL w CubeIDE?
Window > Preferences > STM32Cube > Firmware Update

Tworzenie projektu od zera – opcja “Start from MCU”
Najbardziej podstawowym sposobem rozpoczęcia pracy w STM32CubeIDE jest utworzenie projektu bezpośrednio na podstawie wybranego mikrokontrolera, czyli opcja „Start from MCU”.
W tym modelu konfiguracja rozpoczyna się od czystego układu, bez ustawień narzuconych przez konkretną płytkę. Użytkownik sam definiuje piny, peryferia oraz zegary systemowe, co daje pełną kontrolę nad strukturą projektu i pozwala lepiej zrozumieć proces inicjalizacji mikrokontrolera.
Jak przejść całą ścieżkę?

Przy pierwszym uruchomieniu prawdopodobnie pobierze Ci się dodatkowy selektor układów STM32.

W pierwszej kolejności wybierzemy opcję tworzenia projektu tzw. gołego, czyli sam mikrokontroler. Na NUCLEO-G474RE mamy STM32G474RET6. Możemy wpisać taki w wyszukiwarkę układów


Zaznaczamy interesujący nas układ i przechodzimy dalej.
Musimy nadać nazwę projektu. Wybieramy również opcję projektowe. W zasadzie opcje domyślnie zaznaczone będą dla nas dobre. Co w nich mamy?
- Będziemy chcieli pisać w języku C.
- Wynikiem naszej kompilacji ma być wykonywalna na mikrokontrolerze binarka.
- Typ projketu jaki generujemy będzie dostosowany do STM32CubeIDE w którym to tworzymy projekt.
Po wszystkim klikamy Finish.

Po chwili oczekiwania rozpoczyna się pobieranie paczek HAL do wskazanego przez nas mikrokontrolera, a konkretnie to dla całej rodziny STM32G4.

Po pobraniu paczki i zapoznaniu się z licencją, akceptujemy ją i od razu rozpoczyna się rozpakowywanie bibliotek HAL.


Możesz zauważyć, że dla rodziny STM32G4 pobierane są dwie wersje pakietu firmware, na przykład v1.6.0 oraz v1.6.1. Wynika to z modelu wersjonowania STM32Cube.
Instalowana jest wersja bazowa Major.Minor (np. 1.6.0), zawierająca biblioteki HAL, LL, middleware, przykłady i dokumentację, a następnie oddzielnie dogrywana jest poprawka typu Patch (np. 1.6.1). Pozwala to wprowadzać poprawki bez ponownego pobierania całego pakietu.
W repozytorium firmware znajdują się więc zarówno archiwa pobranych pakietów (ZIP), jak i rozpakowane katalogi z pełną strukturą bibliotek dla danej rodziny mikrokontrolerów.

W repozytorium znajdują się dwie pobrane paczki firmware (wersja bazowa i poprawka typu Patch) oraz katalog z rozpakowaną strukturą STM32Cube dla rodziny G4. Wszystkie elementy są oznaczone numerami wersji, co ułatwia identyfikację zainstalowanego pakietu.
Rozpakowany katalog zawiera nie tylko biblioteki HAL i LL, ale również middleware (np. USB, stosy komunikacyjne, CMSIS), dokumentację oraz komplet przykładów dla danej rodziny mikrokontrolerów.
Szczególnie istotny jest katalog Projects, w którym znajdują się przykłady dla płytek ewaluacyjnych, w tym dla NUCLEO-G474RE. Obejmują one zarówno podstawowe konfiguracje peryferiów (GPIO, UART, ADC, TIM, PWM), jak i bardziej zaawansowane zastosowania.
Przegląd tych projektów pozwala szybko uruchomić wybrane peryferium oraz zobaczyć rekomendowaną strukturę i sposób inicjalizacji. Repozytorium firmware stanowi więc nie tylko źródło bibliotek, ale także praktyczną bazę referencyjną.

W praktyce przykładowe projekty dla nowszych rodzin STM32 są zazwyczaj zgodne z aktualnymi wersjami pakietów firmware i narzędzi, ponieważ rozwijane są równolegle z daną rodziną układów.
Nawet jeśli wymagają drobnych dostosowań (np. regeneracji kodu w nowszym CubeMX), koncepcja konfiguracji peryferiów i sposób inicjalizacji pozostają aktualne. Projekty referencyjne stanowią więc dobry punkt wyjścia do pierwszego uruchomienia wybranego modułu.
Po wygenerowaniu własnego projektu w STM32CubeIDE v1.x przechodzimy bezpośrednio do wbudowanego konfiguratora STM32CubeMX. W serii 1.x konfigurator i edytor kodu działają w jednej aplikacji — plik .ioc otwiera się w IDE, a generowanie kodu nie wymaga uruchamiania dodatkowego narzędzia.

W tym artykule skonfigurujemy sobie LED LD2, który znajduje się na płytce Nucleo, oraz LPUART1, który jest poprowadzony do wbudowanego w płytkę programatora ST-Link, a następnie wyprowadzony przez USB do naszego komputera.
Stworzyliśmy projekt “goły” więc wszystko musimy zrobić samodzielnie. W kolejnym rozdziale nieco sobie to ułatwimy tworząc projekt “Start from Board”. Na ile ułatwimy – to się okaże.
Nie będziemy wchodzić w szczegóły schematu płytki. Gdybyś chciał/chciała z niego skorzystać, to zapraszam Cię na stronę dedykowaną NUCLEO-G474RE. Tam w zakładce CAD są schematy do ostatnich rewizji płytek.
Dioda LD2 znajduje się na pinie PA5. Kliknij na rysunku mikrokontrolera dany pin i ustaw go na GPIO_Output.

Klikając PPM na tym pinie nadamy mu nazwę, która będzie widoczna w kodzie: LD2.



LPUART skonfigurujemy inną ścieżką. Z drzewa interfejsów po prawej stronie wybierz Connectivity > LPUART1 następnie Tryb Asynchronuous. Jest to klasyczny UART, który jest najczęściej wykorzystywany na mikrokontrolerach.

Ustawmy standardową prędkość 115200 Bits/s zachowując domyślnie ustawienie 8n1.

Na tym etapie nie będziemy wprowadzać dodatkowych zmian konfiguracyjnych. Ustawienia zegarów systemowych pozostawimy w
konfiguracji domyślnej, którą można przejrzeć w zakładce Clock Configuration.
W przypadku projektu tworzonego „Start from MCU” zegary są zazwyczaj ustawione w stanie odpowiadającym konfiguracji po resecie mikrokontrolera. Dla STM32G474 oznacza to pracę z wewnętrznym oscylatorem HSI 16 MHz, bez aktywnej pętli PLL i bez przełączania źródła taktowania na zewnętrzny rezonator.
Taka konfiguracja jest w pełni wystarczająca do uruchomienia podstawowych peryferiów, takich jak GPIO czy UART w standardowych prędkościach transmisji. Pozostawienie zegarów w stanie domyślnym upraszcza pierwszy projekt i pozwala skupić się na strukturze generowanego kodu oraz sposobie inicjalizacji peryferiów, bez wchodzenia na tym etapie w szczegóły związane z konfiguracją systemu taktowania.

Taka konfiguracja jest wystarczająca do pierwszych testów oraz uruchomienia podstawowych peryferiów, jednak w docelowych aplikacjach często konieczne jest skonfigurowanie PLL w celu uzyskania wyższej częstotliwości rdzenia lub precyzyjniejszego taktowania wybranych interfejsów.
Jest jeszcze jedna istotna rzecz i według mnie obowiązkowa. Musimy powiedzieć generatorowi projektu, aby rozdzielał pliki źródłowe i nagłówkowe dla poszczególnych peryferiów. Chodzi o to, żeby wszystko co ustawimy nie było wrzucone do pliku main.c, tylko do dedykowanych plików (np. gpio.c, usart.c).
Poprawia to strukturę projektu, ułatwia nawigację w kodzie oraz sprzyja utrzymaniu porządku w bardziej rozbudowanych aplikacjach. Włączenie tej opcji już na początku pracy pozwala zachować spójność architektury projektu wraz z jego rozwojem. Według mnie ta opcja powinna być w CubeMX zaznaczona domyślnie.

Tak przygotowany wstępnie projekt możemy wygenerować używając “trybika”. Zapisując Ctrl+S CubeMX powinien również wykryć zmiany i zaproponować samemu wygenerowanie projektu według zmian.

Po wygenerowaniu kodu projekt zostaje utworzony w wybranej lokalizacji, a jego struktura katalogów jest widoczna w widoku Project Explorer środowiska STM32CubeIDE.

Wygenerowana struktura obejmuje katalogi z plikami źródłowymi (Core/Src), plikami nagłówkowymi (Core/Inc), konfiguracją systemową oraz katalog Drivers, w którym znajdują się biblioteki HAL, CMSIS oraz pozostałe komponenty wymagane do kompilacji projektu.
Aby upewnić się, że projekt został poprawnie wygenerowany i że środowisko jest prawidłowo skonfigurowane, warto wykonać pierwszą kompilację.
W STM32CubeIDE można to zrobić, wybierając opcję Build Project lub używając skrótu klawiaturowego Ctrl+B. Jeśli proces zakończy się bez błędów, oznacza to, że struktura projektu oraz zależności zostały wygenerowane poprawnie i można przejść do dalszej pracy z kodem.

Wszystko działa jak należy. Aby zamigać diodą możemy skorzystać z nazwy którą nadaliśmy podczas konfigurowania pinu w GUI. Wystarczy nam naprawdę prosty przykład:

Podczas pracy z kodem generowanym przez STM32CubeMX należy zwrócić szczególną uwagę na sekcje oznaczone komentarzami USER CODE BEGIN oraz USER CODE END. To właśnie w tych obszarach przewidziane jest miejsce na kod użytkownika. Generator przy kolejnych modyfikacjach projektu nadpisuje wyłącznie fragmenty znajdujące się poza tymi znacznikami, pozostawiając
zawartość sekcji USER CODE bez zmian.
Umieszczenie własnego kodu poza wyznaczonymi obszarami może skutkować jego utratą przy ponownym wygenerowaniu projektu. Dlatego zaleca się konsekwentne korzystanie z tych sekcji, szczególnie w pliku main.c oraz w plikach inicjalizacyjnych peryferiów.
Po uzupełnieniu kodu aplikacyjnego ostatnim krokiem jest zaprogramowanie mikrokontrolera i uruchomienie aplikacji. W STM32CubeIDE można to zrobić, korzystając z przycisku Run (ikona „play”) lub konfiguracji debugowania, która domyślnie tworzona jest podczas pierwszego uruchomienia projektu.
Środowisko automatycznie wykorzysta podłączony programator/debugger STLINK i wgra wygenerowany plik wykonywalny do pamięci mikrokontrolera.

Przy pierwszym uruchomieniu projektu STM32CubeIDE może wyświetlić okno konfiguracji uruchamiania (Run/Debug Configuration). Środowisko automatycznie proponuje domyślną konfigurację opartą o podłączony interfejs ST-LINK oraz wygenerowany plik wykonywalny projektu.
W większości przypadków ustawienia te są poprawne i nie wymagają modyfikacji, dlatego można zaakceptować je bez wprowadzania zmian. Po zatwierdzeniu konfiguracji IDE rozpocznie proces programowania mikrokontrolera oraz, w zależności od wybranego trybu, przejdzie do sesji debugowania lub bezpośredniego uruchomienia aplikacji.

Jeśli tak jak ja – podłączyłeś nową płytkę lub taką, której bardzo dawno nie używałeś – to możesz zostać poproszony o aktualizację firmware programatora ST-Link na płytce Nucleo. Zalecam przeprowadzenie aktualizacji.


Po zakończeniu aktualizacji oprogramowania programatora można ponownie uruchomić projekt z poziomu STM32CubeIDE. W trakcie pierwszej sesji debugowania system operacyjny Windows może wyświetlić komunikat dotyczący zezwolenia na komunikację narzędzia debugującego (serwera GDB) przez zaporę systemową. W takim przypadku należy umożliwić dostęp, aby IDE mogło poprawnie nawiązać połączenie z mikrokontrolerem za pośrednictwem interfejsu ST-LINK.
Po poprawnym zaprogramowaniu i uruchomieniu aplikacji dioda LD2 na płytce NUCLEO-G474RE powinna rozpocząć cykliczne miganie zgodnie z zaimplementowaną logiką w pętli głównej. Oznacza to, że projekt został poprawnie skonfigurowany, skompilowany i wgrany do pamięci mikrokontrolera.
Opisany sposób pracy – rozpoczęcie projektu bezpośrednio od mikrokontrolera – stanowi najbardziej podstawowy i przejrzysty model konfiguracji. W kolejnych częściach przedstawione zostanie alternatywne podejście, czyli utworzenieprojektu w trybie „Start from Board”, a następnie omówione zostaną różnice wynikające z użycia STM32CubeIDE w wersji 2.0.
Mateusz Salamon
