Introduzione alla programmazione dei microcontrollori STM32 ARM Cortex-M a 32 bit

In questo articolo di approfondimento imparerete come sviluppare firmware embedded per i microcontrollori STM32 Cortex-M a 32 bit utilizzando i vari strumenti di sviluppo.

STM32 Microcontrollore

77 Azioni

La serie STM32 sono alcuni dei microcontrollori più popolari utilizzati in una vasta gamma di prodotti. Hanno anche un’eccellente base di supporto da più forum di sviluppo del microcontrollore.

Questa famiglia di microcontrollori di STMicroelectronics si basa sul core del processore ARM Cortex-M a 32 bit.

I microcontrollori STM32 offrono un gran numero di periferiche di comunicazione seriale e parallela che possono essere interfacciate con tutti i tipi di componenti elettronici tra cui sensori, display, telecamere, motori, ecc. Tutte le varianti STM32 sono dotate di memoria flash interna e RAM.

La gamma di prestazioni disponibili con STM32 è piuttosto ampia. Alcune delle varianti più basilari includono le sotto-serie STM32F0 e STM32F1 che iniziano con una frequenza di clock di soli 24 MHz e sono disponibili in pacchetti con un minimo di 16 pin.

All’altro estremo delle prestazioni, l’STM32H7 funziona fino a 400 MHz ed è disponibile in pacchetti con ben 240 pin.

I modelli più avanzati sono disponibili con unità in virgola mobile (FPU) per applicazioni con gravi esigenze di elaborazione numerica. Questi modelli più avanzati offuscano la linea tra un microcontrollore e un microprocessore.

Infine, la sub-serie STM32L è progettata specificamente per applicazioni portatili a bassa potenza in esecuzione da una piccola batteria.

Strumenti di sviluppo

Gli strumenti di sviluppo sono necessari per sviluppare il codice, programmare il microcontrollore e testare/eseguire il debug del codice. Gli strumenti di sviluppo includono:

  • Compilatore
  • Debugger
  • In-Circuit Serial Programmer (ICSP)
Programmazione STM32

Programmazione STM32 tramite il In-Circuit-Serial-Programmer (ICSP).

Sono disponibili diversi strumenti di sviluppo software per lo sviluppo del codice sui microcontrollori STM32. Gli strumenti software sono disponibili come ambienti di sviluppo integrati (IDE) che combina tutti gli strumenti necessari in un ambiente integrato.

Due pacchetti di sviluppo comuni includono:

  • Keil MDK ARM (uVison5 IDE) – Il MDK ARM IDE è un ambiente di sviluppo molto stabile che può essere scaricato gratuitamente. Consente lo sviluppo di codice fino a una dimensione del programma di 32 KB. Per lo sviluppo di programmi più grandi è necessario acquistare una versione con licenza qui.
  • CoIDE-Una catena di strumenti gratuiti che si basa su una versione ridotta dell’IDE Eclipse integrata insieme a una versione ARM incorporata del compilatore GCC gratuito.

Ci sono anche molti altri IDE che sono disponibili per l’uso con i microcontrollori STM32. Tuttavia, questo articolo si concentra sullo sviluppo e lampeggiante un programma utilizzando il molto popolare Keil MDK ARM uVision5 IDE.

Oltre agli strumenti software, è necessario un programmatore seriale in-Circuit (ICSP) per programmare e testare il codice sul microcontrollore effettivo. L’ICSP è necessario per interfacciare il microcontrollore agli strumenti software per PC tramite una porta USB.

I microcontrollori ARM Cortex-M supportano due protocolli di programmazione: JTAG (denominato dall’electronics industry association il Joint Test Action Group) e Serial Wire Debug (SWD).

Ci sono diversi programmatori ICSP disponibili che supportano questi protocolli, tra cui:

  • Keil U-Link 2
  • Segger J-Link
  • ST-Link

Sviluppare la prima applicazione

È sempre più semplice iniziare con un framework di codice di base facilmente disponibile. Quindi, aggiungere il codice richiesto per l’applicazione specifica e il modello di microcontrollore.

Fortunatamente, STMicroelectronics fornisce uno strumento grafico molto utile chiamato STM32CubeMx che aiuta a creare un progetto di applicazione di base per qualsiasi microcontrollore STM32 di vostra scelta. Può anche essere utilizzato per configurare le periferiche sui pin multiplex del microcontrollore.

Lo strumento STM32CubeMX può essere scaricato da qui. STM32Cube è dotato di un ampio set di driver per tutti i tipi di periferiche e supporto per un FreeRTOS opzionale (un sistema operativo in tempo reale gratuito) pre-integrato con il codice.

La sezione seguente descrive in dettaglio come creare una semplice applicazione UART per il microcontrollore STM32F030 che riecheggi tutto ciò che viene digitato su una finestra di terminale.

  • Installare il software STM32CubeMX.
  • Eseguire l’applicazione e selezionare Nuovo progetto. Aprirà quindi la finestra del selettore MCU come mostrato di seguito.
  • Fare doppio clic per selezionare il modello di microcontrollore utilizzato. In questo caso stiamo usando STM32F030K6. Quindi ti porta alla pagina di piedinatura per il microcontrollore selezionato.

