A placa STM32F0 Discovery é um produto da empresa franco-italiana STMicroelectronic, composta por um circuito debugger/gravador, o microcontrolador alvo STM32F51R8T6 (ARM Cortex-M0), um circuito periférico com duas chaves tact-switch (uma para propósitos gerais e uma para RESET) e dois LEDs (um verde e outro azul), além das barras de pinos laterais, as quais estendem o acesso a todos os pinos do microcontrolador, conforme exibido na figura 1:
A STMicroelectronics tem um formato padrão dos kits Discovery, assim como os kits STM32F334 Discovery, STM32F3 Discovery, STM32F4 Discovery, entre outros, já apresentados respectivamente por Felipe Neves, Thiago Lima e André Curvello.
Objetivo
O propósito da apresentação deste kit é induzir iniciantes e profissionais a conhecer essa linha de microcontroladores da ST, assim como a percepção da facilidade em iniciar um projeto com esse hardware seja com o MDK-ARM, IAR Embedded Workbench for ARM, Atollic TrueSTUDIO ou Cocoox, e a possibilidade de embarcar um Real Time Operation System (Sistema Operacional de Tempo Real) da própria Keil (RTX). Assim, iremos dar alguns detalhes do microcontrolador, do circuito periférico disponível ao usuário e também a inicialização de um projeto básico (startup).
O Microcontrolador
A seguir listamos algumas características relevantes do microcontrolador STM32F051R8T6 que compõe a placa:
- Core: ARM® 32-bit Cortex®-M0 CPU, cuja frequência vai até 48 MHz;
- Memória: 64KB de Flash e 8KB de SRAM;
- Gerenciador de Power e Reset: Power ON/Power Down Reset (POR/PDR), Detector de Tensão Programável (PVD), modos de baixo consumo (Sleep, Stop, Standby) e Vbat (pino 1 do microcontrolador) como fonte de alimentação para o RTC (Real Time Clock) e backup de registradores;
- Clock: cristal oscilador de 4 até 32MHz (HSE – High-Speed External), cristal oscilador de 32kHz (LSE – Low-Speed External) para RTC, RC interno de 8MHz com opção de PLLx6 e outro RC interno de 40kHz;
- I/O: até 55 fast I/Os sendo que 36 são tolerantes a 5Vdc;
- Controlador DMA (Direct Memory Acess – Acesso Direto à Memória) de 5 canais;
- Um ADC (Analog to Digital Converter – Conversor Analógico para Digital) de 12 bits cuja faixa de conversão é de 0 até 3,6Vdc e com fonte analógica separada;
- Até 18 canais com sensoriamento capacitivo (chave, linear e rotatório);
- 11 Timers;
- 2 USARTs, suportando SPI síncrono master, LIN e IrDA;
- 2 SPI (18Mbits/s) com 4 até 16 bit frame programável, uma com interface multiplexada I²S.
Circuito Periférico
O circuito periférico para propósito geral (usuário) é visto a seguir na figura 2:
Percebe-se que ele é muito simples, nada de displays, acelerômetros, etc, mas já é o suficiente, inicialmente, para aprendermos como é feita a configuração dos GPIOs e do clock do core e fazer o LED piscar, ou seja, o “Hello World” embarcado.
Para aplicações ou projetos que utilizarão como uma unidade de controle, controlando um driver de motor, por exemplo, os LEDs poderão ser úteis para indicar que o código está rodando, ou seja, piscando a uma frequência conhecida pelo desenvolvedor, ou para passar alguma indicação de “erro”, assim assumindo um comportamento diferenciado.
Além deste circuito que é destinado ao usuário, o kit também dispõe de um debugger/gravador, o qual depura o código “step-by-step” (passo a passo) e também pode funcionar como um gravador para produtos já concebidos, apenas modificando dois “jumpers” e também um cabo customizado, exibidos na figura 3.
“Hello World” STM32F0 Discovery
Para este projeto será utilizado como ferramenta de desenvolvimento o MDK-ARM da Keil, o qual pode ser baixado do site da empresa. Esta versão compila projetos de até 32KB, mas acredite, pode-se fazer muita coisa com isso! Além disso, é importante que seja instalado o driver para utilizarmos o ST-LINK debugger.
A escolha desta ferramenta foi subjetiva, sinta-se livre para usar outras que for mais conveniente, pois a configuração do hardware e o resultado final serão os mesmos.
A ST dispõe de muito conteúdo para auxiliar o desenvolvimento e aprendizado, principalmente com os kits Discovery, assim, baixe o “STM32F0 Discovery kit firmware package”, pois além de projetos exemplos, neste pacote estão os arquivos system_stm32f0xx.c, system_stm32f0xx.h e o startup_stm32f0xx.s que serão utilizados.
Para iniciar um projeto no MDK-ARM, sugiro que seja lido o User Manual 1523, pois nesse manual é feito o passo a passo, além de ser ilustrado.
Lido o manual, inicializado o projeto no MDK-ARM e instalado o driver, sugiro que a árvore do projeto seja feita da seguinte forma, a fim de ser organizado:
Importante: lembre-se que os arquivos mencionados acima, arquivos-fonte “main.c” e “.uvproj”, deverão estar na mesma pasta.
O diretório “Projeto Pisca LED” é composto pelos subdiretórios “CMSIS” e “Aplicação”. Em CMSIS estão os arquivos das rotinas de reset e configuração dos registradores do RCC (Reset and Clock Control), ou seja, configuração do clock do core, memória Flash e barramentos, além do arquivo “startup” constituído pelo mapa de vetores e também pela configuração do Stack Pointer, Heap e também qual instrução inicial que o Program Counter carregará após o reset, vide figura 5.
Pode-se visualizar na figura acima que no “Reset Handler” será chamada a rotina “SystemInit()” que fará o reset dos registradores de configuração do clock e ainda chamará a rotina que configurará o HSE (“SetSysClock()”) vide figura 6. Porém, se o usuário for usar outra fonte de clock (High Speed Internal por exemplo), isto realizará um trabalho desnecessário, fazendo duas configurações uma sobrepondo a outra. Assim para este projeto, colocaremos esta rotina de configuração do HSE no arquivo “main” e comentaremos “SetSysClock()” em “SystemInit()”, porém se o usuário quiser manter a configuração do arquivo original, fique à vontade, apenas lembre-se da localização para modificações.
Assim sendo, o código fonte do “Pisca_LED” está a seguir:
#include "stm32f0xx.h"
#define LED_AZUL (unsigned char)0
#define LED_VERDE (unsigned char)1
#define LED_NUM (unsigned char)2
const unsigned long led_mask[] = {1UL << 8, 1UL << 9};
const unsigned long ulRefTime = 4800000;
/*----------------------------------------------------------
* vDelay: Delay
*
* Parameters: nenhum.
* Return: nenhum.
*---------------------------------------------------------*/
void vDelay(void)
{
unsigned long ulCounter = 0;
while(ulCounter++ <= ulRefTime){}
}
/*----------------------------------------------------------
* LEDs_Init: inicializa os pinos que liga/desliga os LEDs.
*
* Parameters: nenhum.
* Return: nenhum.
*---------------------------------------------------------*/
void vLEDs_Init(void)
{
/* Habilita o clock do barramento AHB - GPIOC */
RCC->AHBENR |= (1UL << 19);
/* Configura os pinos PC8 e PC9 como saída "push-pull" */
/* Reseta os bits do PC8 e PC9 */
GPIOC->MODER &= ~((3UL << 2 * 8) | (3UL << 2 * 9));
/* PC8 e PC9 como "output" */
GPIOC->MODER |= ((1UL << 2 * 8) | (1UL << 2 * 9));
/* Outputs como "push-pull" */
GPIOC->OTYPER &= ~((1UL << 8) | (1UL << 9));
/* Barramento do GPIO como "low-speed" */
GPIOC->OSPEEDR &= ~((3UL << 2 * 8) |(3UL << 2 * 9));
/* Sem "pull-up" e "pull-down" */
GPIOC->PUPDR &= ~((3UL << 2 * 8) |(3UL << 2 * 9));
}
/*----------------------------------------------------------
* LED_Liga: Seta a saída para ligar o LED.
*
* Parameters: Qual LED será ligado.
* Return: nenhum.
*---------------------------------------------------------*/
void vLED_Liga(unsigned char ucNum)
{
if(ucNum < LED_NUM)
{
GPIOC->BSRR |= (led_mask[ucNum]);
}
}
/*----------------------------------------------------------
* LED_Desliga: Reseta a saída para desligar o LED.
*
* Parameters: Qual LED será desligado.
* Return: nenhum.
*---------------------------------------------------------*/
void vLED_Desliga(unsigned char ucNum)
{
if(ucNum < LED_NUM)
{
GPIOC->BSRR |= (led_mask[ucNum] << 16);
}
}
/*----------------------------------------------------------
* vSystemCoreClockSetHSE: configura o clock do core, dos
* barramentos AHB e APB e o buffer da Flash.
*
* Parameters: nenhum.
* Return: nenhum.
*---------------------------------------------------------*/
void vSystemCoreClockSetHSE(void)
{
/* Habilita o HSE como fonte de clock */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Aguarda pela estabilização do HSE */
while ((RCC->CR & RCC_CR_HSERDY) == 0);
/* HSE selecionado como "system clock */
RCC->CFGR = RCC_CFGR_SW_HSE;
/* Aguardando HSE para ser usado como "system clock" */
while ((RCC->CFGR & RCC_CFGR_SWS) == RESET);
/* Habilita o Buffer de Pré-Busca */
FLASH->ACR = FLASH_ACR_PRFTBE;
/* Aguarda um cliclo */
FLASH->ACR |= FLASH_ACR_LATENCY;
/* Fator de divisão do clock do barramento AHB (:1), AHB = SYSCLK */
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/* Fator de divisão do clock do barramento APB (:1), APB = AHB*/
RCC->CFGR |= RCC_CFGR_PPRE_DIV1;
/* Desabilita o PLL para configuração */
RCC->CR &= ~RCC_CR_PLLON;
/* Configuração do PLL = HSE * 6 = 48 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
/* Habilita o PLL */
RCC->CR |= RCC_CR_PLLON;
/* Aguarda o PLL estar pronto, equanto isso não faz nada! */
while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP();
/* Seleciona PLL como "system clock" */
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_PLL;
/* Aguarda PLL ser o "system clock" */
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}
int main(void)
{
vSystemCoreClockSetHSE();
vLEDs_Init();
while(1)
{
vLED_Liga(LED_VERDE);
vLED_Desliga(LED_AZUL);
vDelay();
vLED_Desliga(LED_VERDE);
vLED_Liga(LED_AZUL);
vDelay();
}
}
Neste arquivo estão: “vSystemCoreClockSetHSE()” que realiza a configuração o clock como já dito, “vLEDs_Init()” que configura os GPIOs dos LEDs, as rotinas “vLED_Liga()” e “vLED_Desliga()” e a rotina de “vDelay()”. Na função main() é feito o pisca-pisca.
Para os profissionais mais experientes, a codificação do “pisca-pisca” é bem simples e não demanda conhecimentos extras, é claro, mas mostrará para quem não trabalhou com esta arquitetura ou fabricante, uma idéia de como funciona e para aqueles que são iniciantes, uma oportunidade em dedicar tempo para aprender e fazer algo novo.
É claro que não houve nenhuma preocupação quanto ao uso do “WatchDog”, “Power Voltage Detector (PVD)”, entre outros circuitos de monitoramento distintos, pois o ponto principal é dar um suporte básico para o “ponta-pé” inicial.
Conclusão
Diante do apresentado neste artigo, ou seja, as características principais, as opções de funcionamento (fontes de clock, GPIOs, Flash, etc) e o que há de disponível para usufruir do kit STM32F0 Discovery, é possível realizar um projeto básico como o “pisca-pisca” e condicionar o usuário, mediante a esforços para agregar mais conhecimentos, projetos mais complexos.
Portando, é possível realizar um “Hello World” embarcado com este conteúdo e também fornecer conhecimentos básicos necessários para introduzirmos um RTOS futuramente.







