
0. Antes de ler o artigo
Este artigo tem os seguintes objetivos:
- mostre como trabalhar especificamente com este quadro;
- mostre a abordagem pela qual você pode escrever um programa de LED piscando, confiando apenas na documentação e na lógica;
- Apresente o material em um idioma compreensível para uma pessoa pouco familiarizada com os microcontroladores.
O código será minimalista em termos de uso de arquivos adicionais - não incluiremos um único arquivo, exceto os necessários para criar um firmware vazio, mas válido. I.e. com base no código do firmware, que funciona, mas não faz nada útil.
Vamos precisar da seguinte documentação:
- Folha de dados STM32F030x4 (eu uso o documento de janeiro de 2017 DocID024849 Rev 3);
- RM0360 Manual de referência STM32F030x4 / x6 / x8 / xC (eu uso o documento de abril de 2017 DocID025023 Rev 4);
- placa de circuito.
Você pode baixar esses documentos da
nuvem .
O cronômetro no artigo
não será considerado e
não estará envolvido no código.
O programador ST-LINK
não foi usado. Para trabalhar com a placa, foi utilizado um adaptador USB-COM (RS232 baseado em PL2303HX), que emula uma porta COM.
Tudo foi coletado em uma máquina virtual do Windows XP Professional 2002 SP3 executando o VirtualBox versão 5.2.22r126460 em um host do Windows X.
1. Instalando o driver para o adaptador USB-COM
O Windows não ajuda, faça o download no site oficial
Prolific (o primeiro link para a solicitação de "driver prolífico" no Google) USB para UART / Serial / Printer
PL2303 Windows Driver (você precisa daquele
Driver Padrão ). Ou você pode baixar da minha
nuvem .
Instale o driver, reinicie e veja a nova porta COM.
Captura de tela com o nome do instalador e a nova porta COM As configurações da porta deixaram o padrão. Você pode alterar o número da porta COM a seu critério. Na minha experiência, apenas uma vez na vida vi um programa ver apenas as 4 primeiras portas COM; se não me engano, era algum tipo de terminal Bluetooth no Windows.
Configurações da porta COM 2. Preenchendo o firmware dentro e fora da placa
2.0 Utilitário de download para trabalhar com o quadro
Fazemos o download do utilitário
FLASHER-STM32 no site do
STM (na descrição é chamado de demonstrador de carregador STM32 Flash (UM0462)), você deverá se registrar para isso, mas não é assustador - no final, removeremos o arquivo zip com o instalador; Próximo-> Próximo-> Próximo ... e tudo está instalado. Por conveniência, crio um atalho para esse aplicativo na pasta de trabalho.
Aqui está o utilitário (captura de tela do site) Por padrão, o caminho para o utilitário
C: Arquivos de Programas \ STMicroelectronics \ Software \ Flash Loader Demo \ STMFlashLoader Demo.exe .
2.1 nuance de inicialização
Há um jumper BOOT no quadro.
- Quando o jumper é fechado , o microcontrolador carrega instruções da memória (ou seja, um programa escrito por um programador).
- Quando o jumper está aberto , o microcontrolador receberá informações nas linhas RX e TX, ou seja, Ele piscará na porta COM (do adaptador no meu caso).
2.2 Configurando o utilitário