screenshot sulla creazione di un nuovo progetto in STM32CubeMX

STM32F030K6 è un core ARM Cortex-M0 con 32KB di memoria Flash e 4KB di memoria RAM. Il codice di esempio abilita l’UART che utilizza i pin PA9 e PA10 per ricevere e trasmettere dati seriali come mostrato di seguito con i pin verdi.

screenshot che mostra la piedinatura per STM32F030K6 in STM32CubeMX

Configura le impostazioni UART nella scheda Configurazione e scegli le impostazioni UART come mostrato di seguito. Attivare l’opzione di interrupt globale NVIC nella scheda Impostazioni NVIC.

screenshot che mostra come configurare le impostazioni UART STM32CubeMX

Quindi, passare a Project–>Impostazioni per aggiungere il nuovo nome del progetto e selezionare l’IDE della catena di strumenti da utilizzare. Per questo esempio, impostare il nome del progetto su ‘UARTEcho’ e selezionare l’IDE Keil-MDK5 per lo sviluppo del progetto.

Infine, genera il codice del progetto facendo clic su Project- > Genera codice.

Costruire e lampeggiante il codice

Ora aprire il file di progetto MDK-ARM generato UARTEcho\MDK-ARM\UartEcho.uprojx.

Questo programma finora inizializza solo la periferica UART e si ferma in un ciclo infinito.

È importante notare che STM32Cube genera / * CODICE UTENTE BEGIN x * / e / * CODICE UTENTE END x * / blocchi di commento per implementare il codice specifico dell’utente. Il codice utente deve essere scritto all’interno di questi blocchi di commento. Ogni volta che il codice viene ri-generato con configurazioni modificate lo strumento STMCube mantiene il codice utente all’interno di questi blocchi di commento utente.

Quindi, definire una variabile globale per ricevere un byte dall’UART nel main.c file sorgente:

/* USER CODE BEGIN PV *//* Private variables ———————————————————*/static uint8_t recv_data;/* USER CODE END PV */

Dopo tutto il codice di inizializzazione, abilitare il driver per ricevere 1 byte. La seguente funzione abilita il bit di interrupt RXNE.

/* USER CODE BEGIN 2 */HAL_UART_Receive_IT(&huart1, &recv_data, 1);/* USER CODE END 2 */

Ora, aggiungere una funzione di callback per gestire l’interrupt di ricezione e trasmettere il byte ricevuto.

/* USER CODE BEGIN 0 */void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){HAL_UART_Transmit(huart, huart->pRxBuffPtr, 1, 1000);}/* USER CODE END 0 */

Infine, abbiamo bisogno di compilare il codice e flash (download) al microcontrollore.

Quando il Keil MDK ARM IDE è installato, i driver per ST-LINK V2, J-Link e Ulink2 sono disponibili. Il debugger ST-Link sarà selezionato per impostazione predefinita. Vai a Progetti – >Opzioni per Target e nella scheda Debug selezionare il programmatore ICSP utilizzato.

Flash il codice selezionando Flash – >Download.

NOTA: Assicurati di scaricare la tua guida PDF gratuita 15 Passi per sviluppare il tuo nuovo prodotto hardware elettronico.

Il microcontrollore ora echeggerà tutti i dati ricevuti tramite UART. Può essere collegato a un PC utilizzando un convertitore da USB a seriale. Sul PC aprire la porta COM con un’applicazione terminale utilizzando le impostazioni di 115200-8-N-1. Ora tutto ciò che viene inviato dal terminale riecheggerà attraverso il microcontrollore.

Sistema di interrupt

Il sistema di interrupt STM32 è basato sulla periferica NVIC ARM Cortex M core. Le MCU STM32 supportano più canali di interrupt mascherabili a parte i 16 canali di interrupt del core ARM.

Ad esempio la serie MCU STM32F0 supporta 32 interrupt mascherabili. L’eccezione e la tabella vettoriale di interrupt per questa famiglia di MCU sono riportate nella tabella seguente.

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 Interrupts and Events Controller (EXTI)

Gli MCU STM32 dispongono di un Extended interrupts and Events controller che gestisce gli eventi/interrupt asincroni esterni ed interni e genera la richiesta di evento al controller CPU / Interrupt e una richiesta di wake-up al Power Manager.

Ciascuna delle una o più linee EXTI sono mappate su uno dei vettori di interrupt NVIC.

Per le linee di interrupt esterne, per generare un interrupt, la linea di interrupt deve essere configurata e abilitata. Questo viene fatto programmando i due registri trigger con il rilevamento dei bordi desiderato e abilitando la richiesta di interrupt scrivendo un’ 1 ‘ al bit corrispondente nel registro maschera di interrupt.

Interrupt esterno e mappatura GPIO