Amigos bom dia.
Eu tenho uma placa STM32F0 e STM32F100…
Gostaria de ajuda pra entender como controlar um servo motor…
Alguma dica ou material por ai na comunidade?
Obrigado pela atenção.
opa tudo bem eder preciso que desenvolva um projeto de scaner e possivel se sim me adciona por favor. urgente 038997248422 claudio
Belo artigo Eder!!! Parabens!!!
Obrigado Ciro!
Muito bacana! Gosto de estudar novas arquitetura as com o códigos e funções abertos ao programador, pois quando comecei me frustrava em usar ex: adc_Read(x) pois chaveamento do periférico é escondido. Gostei do seu post, Parabéns!
Obrigado João!
Sempre há as duas formas de configuração ou uso de algum periférico do uC: configuração ou elaboração da rotina “escovando o bit” ou o uso da biblioteca do fabricante. Este úlitmo, tratando-se da ST, é muito confiável, ao menos nunca tive problemas com ela! 🙂
A mikroElektronika disponibilizar versão demo que compila projetos de até 8KB, do mikroC PRO for ARM, mikroBasic PRO for ARM e mikroPascal PRO for ARM. De fácil aprendizado e o custo de aquisição é bem em conta, quando comparado com algumas outras opções.
Examples for STM32F051 line with STM32F0Discovery development board:
https://www.libstock.com/projects/view/803/stm32f0discovery-examples
Bacana Oliveira! Mais uma opção de ferramenta para o desenvolvedor de ARM. Apenas gostaria de dar uma sugestão: tente usar àquelas que dispõe compiladores para C/C++, pois estas linguagens estão entre as mais utilizadas em embedded systems, ok? E obrigado pelo comentário, sempre é útil! 🙂
Maior orgulho!
Valeu brother!
Muito legal!
Agora falando mais de gosto, eu gosto mais de trabalhar com o CubeMX (inicializador de código) como o Rafael Dias comentou. Acho ele bem simples para iniciantes.
E sobre o Keil, a ST tem um acordo com eles e para Cortex M0 (STM32F0xx) e Cortex M0+ (STM32L0xx), eles distribuem uma licença full gratuita. É via esse link: http://www.keil.com/mdk-st
Que bacana Diego Mendes!!! Essa licença com certeza atrairá muitos desenvolvedores em início de projeto!
Parabéns!
Obrigado Gil!
Vale ressaltar que os projetos para o Atollic podem ser carregados no eclipse + launchpad GCC
Legal Rafael!
acho que outro aspecto interessante a cobrir em algum artigo é o uso da STM32Cube (https://www.st.com/web/en/catalog/tools/FM146/CL2167/SC2004)
Ah sim! O STM32 Cube eu já usei em projetos, na verdade apenas para configuração de GPIO e não para elaboração da árvore do projeto. É uma boa sugestão!
eu usei ele como muleta para ver como se configurava algumas coisas… Na verdade, ainda uso.
Rafael, esses dias que eu consegui lembrar o antecessor do STM32Cube: o MicroXplorer! A IDE era praticamente a mesma, mas com menos recursos. Você conheceu? Chegou a mexer?
Não cheguei a usar pois Na época eu tinha um pouco de aversão a usar esses geradores de código, até o dia que apanhei muito para acertar a configuração de um oscilador para um projeto que estava tocando… Desde então eu uso para algumas coisas.
Eu também tinha até o momento que eu tinha que configurar um STM32F407 (Cortex M4) com 144 pinos!
onde encontro placas como essa no Brasil? só acho versões muito básicas com stm32