Execute este aplicativo, ele é realmente o mais simples (contém um mínimo de configurações). Na primeira janela, selecione:
- interface (eu tenho COM-3);
- a velocidade com a qual o computador e o microcontrolador se comunicarão (IMHO, valor normal de 9600);
- o número de bits de dados (por algum motivo, essa janela não está disponível para mim, mas até agora isso não é importante);
- paridade (não tenho paridade, ou seja, Nenhuma);
- eco (desativei);
- tempo de espera (eu tenho 10 segundos).
Clique em Avançar e, se tudo estiver em ordem, veremos uma luz verde e "O alvo está legível"; se virmos uma luz vermelha, o computador não pôde se conectar.
O alvo é legível se o microcontrolador for detectado com sucesso A ordem das etapas que sempre ajudam:
- Primeiro, você precisa verificar se o jumper BOOT na placa está fechado.
- Em segundo lugar, em qualquer caso, desligue a energia do microcontrolador e, de preferência, as linhas TX e RX vindas do adaptador para a placa (você não pode desconectar o terra).
- Em terceiro lugar, no programa, pressione Voltar até o fim, ou seja, para a primeira página, ou até fechá-la e reiniciá-la (em geral, às vezes congela) É importante começar sempre da primeira página antes de cada conexão à placa através deste programa.
- Quarto, pegue os fios do adaptador na placa e tente conectar-se novamente no programa (certifique-se da primeira página!).
Se tudo mais falhar, tente desligar tudo, reinicie o computador e reconecte-se à placa.
Porque Trabalho em uma máquina virtual, preciso reconectar o adaptador USB-COM várias vezes para que seja detectado pela máquina virtual e a máquina host não tenha tempo para instalar drivers danificados.
Outra opção que encontrei trabalhando enquanto escrevia este artigo é pressionar um botão no quadro em vez de puxar constantemente os fios. No entanto, você precisará fechar e abrir o jumper BOOT em qualquer caso. Esta opção funciona porque o botão é colocado no pé da redefinição
NRST externa.
Na próxima janela, selecione o dispositivo de destino Destino. A propósito, às vezes aqui você pode ver (talvez um bug) o dispositivo esquerdo em geral, por exemplo, em vez de STM32 ver STM8 - em algum lugar houve algum tipo de falha, o procedimento de tratamento é descrito acima. Portanto, nesta etapa, você não pode se apressar em clicar em Avançar, mas sempre preste atenção no fato de que o dispositivo desejado está selecionado no Target.
Seleção de dispositivo de destino Como determinar qual dispositivo temos? - olhamos para o chip e reescrevemos tudo o que está escrito nele. Abrimos a
folha de
dados em nosso chip, a seção
Informações sobre pedidos descreve qual letra é responsável por quê. No meu caso é:


Seleciono meu chip (16K) no Target e seguirei em frente. É oferecida uma escolha de 4 ações com um chip:
- apagar memória (inteira ou selecionar uma área específica);
- escreva o firmware no dispositivo;
- leia o firmware do dispositivo;
- ativar / desativar a proteção contra gravação ou leitura.
2.3 Leia o firmware do quadro
Quando conectei a placa pela primeira vez, decidi manter o firmware original, uma espécie de backup - faremos isso agora. Será necessário indicar onde salvar este firmware e quais páginas de memória salvar; também é proposto o uso de um formato de arquivo
hex ,
bin ou
s19 para sua
escolha .
Selecione as páginas de memória para ler Se você acabou de fazer o upload do firmware para a placa ou ler o firmware da placa, não haverá diferença entre esses formatos de arquivo. A seguir, é apresentada uma página de progresso, na qual, às vezes, o processo congela por 99% por um longo tempo (não necessariamente 99), mas após alguns segundos ele supostamente é concluído com êxito - na verdade, depois disso, a placa não divulgou o comportamento que corresponderia ao firmware carregado. Simplificando, você precisa reconectar tudo e reencher o firmware, não há nada crítico nisso.
O arquivo do firmware foi salvo e, no futuro, poderá ser carregado na placa.
No entanto, se a proteção de leitura estiver instalada, o firmware não poderá ser lido.
2.4 Piscando o quadro
Agora preencha o arquivo de firmware, cuja escrita do código fonte é fornecida abaixo. Olhando para o futuro, direi que enviaremos arquivos
bin e
hex , porque o ambiente de desenvolvimento os emitirá. Configurações adicionais para arquivos
s19 e
hexadecimais são idênticas; ao contrário deles, no arquivo
bin , você pode selecionar o endereço no qual o firmware será gravado; por padrão, no utilitário é 8000000 (adequado para nós).
Antes da gravação, você pode limpar a memória flash do microcontrolador escolhendo uma das três opções:
- Apague as páginas necessárias (limpe as seções necessárias da memória);
- Sem apagamento (sem purificação);
- Apagamento global (limpeza completa).
De fato, a limpeza é o processo de gravar zeros na memória.
Ainda existem bytes opcionais, mas até agora você não pode tocá-los. Clique em Avançar, aguarde a conclusão do processo e pronto.
Caso queira gravar meu firmware, você pode encontrá-lo na nuvem, o arquivo
blink.bin . Ao usar este firmware, o LED embutido que pisca no pé PA4 deve piscar.
3. Escrita de código
3.0 Instalando o ambiente de desenvolvimento CooCox CoIDE
Você pode fazer o download do IDE no site da
SoftPedia.com , antes de poder baixá-lo no site do STM e no próprio site do IDE, mas como os IDEs deixaram de ser compatíveis, tornou-se impossível. Não há nada crítico que o IDE não seja mais suportado, não, porque para escrever código, o principal é o compilador. Baixei as duas versões, mas uso a versão 1.7.8.
O primeiro lançamento do ambiente está bem descrito
aqui , Próximo-> Próximo-> Próximo ... e nada complicado. Acrescentarei apenas que primeiro é melhor criar um projeto e depois todo o resto.
E, no entanto, se você perdeu a guia Repositório, pode encontrá-la no menu
Exibir -> Repositório .
Você pode baixar ferramentas (compilador) para o ambiente
aqui ou pedir ao Google "gnu tools for arm"; Eu baixei uma opção que tem sha1.exe no final.
3.1 Estrutura de origem
Assim, o projeto foi criado, o chip foi selecionado, agora vamos adicionar o conjunto mínimo de fontes ao projeto, sem o qual ele não poderá viver sem.
É assim que o projeto deve ficar quando for criado, ou seja, existe apenas o arquivo main.c principal e nada mais Selecione CMSIS BOOT e o ambiente
selecionará automaticamente
M0 Cmsis Core , porque dependências exigem isso.
Agora temos o conjunto mínimo de fontes Monte o projeto (ícone Compilar ou tecla F7). Por motivos desconhecidos para mim, o arquivo hexadecimal não foi coletado (há um aviso no console); Reinstalei o IDE e o compilador várias vezes, recriei o projeto, mas por algum motivo esse resultado foi feito na máquina virtual; em outro computador (não virtual, mas real), tudo é individual e a saída está funcionando hexadecimal. Felizmente, há bin.
O projeto foi montado com sucesso Aconselho que você preste atenção ao tamanho do arquivo, ele pode ser visto no final da saída no console ou você pode vê-lo por meios padrão (aqui, a propósito, você pode ver que hex está vazio); Ao mesmo tempo, esta captura de tela mostra que os arquivos de firmware estão na pasta do projeto e, em seguida, Debug / bin / Embora o código não faça nada, carrego-o no quadro para garantir que você possa carregá-lo (que, por exemplo, o utilitário não o rejeita). Aconselho o leitor a fazer isso. Se não funcionar, tente novamente e escreva comentários.
3.2 Algoritmo de Dedo
Para começar, esboçamos um algoritmo de como, do ponto de vista humano, o microcontrolador pisca um LED. E por isso um pouco de raciocínio.
Cada equipamento funciona devido à energia armazenada, por exemplo, alguns motores podem funcionar com diferentes tipos de combustível, mas, para isso, o motor precisa ser ajustado ao tipo de combustível com o qual vamos alimentá-lo. Da mesma forma, o microcontrolador precisa ser ajustado (sintonizado) para a fonte de energia - este será o
primeiro bloco do algoritmo.
Nós raciocinamos mais. O computador de mesa possui um monitor, alto-falantes, teclado, mouse ... e você pode ver que alguns dispositivos nos fornecem informações e, com a ajuda de outros, fornecemos informações ao computador, mas todos eles estão conectados a uma caixa comum a todos eles (a unidade de sistema). Você pode adivinhar que o microcontrolador pode receber e fornecer informações, o que significa que suas pernas podem receber um sinal ou emitir um sinal - este será o
próximo bloco do algoritmo.
Em seguida, o microcontrolador deve acender o LED, aguardar um pouco, desligar o LED, aguardar um pouco e ligá-lo-esperar-desligar ...
Como resultado, o algoritmo será mais ou menos assim

