w tym szczegółowym artykule dowiesz się, jak tworzyć wbudowane oprogramowanie układowe dla 32-bitowych mikrokontrolerów STM32 Cortex-m przy użyciu różnych narzędzi programistycznych.
seria STM32 to jedne z najpopularniejszych mikrokontrolerów stosowanych w szerokiej gamie produktów. Mają również doskonałą bazę wsparcia z wielu forów programistycznych mikrokontrolerów.
ta rodzina mikrokontrolerów firmy STMicroelectronics oparta jest na 32-bitowym rdzeniu procesora ARM Cortex-M.
mikrokontrolery STM32 oferują dużą liczbę szeregowych i równoległych peryferii komunikacyjnych, które mogą być połączone z wszelkiego rodzaju komponentami elektronicznymi, w tym czujnikami, wyświetlaczami, kamerami, silnikami itp. Wszystkie warianty STM32 są wyposażone w wewnętrzną pamięć Flash i RAM.
zakres wydajności dostępny w STM32 jest dość rozległy. Niektóre z najbardziej podstawowych wariantów obejmują pod-serie STM32F0 i stm32f1, które zaczynają się z częstotliwością zegara tylko 24 MHz i są dostępne w pakietach z zaledwie 16 pinami.
przy innych ekstremalnych osiągach, stm32h7 działa z częstotliwością do 400 MHz i jest dostępny w pakietach z aż 240 pinami.
bardziej zaawansowane modele są dostępne z jednostkami Zmiennoprzecinkowymi (FPU) dla aplikacji o poważnych wymaganiach przetwarzania numerycznego. Te bardziej zaawansowane modele rozmywają linię między mikrokontrolerem a mikroprocesorem.
wreszcie, pod-seria STM32L została zaprojektowana specjalnie do zastosowań przenośnych o małej mocy, działających z małej baterii.
narzędzia programistyczne
narzędzia programistyczne są wymagane do opracowania kodu, zaprogramowania mikrokontrolera i przetestowania/debugowania kodu. Do narzędzi programistycznych należą:
- kompilator
- Debugger
- In-Circuit Serial Programmer (ICSP)
Programowanie STM32 za pomocą In-Circuit-Serial-Programmer (ICSP).
istnieje kilka narzędzi programistycznych dostępnych do tworzenia kodu na mikrokontrolerach STM32. Narzędzia programowe są dostępne jako zintegrowane Środowiska programistyczne (IDE), które łączy wszystkie niezbędne narzędzia w zintegrowane środowisko.
dwa popularne pakiety programistyczne obejmują:
- Keil MDK ARM (UVISON5 IDE) – MDK ARM IDE jest bardzo stabilnym środowiskiem programistycznym, które można pobrać za darmo. Umożliwia tworzenie kodu do wielkości programu 32 KB. Do tworzenia większych programów należy zakupić tutaj licencjonowaną wersję.
- CoIDE-darmowy łańcuch narzędzi, który bazuje na skróconej wersji Eclipse IDE zintegrowanej wraz z wbudowaną wersją ARM wolnego kompilatora GCC.
istnieje również kilka innych ID, które są dostępne do użytku z mikrokontrolerami STM32. Jednak ten artykuł skupia się na rozwijaniu i flashowaniu programu przy użyciu bardzo popularnego Keil MDK ARM UVISION5 IDE.
oprócz narzędzi programowych, do programowania i testowania kodu na rzeczywistym mikrokontrolerze wymagany jest programator szeregowy (In-Circuit Serial Programmer, ICSP). ICSP jest wymagany do podłączenia mikrokontrolera do narzędzi programowych komputera za pośrednictwem portu USB.
mikrokontrolery ARM Cortex-m obsługują dwa protokoły programowania: JTAG (nazwany przez Stowarzyszenie przemysłu elektronicznego Joint Test Action Group) i Serial Wire Debug (SWD).
dostępnych jest kilka programistów ICSP obsługujących te protokoły, w tym:
- Keil u-Link 2
- Segger J-Link
- ST-Link
Tworzenie pierwszej aplikacji
zawsze najłatwiej jest zacząć od łatwo dostępnego podstawowego frameworka kodu. Następnie dodaj kod, który jest wymagany dla konkretnej aplikacji i modelu mikrokontrolera.
na szczęście STMicroelectronics dostarcza bardzo przydatne narzędzie graficzne o nazwie STM32CubeMx, które pomaga w tworzeniu podstawowego projektu aplikacji dla dowolnego mikrokontrolera STM32. Może być również używany do konfiguracji urządzeń peryferyjnych na multipleksowanych pinach mikrokontrolera.
narzędzie STM32CubeMX można pobrać stąd. STM32Cube jest wyposażony w obszerny zestaw sterowników dla wszystkich typów urządzeń peryferyjnych i obsługuje opcjonalny FreeRTOS (darmowy system operacyjny czasu rzeczywistego) wstępnie zintegrowany z kodem.
w poniższej sekcji szczegółowo opisano, jak stworzyć prostą aplikację UART dla mikrokontrolera STM32F030, która będzie odtwarzać wszystko, co jest wpisane w oknie terminala.
- Zainstaluj oprogramowanie STM32CubeMX.
- Uruchom aplikację i wybierz nowy projekt. Następnie otworzy okno wyboru MCU, jak pokazano poniżej.
- Kliknij dwukrotnie, aby wybrać model mikrokontrolera. W tym przypadku używamy stm32f030k6. Następnie przechodzi do strony wyprowadzenia wybranego mikrokontrolera.
STM32F030K6 to rdzeń ARM Cortex-M0 z 32KB pamięci Flash i 4KB pamięci RAM. Przykładowy kod umożliwia UART, który używa pinów PA9 i PA10 do odbierania i przesyłania danych szeregowych, jak pokazano poniżej za pomocą zielonych pinów.
skonfiguruj ustawienia UART w zakładce Konfiguracja i wybierz Ustawienia UART, jak pokazano poniżej. Włącz opcję globalnego przerwania nvic na karcie Ustawienia Nvic.
następnie przejdź do projektu–>Ustawienia, aby dodać nową nazwę projektu i wybrać IDE łańcucha narzędzi, które ma być używane. W tym przykładzie Ustaw nazwę projektu na „UARTEcho” i wybierz Keil-MDK5 IDE dla rozwoju projektu.
na koniec Wygeneruj kod projektu klikając Project- > Wygeneruj kod.
Budowanie i flashowanie kodu
teraz otwórz wygenerowany plik projektu MDK-ARM UARTEcho\MDK-ARM\UARTECHO.uprojx.
Ten program do tej pory tylko inicjalizuje UART i zatrzymuje się w nieskończonej pętli.
należy pamiętać, że STM32Cube generuje bloki /* kod użytkownika BEGIN X */ i /* Kod użytkownika END X */ comment, aby zaimplementować kod specyficzny dla użytkownika. Kod użytkownika musi być zapisany w tych blokach komentarzy. Za każdym razem, gdy kod jest ponownie generowany ze zmodyfikowanymi konfiguracjami, narzędzie STMCube zachowuje kod użytkownika w tych blokach Komentarzy Użytkownika.
następnie zdefiniuj zmienną globalną, aby otrzymać bajt z UART w głównej.c plik źródłowy:
/* USER CODE BEGIN PV *//* Private variables ———————————————————*/static uint8_t recv_data;/* USER CODE END PV */
po całym kodzie inicjalizacyjnym włącz sterownik, aby otrzymał 1 bajt. Poniższa funkcja włącza bit przerwania RXNE.
/* USER CODE BEGIN 2 */HAL_UART_Receive_IT(&huart1, &recv_data, 1);/* USER CODE END 2 */
teraz Dodaj funkcję zwrotną do obsługi przerwania odbioru i transmisji odebranego bajtu.
/* USER CODE BEGIN 0 */void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){HAL_UART_Transmit(huart, huart->pRxBuffPtr, 1, 1000);}/* USER CODE END 0 */
na koniec musimy skompilować kod i flashować go (pobrać) do mikrokontrolera.
Po zainstalowaniu Keil MDK ARM IDE dostępne są sterowniki dla ST-LINK V2, J-Link i Ulink2. Debugger ST-Link zostanie wybrany domyślnie. Przejdź do projektów->opcje dla Target i w zakładce Debug wybierz używany programator ICSP.
Flashuj kod wybierając Flash- > Pobierz.
mikrokontroler będzie teraz echo wszystkich danych odebranych przez UART. Można go podłączyć do komputera za pomocą konwertera USB-to-Serial. Na komputerze otwórz port COM za pomocą aplikacji terminalowej za pomocą ustawień 115200-8-N-1. Teraz wszystko, co zostanie wysłane z terminala, wróci echem przez mikrokontroler.
System przerwań
System przerwań STM32 oparty jest na rdzeniu ARM Cortex M nvic peripheral. MCU STM32 obsługują wiele maskowalnych kanałów przerwań, oprócz 16 kanałów przerwań rdzenia ARM.
na przykład seria MCU STM32F0 obsługuje 32 maskowalne przerwania. Tabela wyjątków i wektorów przerwań dla tej rodziny MCU jest podana w poniższej tabeli.
Interrupt | Description | Vector Address |
– | Reserved | 0x00000000 |
Reset | Reset | 0x00000004 |
NMI | Non maskable interrupt. The RCC clock security system (CSS) is linked to the NMI vector | 0x00000008 |
HardFault | All class of faults | 0x0000000C |
SVCall | System service call via SWI Instruction | 0x0000002C |
PendSV | Pendable request for system service | 0x00000038 |
SysTick | System tick timer | 0x0000003C |
WWDG | Window watchdog interrupt | 0x00000040 |
PVD_VDDIO2 | PVD and VDDIO2 supply comparator interrupt (combined with EXTI lines 16 and 31) | 0x00000044 |
RTC | RTC interrupts (combined EXTI lines 17, 19 and 20) | 0x00000048 |
Flash | Flash global interrupt | 0x0000004C |
RCC_CRS | RCC and CRS global interrupts | 0x00000050 |
EXTI0_1 | EXTI line interrupts | 0x00000054 |
EXTI2_3 | EXTI line interrupts | 0x00000058 |
EXTI4_15 | EXTI line interrupts | 0x0000005C |
TSC | Touch sensing interrupt | 0x00000060 |
DMA_CH1 | DMA channel 1 interrupt | 0x00000064 |
DMA_CH2_3 DMA2_CH1_2 |
DMA channels 2 and 3 interrupts DMA2 channel1 and 2 interrupts |
0x00000068 |
DMA_CH4_5_6_7 DMA2_CH3_4_5 |
DMA channel 4,5,6 and 7 interrupts DMA2 channel 3, 4, and 5 interrupts |
0x0000006C |
ADC_COMP | ADC and COMP interrupts (Combined EXTI lines 21 and 22) | 0x00000070 |
TIM1_BRK_UP_TRG_COM | TIM1 break, update, trigger and commutation interrupts | 0x00000074 |
TIM1_CC | TIM1 capture compare interrupt | 0x00000078 |
TIM2 | TIM2 global interrupt | 0x0000007C |
TIM3 | TIM3 global interrupt | 0x00000080 |
TIM6_DAC | TIM6 global interrupt and DAC underrun interrupt | 0x00000084 |
TIM7 | TIM7 global interrupt | 0x00000088 |
TIM14 | TIM14 global interrupt | 0x0000008C |
TIM15 | TIM15 global interrupt | 0x00000090 |
TIM16 | TIM16 global interrupt | 0x00000094 |
TIM17 | TIM17 global interrupt | 0x00000098 |
I2C1 | I2C1 global interrupt (combined with EXTI line 23) | 0x0000009C |
I2C2 | I2C2 global interrupt | 0x000000A0 |
SPI1 | SPI1 global interrupt | 0x000000A4 |
SPI2 | SPI2 global interrupt | 0x000000A8 |
USART1 | USART1 global interrupt (combined with EXTI line 25) | 0x000000AC |
UART2 | USART2 global interrupt (combined with EXTI line 26) | 0x000000B0 |
USART3_4_5_6_7_ 8 | USART3, USART4, USART5, USART6, USART7, USART8 global interrupts (combined with EXTI line 28) | 0x000000B4 |
CEC_CAN | CEC and CAN global interrupts (combined with EXTI line 27 | 0x000000B8 |
USB | USB global interrupt (combined with EXTI line 18) | 0x000000BC |
Extended Kontroler przerwań i zdarzeń (EXTI)
MCU STM32 mają rozszerzony kontroler przerwań i zdarzeń, który zarządza zewnętrznymi i wewnętrznymi asynchronicznymi zdarzeniami/przerwaniami i generuje żądanie zdarzenia do kontrolera CPU/przerwań oraz żądanie budzenia do Menedżera zasilania.
każda z jednej lub więcej linii EXTI jest odwzorowana na jeden z wektorów przerwania NVIC.
dla zewnętrznych linii przerwań, aby wygenerować przerwanie, linia przerwań powinna być skonfigurowana i włączona. Odbywa się to poprzez zaprogramowanie dwóch rejestrów wyzwalania z żądaną detekcją krawędzi i włączenie żądania przerwania przez zapisanie '1′ do odpowiedniego bitu w rejestrze maski przerwań.
zewnętrzne przerwanie i mapowanie GPIO
każdy z GPIO dostępnych w systemie może być skonfigurowany do generowania przerwania. Ale każda z linii przerwań EXTI jest odwzorowana na wiele pinów GPIO. Na przykład, PIO0 na wszystkich dostępnych portów GPIO (A,B, C, itp.) zostanie zmapowany do linii EXTI0. PIO1 dla wszystkich portów będzie mapowany do linii EXTI1 i tak dalej.
niektóre z linii EXTI są połączone w jeden wektor NVIC. Na przykład, EXTI4_15 jest mapowany na pojedynczy adres wektorowy, więc będzie jedna procedura przerwania dla wszystkich przerwań z PIO4 do PIO15. Ale źródło przerwania może być zidentyfikowane przez odczyt rejestru przerwania oczekującego.
jedną ważną rzeczą, którą należy wziąć pod uwagę podczas projektowania systemu wykorzystującego MCU STM32, jest wybór pinów GPIO dla przerwań. MCU może mieć więcej niż 16 GPIOs dostępnych na urządzeniu, ale dostępnych jest tylko 16 zewnętrznych linii przerwań.
na przykład, EXTI_0 może być zmapowany do PA0 lub PB0, ale nie do obu. Tak więc przy wyborze pinów dla zewnętrznych przerwań powinny być tak dobrane, aby mogły być jednoznacznie odwzorowane na jedną z linii EXTI.
poniższa sekcja opisuje jak skonfigurować przerwanie za pomocą kostki STM32.
wybierz zakładkę Konfiguracja i wybierz moduł sprzętowy, dla którego ma być skonfigurowane przerwanie. Zostanie otwarte okno konfiguracji modułu.
następnie wybierz kartę Ustawienia NVIC i włącz globalne przerwanie.
kod włączający przerwanie dla modułu zostanie wygenerowany w stm32f0xx_hal_msp.c w funkcji HAL_<modułu>_mspinit (…).
/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);
kod wygenerowany przez kostkę STM32 będzie miał implementację IRQ_Handler wszystkich przerwań. Po włączeniu przerwania kod zostanie dołączony do aplikacji.
Zwykle wygenerowany kod obsługuje już IRQ i czyści flagę, która wygenerowała przerwanie. Następnie wywołuje wywołanie zwrotne aplikacji, które odpowiada zdarzeniu, które wygenerowało przerwanie dla modułu.
HAL STM32 (Hardware Abstraction Layer) implementuje wywołanie zwrotne dla każdego typu zdarzeń w każdym module jako część sterownika. W tym przykładzie RX Transfer Complete callback powinien zostać skopiowany z stm32f0xx_hal_uart.plik C.
funkcje zwrotne wewnątrz sterownika będą zaimplementowane z atrybutem __weak linker. Użytkownik musi zaimplementować kopię niezbędnej funkcji zwrotnej, usuwając atrybut _ _ weak w jednym z plików aplikacji, a następnie zapisując określoną obsługę wymaganą w tej funkcji.
/*** @brief Rx Transfer completed callback.* @param huart UART handle.* @retval None*/__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){/* Prevent unused argument(s) compilation warning */UNUSED(huart);/* NOTE : This function should not be modified, when the callback is needed,the HAL_UART_RxCpltCallback can be implemented in the user file.*/}
wnioski
Ten poradnik jest wprowadzeniem do pisania aplikacji, która współpracuje z rodziną mikrokontrolerów STM32. Istnieje kilka innych metod pisania aplikacji, ale omawiany STM32Cube jest łatwą i intuicyjną metodą na rozpoczęcie pracy.
To narzędzie upraszcza inicjalizację urządzeń peryferyjnych mikrokontrolera. Poprawia to również łatwość obsługi kodu, zwłaszcza gdy występują zmiany sprzętowe, które wymagają ponownego mapowania sygnałów na różne piny.
Kolejną zaletą korzystania z narzędzia STM32Cube jest to, że generuje on raport konfiguracji użytkownika dla mikrokontrolera. W tym raporcie szczegółowo opisano drzewo zegarów, mapowanie pinów i konfigurację modułów sprzętowych, które są bardzo przydatne.
istnieje również kilka innych bibliotek kodu i przykładowe programy dostępne dla wszystkich wariantów STM32. Wsparcie dla kilku IDE jest również włączone.
Jeśli twój projekt wymaga zaawansowanego 32-bitowego mikrokontrolera, to Gorąco polecam serię STM32. Nie tylko są potężne i popularne, ale mikrokontrolery STM32 są również dość przystępne cenowo.
Potrzebujesz więcej szkoleń z programowania mikrokontrolerów STM32? Jeśli tak, oto bardziej dogłębny kurs wprowadzający, który powinieneś sprawdzić.
Ten artykuł został napisany przez Mohan Kashivasi z Vithamas Technologies. Jest również jednym z ekspertów, którzy pomogą Ci z produktem w Akademii sprzętu.
na koniec nie zapomnij pobrać darmowego pliku PDF: Najlepszy przewodnik do opracowania i sprzedaży nowego produktu sprzętu elektronicznego. Będziesz także otrzymywać mój cotygodniowy newsletter, w którym udostępniam treści premium niedostępne na moim blogu.
inne treści, które mogą ci się spodobać:
- Wprowadzenie do Stm32cubeide dla mikrokontrolerów STM32
- Jak wybrać mikrokontroler dla nowego produktu
- używanie Arduino jako wbudowanej Platformy Programistycznej
- przegląd arkusza danych: Entry-Level STM32 Cortex-M0 Microcontroller (Blog + Video)
- Introduction to the Ultra High-Performance STM32H7 32-bit Microcontroller