Ciascuno dei GPIO disponibili sul sistema può essere configurato per generare un interrupt. Ma ciascuna delle linee di interrupt EXTI è mappata su più pin GPIO. Ad esempio,PIO0 su tutte le porte GPIO disponibili (A,B, C, ecc.) sarà mappato alla linea EXTI0. PIO1 per tutte le porte verrà mappato alla linea EXTI1 e così via.

Alcune delle linee EXTI sono combinate in un singolo vettore NVIC. Ad esempio, EXTI4_15 è mappato su un singolo indirizzo vettoriale, quindi ci sarà una singola routine di interrupt per tutti gli interrupt da PIO4 a PIO15. Ma la fonte dell’interrupt può essere identificata leggendo il registro in sospeso di interrupt.

Una cosa importante da considerare durante la progettazione di un sistema utilizzando le MCU STM32 è la selezione dei pin GPIO per gli interrupt. L’MCU può avere più di 16 GPIO disponibili sul dispositivo, ma ci sono solo 16 linee di interrupt esterne disponibili.

Ad esempio, EXTI_0 può essere mappato su PA0 o PB0 ma non su entrambi. Quindi, mentre si scelgono i pin per gli interrupt esterni, dovrebbero essere scelti in modo tale che possano essere mappati in modo univoco su una delle linee EXTI.

La sezione seguente descrive come configurare un interrupt utilizzando il cubo STM32.

schermata configurazione interrupt STM32CubeMX

Selezionare la scheda Configurazione e scegliere il modulo hardware per il quale l’interrupt deve essere configurato. Si apre la finestra di configurazione del modulo.

Quindi selezionare la scheda Impostazioni NVIC e abilitare l’interrupt globale.

Il codice per abilitare l’interrupt per il modulo verrà generato in stm32f0xx_hal_msp.c nella funzione HAL_<modulo >_MSPInit (…).

/* USART1 interrupt Init */HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);

Il codice generato dal Cubo STM32 avrà l’implementazione IRQ_Handler di tutti gli interrupt. Quando l’interrupt è abilitato il codice verrà incluso nell’applicazione.

Di solito il codice generato gestisce già l’IRQ e cancella il flag che ha generato l’interrupt. Quindi chiama un callback dell’applicazione che corrisponde all’evento che ha generato l’interrupt per il modulo.

L’HAL STM32 (Hardware Abstraction Layer) implementa un callback per ciascuno dei tipi di evento all’interno di ciascun modulo come parte del driver. In questo esempio il callback completo del trasferimento Rx deve essere copiato da stm32f0xx_hal_UART.file C.

Le funzioni di callback all’interno del driver saranno implementate con un attributo __weak linker. L’utente deve implementare una copia della funzione di callback necessaria rimuovendo l’attributo _ _ weak in uno dei file dell’applicazione e quindi scrivendo la gestione specifica richiesta all’interno di tale funzione.

/*** @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.*/}

Conclusione

Questo tutorial è un’introduzione alla scrittura di un’applicazione che funziona con la famiglia di microcontrollori STM32. Esistono diversi altri metodi per scrivere un’applicazione, ma STM32Cube discusso è un metodo facile e intuitivo per iniziare.

Questo strumento semplifica l’inizializzazione delle periferiche del microcontrollore. Migliora anche la manutenibilità del codice, specialmente quando ci sono revisioni hardware che richiedono la rimappatura dei segnali su diversi pin.

Un altro vantaggio dell’utilizzo dello strumento STM32Cube è che genera un report della configurazione utente per il microcontrollore. In questo rapporto descrive l’albero dell’orologio, la mappatura dei pin e la configurazione del modulo hardware che sono tutti molto utili.

Ci sono anche diverse altre librerie di codice e programmi di esempio disponibili per tutte le varianti STM32. È incluso anche il supporto per diversi IDE.

Se il tuo progetto richiede un sofisticato microcontrollore a 32 bit, consiglio vivamente la serie STM32. Non solo sono potenti e popolari, ma i microcontrollori STM32 sono anche abbastanza convenienti.

Hai bisogno di più formazione sulla programmazione dei microcontrollori STM32? Se è così, ecco un corso introduttivo più approfondito che dovresti controllare.

Questo articolo è stato scritto da Mohan Kashivasi da Vithamas Technologies. È anche uno degli esperti disponibili per aiutarti con il tuo prodotto all’interno dell’Hardware Academy.

Infine, non dimenticare di scaricare il tuo PDF gratuito: Guida definitiva per sviluppare e vendere il tuo nuovo prodotto hardware elettronico. Riceverai anche la mia newsletter settimanale in cui condivido contenuti premium non disponibili sul mio blog.

Altri contenuti che ti potrebbero piacere:

  • Introduzione al STM32CubeIDE per STM32 Microcontrollori
  • Come selezionare il microcontrollore per il vostro nuovo prodotto
  • Utilizzando Arduino come piattaforma di sviluppo embedded
  • Scheda tecnica Recensione: Entry-Level STM32 Cortex-M0 Microcontroller (Blog + Video)
  • Introduction to the Ultra High-Performance STM32H7 32-bit Microcontroller
4.52votes
Article Rating

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.