O objetivo deste fluxograma é mostrar claramente o que o algoritmo faz; Primeiro de tudo, o esquema é escrito para você, para que todos sejam livres para escrevê-lo / desenhá-lo como quiser (por si mesmo). Eu acredito que o esquema deve ter como objetivo ser o mais simples, legível e intuitivo possível, ter um alto nível de abstração.
De acordo com este algoritmo, escreveremos código.
3.3 Trabalhando com documentação
Eu recomendo a leitura desta parte do artigo com o arquivo aberto
stm32f0xx.h , que fica na pasta
cmsis_boot do nosso projeto e na documentação aberta.
3.3.1 Selecionando uma fonte de relógio
Primeiro, você precisa fornecer energia ao microcontrolador. O microcontrolador recebe 5 Volts do adaptador (medido com um multímetro), mas surge a questão de "em que frequência o microcontrolador trabalha", porque é sabido que a eletrônica funciona em diferentes frequências. Primeiro, abra a
folha de dados ; no conteúdo, você pode ver duas seções relevantes em significado:
Gerenciamento de energia ,
Relógios e inicialização . O primeiro é sobre os modos de tensão e baixa potência. A segunda seção esconde o que nos interessa no momento. Já na primeira frase, ele diz que “o oscilador RC 8 MHz interno é selecionado como clock padrão da CPU na reinicialização”, o que significa que,
por padrão, após a redefinição do MC, a cadeia RC interna de 8 MHz é selecionada como a
principal fonte de clock .
Em seguida, vem um esquema incompreensível de árvore do Relógio, que consideraremos um pouco mais tarde.
A rigor, você pode confiar na frase "por padrão, após redefinir o MK ..." e ler esta parte do artigo na diagonal.
Agora você precisa se distrair com a placa e procurar o LED interno. Eu sei que os diodos nos circuitos são indicados por
D1 ,
D2 ..., ou seja,
D == diodo , na minha placa perto do resistor
R7 é o diodo
D1 .
Talvez, depois de examinar cuidadosamente a placa, você possa traçar em qual perna o diodo está conectado, mas voltarei para a placa de circuito. Infelizmente, os elementos do quadro não correspondem exatamente aos elementos do circuito em sua localização; mas fico feliz por ter encontrado esse esquema na Internet (caso contrário, não conseguiria encontrar nada por um longo tempo).

No diagrama, vemos que o cátodo do diodo é conectado ao terra através do jumper
J2 , e o ânodo é conectado ao pino
PA4 através de um resistor.
PA4 significa a quarta saída da porta
A , o que significa que, para acender e desligar o LED, será necessário fornecer tensão à saída do
PA4 .
Em seguida, você precisa determinar como aplicar tensão a esta saída. Isso não foi nada intuitivo para mim e, durante muito tempo, vasculhei a documentação longitudinalmente até encontrar o
diagrama de blocos na seção
Descrição , no início da folha de dados. E nele vi a preciosa faixa
PA [15: 0] <=> porta GPIO A <=> decodificador AHB <=> Bus matrix <=> Cortex-M0 , ou seja,
A porta
A é uma porta de E / S de uso geral e está conectada ao barramento
AHB .
Diagrama de blocos(A imagem é clicável)

