Indice |
Introduzione
Ho deciso di scrivere questa guida per descrivere il procedimento di configurazione e programmazione di un microcontrollore ARM Cortex M3, in particolare l' "ST32F100RBT6B", viste le molteplici complessità incontrate.
La scheda di valutazione utilizzata è questa.
Mentre come compilatore è stato usato Keil(MKD-ARM) .
Prima di poter cominciare la stesura vera e propria del programma si deve configurare a dovere il compilatore, per fare ciò serviranno le librerie ufficiali ST reperibili a questo link.
Queste librerie servono per semplificarci la vita,invece evitare di andare a modificare i singoli bit dei registri, possiamo utilizzare le funzioni proposte dal file di help (il file con estensione .chm).
D'obbligo avere sempre sotto mano il datasheet del micro e, in questo caso, può fare comodo anche quello dalla board.
Questa è la pagina del micro e questo il relativo datasheet.
Primo Programma
Il primo programma di prova consiste nel dimmerare il LED verde(PC9) in modo da simulare un effetto fade. Quindi dopo aver scaricato tutto il necessario basterà installare ed avviare Keil uVision4.
Consiglio di creare una nuova cartella per ogni progetto, in quanto il progetto prevede numerosi file. Nella cartella del progetto è consigliabile copiare ogni volta tutti i file necessari, come i file .h e .c delle librerie, nel nostro caso copiare la cartella "Libraries" presente nel pacchetto ST sopracitato. Inoltre serve il file "stm32f10x_conf.h" che si trova sempre nella libreria sotto "\Project\STM32F10x_StdPeriph_Template", da copiare all'interno della cartella del progetto.
Una volta aperto l'IDE vi troverete in questa schermata
quindi andare su Project poi su New uVison project..
scegliere un percorso dove salvare il progetto e dargli un nome (in questo caso pwm-led)
selezionare il micro, in questo caso STM32F100RB
sciegliere Si per aggiungere il file di startup
creiamo un nuovo file premendo New
salviamo il file appena creato
e chiamiamolo main.c
nella finestra di sinistra (Project) possiamo rinominare i gruppi a piacimento (premendo f2), in questo caso User
aggiungiamo altri file .c al gruppo user tramite click dx -> Add Files to Group 'User'...
aggiungiamo il file precedentemente creato main.c
aggiungiamo un nuovo gruppo da Target 1 -> click dx -> Add Gruop...
chiamiamolo StdPeriph_Driver (i nomi dei gruppi sono soggettivi)
per aggiungere file al gruppo, come sopra, click dx sul gruppo -> Add Files to Group..
aggiungiamo tutti i file, sempre con estensione .c, del percorso \Libraries\STM32F10x_StdPeriph_Driver\src
questo dovrebbe essere il risultato
aggiungiamo un altro gruppo e chiamiamolo CMSIS
aggiungiamo il file core_cm3.c che si trova in \Libraries\CMSIS\CM3\CoreSupport
e il file system_stm32f10x.c che si trova in \Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
A questo punto si può copiare il codice nel main.c
#include "stm32f10x.h" TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; uint16_t CCR1_Val = 0; int check=0; uint16_t PrescalerValue = 0; int fade_time = 0x1FFFF; /* Function Definition */ void RCC_Configuration(void); void GPIO_Configuration(void); int main(void){ /* System Clocks Configuration */ RCC_Configuration(); /* GPIO Configuration */ GPIO_Configuration(); /* ----------------------------------------------------------------------- TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles: The TIM3CLK frequency is set to SystemCoreClock (Hz), to get TIM3 counter clock at 24 MHz the Prescaler is computed as following: - Prescaler = (TIM3CLK / TIM3 counter clock) - 1 SystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-density and Connectivity line devices and to 24 MHz for Low-Density Value line and Medium-Density Value line devices The TIM3 is running at 36 KHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1) = 24 MHz / 500 = 48 KHz TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = variable% ----------------------------------------------------------------------- */ /* Compute the prescaler value */ PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 500; TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel4 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC4Init(TIM3, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM3, ENABLE); /* TIM3 enable counter */ TIM_Cmd(TIM3, ENABLE); while (1) { int i; if(CCR1_Val>=500){ while(CCR1_Val>=1){ CCR1_Val-=10; for(i=fade_time;i!=0;i--); TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OC4Init(TIM3, &TIM_OCInitStructure); } } else{ CCR1_Val+=10; for(i=fade_time;i!=0;i--); TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OC4Init(TIM3, &TIM_OCInitStructure); } } } void RCC_Configuration(void) { /* TIM3 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* GPIOA and GPIOB clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); //remap per pin 8 e 9 porta C } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); //caricare le impostazioni gpio }
Prima di poter compilare però ci sono ancora alcuni passagi da seguire
andare su Target Options...
spostarsi su C/C++
nel campo Define scrivere STM32F10X_MD_VL, USE_STDPERIPH_DRIVER
spostarsi nel campo in basso Include Paths e premere il tasto sulla destra
premere New
poi il pulsante ...
quindi inserire i seguenti percorsi:
- \pwm-led (perchè la mia cartella principale del progetto è pwm-led)
- \pwm-led\Libraries\STM32F10x_StdPeriph_Driver\inc
- \pwm-led\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
- \pwm-led\Libraries\CMSIS\CM3\CoreSupport
dovrebbe essere come nell'immagine
OK ora si può compilare (premendo f7)
se il risultato è come quello in foto, il procedimento è andato a buon fine
Non rimane che configurare il programmatore/debugger in Keil
tornare in Target Otpions... e spostarsi su Debug
dal menu a tendina selezionare ST-Link Debugger e mettere la spunta su Use
spostarsi su Utilities
dal menu a tendina sciegliere sempre ST-Link Debugger
andare su Settings
spuntare Reset and Run in modo che, una volta scaricato il codice, si avvii senza dover resettare a mano la scheda
premere Add
selezionare STM32F10x Med-density Flash ...
Ed il gioco è fatto ora non vi resta che scaricare il codice nella schda e testare il tutto
Riepilogo
Add-on
Questo è il video di quello che dovrebbe fare la il programma sulla STM32 Discovery
mentre questo è l'analisi all'oscilloscopio della variazione del segnale pwm nel pin PC9
Spero che questo articolo possa essere di aiuto a qualcuno.
Ovviamente sono ben accetti consigli per il miglioramento della guida, e per la correzione di eventuali errori.
Ringrazio in generale tutta la community di ElectroYou per il supporto che offre, ed in particolare a TardoFreak che mi ha aiutato a risolvere gli ultimi problemi sulle inclusioni.
Un saluto a tutti
Silvio