Observo que na eletrônica é habitual dividir as saídas do microcontrolador em portas, e geralmente a porta possui 16 saídas. O diagrama mostra que as portas
A ,
B e
C têm apenas 16, mas as portas
D e
F têm menos (menos de 16 pinos podem ser, mais - não).
Vamos voltar ao esquema da
árvore do
relógio e encontrar a saída assinada pelo
AHB . Vamos descobrir com que frequência essa saída funciona. Para o
AHB está o sinal
HCLK , que sai do divisor
HPRE . Este divisor recebe o sinal
SYSCLK do comutador
SW . Quais dos sinais na entrada
SW serão usados quando o
SYSCLK estiver
programado ,
especificaremos isso mais no código. A escolha é oferecida:
- HSI - um sinal de um gerador interno de alta frequência, é produzido por um ressonador de quartzo de 8 MHz, que soldei antes de trabalhar com esta placa;
- PLLCLK - sinal do multiplicador de frequência PLLMUL ;
- HSE - sinal de um gerador externo de alta frequência.
Qualquer opção é adequada para a nossa tarefa, sugiro escolher a mais simples e mais barata delas -
HSI .
Iremos para o
manual de referência e abriremos a seção
7 Redefinição e controle de relógio (RCC) , especificamente
7.2.6 Seleção do relógio do sistema , onde mais uma vez encontramos uma redação semelhante encontrada na folha de dados: "após uma redefinição do sistema, o oscilador
HSI é selecionado como sistema relógio "- ou seja, nem precisamos fazer nada, o MK começará no
HSI .
Para garantir que o MK realmente funcione a partir dessa fonte, escreverei isso explicitamente no programa; Role até os registros responsáveis pela redefinição e pela contagem de horas (seção
7.4 registros RCC ). O primeiro registro descrito na documentação é o
registro de controle do relógio (RCC_CR) ; Abaixo está uma descrição dos bits, que é responsável por quê.
Registro de controle do relógio Estamos interessados no bit zero
HSION , responsável por ligar o ressonador (
0 - desligado,
1 - ligado).
Assim, será necessário escrever um no registro
RCC_CR . (zero bit é um ou 2
0 = 1).
Agora, encontramos no arquivo
stm32f0xx.h a definição de
RCC (
#define RCC ).
Como você pode ver, esta é a estrutura localizada em
RCC_BASE ; endereço
0x40021000 , se você expandir todas as
definições , o mesmo endereço poderá ser visto no
manual de referência na seção
2.2.2 Mapa de memória e endereços de limite de registro e na folha de dados na seção
5 Mapeamento de memória (área
AHB ).
Para escrever uma unidade para ativar o
HSI no registro
CR do bloco
RCC , você precisa de uma linha de código
RCC->CR |= 0x1;
3.3.2 Ajustando as pernas
Enviar um sinal para a perna do microcontrolador para acender o LED e interromper o sinal para que o LED apague são ações simples e, portanto, isso se refere às funções
GPIO (portas de entrada e saída de uso geral).
Por padrão, as pernas do MK não estão conectadas, ou seja, o resultado é incerteza. É necessário conectar uma porta, cuja perna irá alimentar o LED. Anteriormente, determinamos que as portas
GPIO estão conectadas ao barramento
AHB - você precisa instalá-lo. Continuando a percorrer a seção
7.4 registros RCC (controle e redefinir registros de controle), encontramos a seção
7.4.6 Registro de habilitação de relógio periférico AHB (
registro de habilitação de relógio de barramento
RCC_AHBENR ,
AHB ). Anteriormente, determinei que meu LED estava conectado à perna do
PA4 - portanto, preciso gravar uma unidade no 17º bit do registro para acessar a porta
A.Registro de habilitação do relógio periférico AHB Assim, o código deve ser
RCC->AHBENR |= (1 << 17);
ou, que é a mesma coisa
RCC->AHBENR |= 0x20000;
usando o arquivo
#define stm32f0xx.h write
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
Temos alimentado a porta
A , agora precisamos informar ao MK que o
PA4 funcionará na
saída - leremos a seção
8 E / S de uso geral (GPIO) ; a introdução da seção já diz "Cada porta de E / S de uso geral possui quatro registros de configuração de 32 bits (
GPIOx_MODER ,
GPIOx_OTYPER ,
GPIOx_OTYPER ,
GPIOx_OSPEEDR e
GPIOx_PUPDR ), dois registros de dados de 32 bits (
GPIOx_IDR e
GPIOx_ODR ) ..." -
para cada GPIO A porta possui 4 registros de ajuste e 2 registros de dados - é disso que precisamos (configure a porta
A , ou melhor, a saída
PA4 e envie periodicamente
0 e
1 ). Para uma melhor compreensão (teoria) do que está acontecendo, você pode ler esta seção, mas eu desço até a seção
8.4 Registros GPIO e configuro a porta de acordo com as descrições.
- modo de porta - saia. De acordo com a documentação, é necessário escrever 01 na área correspondente ( MODER4 ) do registro correspondente ( GPIOA_MODER ), ou seja, bits 9 e 8 : no 9º bit deve ser zero, na 8ª unidade:
GPIOA->MODER |= (1 << 8); //
GPIOA->MODER |= 0x100; //
GPIOA->MODER |= GPIO_MODER_MODER4_0;
Registro do modo de porta GPIO
- tipo de saída. Honestamente, ainda não descobri completamente o circuito deste caso (vou entender, reler os fóruns novamente etc.), mas estudar outros recursos sobre a configuração da saída MK, além de lógica e intuição, sugere que deve haver um empurrão -puxar e depois deve ser puxado para cima . De qualquer forma, o código está escrito, tudo funciona e nada queimado. Existe um risco real de queimadura se você selecionar o tipo de dreno aberto e causar um curto-circuito nessa saída com outro dispositivo, como Esta é uma saída aberta e não está protegida por nada. Além disso, temos um resistor limitador de corrente na frente do diodo - ele certamente não queima aqui.
Seguindo a documentação, é necessário escrever zero no 4º bit; a documentação também afirma que após a redefinição haverá zero.
GPIOA->OTYPER &= ~(1 << 4); //
GPIOA->OTYPER &= ~0x10; //
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_4;
Registro do tipo de saída da porta GPIO
- velocidade de saída. No nosso caso, isso não importa, mas por uma questão de fidelidade, escreverei aqui zero.
GPIOA->OSPEEDR &= ~(1 << 8); //
GPIOA->OSPEEDR &= ~0x100; //
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR4_0;
Registro de velocidade de saída da porta GPIO
- um elevador . Porque a saída energizará o LED, é necessário puxá-lo para cima, ou seja, pull-up .
É necessário apertar o 4º pino da porta A ; a documentação diz que, para isso, é necessário escrever zero e um em 9 e 8 bits, respectivamente.
GPIOA->PUPDR |= (1 << 8); //
GPIOA->PUPDR |= 0x100; //
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR4_0;
Registro pull-up / pull-down da porta GPIO
3.3.3 LED ligado / desligado e atraso
Anteriormente, lemos que cada porta possui registros, incluindo registros de dados
IDR e
ODR - registros de dados de entrada e saída, respectivamente. Zeros lógicos e outros na perna MK - são esses dados? Sim, dados. Os dados podem vir de fora do microcontrolador (
entrada ) e sair do microcontrolador e ir para outro dispositivo (
saída ). A unidade na perna MK é a presença de um nível de alta tensão, ou seja, se você trouxer um para a saída, haverá tensão e esse LED poderá alimentar nosso LED. A saída de uma unidade para a perna do microcontrolador é outra coisa que gravar esta unidade no registro de saída do
ODR .
Registro de dados de saída da porta GPIO De acordo com a documentação, vemos que, para cada porta (
A ,
B ,
C ,
D ,
F ), há um registro de 32 bits. a porta não pode ter mais de 16 pinos; somente os primeiros 16 bits do registro são usados. Cada bit corresponde a um número de porta (pino). Para enviar uma unidade para o trecho
PA4 , é necessário escrever uma unidade no 4º bit, gerar um zero - escrever um zero no 4º bit, ou seja, remova a tensão da saída.

O código para ligar o LED ficará assim
GPIOA->ODR |= (1 << 4); //
GPIOA->ODR |= 0x10; //
GPIOA->ODR |= GPIO_ODR_4;
Código para desligar o LED
GPIOA->ODR &= ~(1 << 4); //
GPIOA->ODR &= ~0x10; //
GPIOA->ODR &= ~GPIO_ODR_4;
Mas se você escrever a linha para desligar o LED após a linha para ligar, o LED não piscará (se você estiver interessado no que acontece - você pode tentar; nada será queimado, isso já foi discutido acima) -, você precisará atrasar. Os temporizadores são usados para atraso, mas os temporizadores são dignos de um artigo separado (devido à complexidade), portanto, faremos um atraso na muleta: conduziremos o ciclo de inatividade. Há um ponto:
se a otimização do compilador estiver ativada , o
compilador cortará nosso ciclo inativo e não haverá atraso. Verifique se a otimização não está ativada. Para fazer isso, vamos para a configuração do projeto (clique com o botão direito do mouse no nome do projeto na árvore do projeto) e verifique a linha
Compilar Control String na guia
Compile : ele deve ter o argumento
-O0 ("about zero" significa que a otimização está desativada). Se você coletou tudo de acordo com minhas instruções, provavelmente também terá
-O0 , porque era por padrão e eu não toquei em nada aqui. Os argumentos
-O1 -O2 -O3 significam que a otimização do nível correspondente está ativada.
Verificação de otimização do compilador Um ciclo inativo pode ser escrito assim:
int t = 4000000; while(t > 0) t--;
Eu não defini o valor de
t como tal, raciocinei assim: se o microcontrolador rodar em 8MHz, ele executará aproximadamente 8.000.000 de instruções em um segundo, se você exagerar profundamente, e por um atraso de meio segundo, precisará executar o ciclo 4.000.000 de vezes.
O ciclo de inatividade precisará ser executado após ligar o LED e depois de desligá-lo, e todo esse loop.
3.4 Escrevendo código e executando
Vamos montar todas as linhas de código que escrevemos antes. Você também precisa incluir o arquivo de cabeçalho
stm32f0xx.h , como confiamos nele e extraímos definições de estruturas, endereços e valores. O resultado deve ser:
#include "stm32f0xx.h" int main(void) { int t; // '' RCC->CR |= 0x1; // HSI RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // A GPIOA->MODER |= GPIO_MODER_MODER4_0; // PA4 GPIOA->OTYPER &= ~GPIO_OTYPER_OT_4; // push-pull PA4 GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR4_0; // PA4 GPIOA->PUPDR |= GPIO_PUPDR_PUPDR4_0; // pull-up PA4 while(1) { GPIOA->ODR |= GPIO_ODR_4; // PA4 t = 4000000; while(t > 0) t--; // GPIOA->ODR &= ~GPIO_ODR_4; // PA4 t = 4000000; while(t > 0) t--; // } }
Clique em Reconstruir e preencha o código no quadro por meio do utilitário.

Para que a placa inicie um novo firmware, não esqueça de fechar o jumper BOOT e fazer um reset (RESET).
4. Conclusão
O código está escrito, tudo funciona. Forças gastas sem medida. Fico feliz que, com base na documentação, ele tenha escrito código de trabalho, em grande parte devido ao fato de o STM possuir documentação de alta qualidade.
Os planos são escrever um artigo sobre como montar tudo manualmente, sem um IDE, através do console,
verdadeira velha escola , idealmente para que tudo isso possa ser feito no Linux. Agora estou trabalhando em PWM e ADCs (também neste quadro) - também escreverei um artigo sobre eles.