Biblioteca Periférica Padrão.

10.09.2021

Uma lista de artigos que ajudarão até mesmo um iniciante a aprender o microcontrolador STM32. Detalhes sobre tudo com exemplos que vão desde LED piscando até controle de motor sem escova. Os exemplos usam a SPL padrão (Standard Peripheral Library).

Placa de teste STM32F103, programador ST-Link e software para firmware para Windows e Ubuntu.

VIC (Controlador de interrupção vetorial aninhado) – módulo de controle de interrupção. Configurando e usando interrupções. Interromper prioridades. Interrupções aninhadas.

ADC ( conversor analógico para digital). Diagrama de fonte de alimentação e exemplos de uso de ADC em vários modos. Canais regulares e injetados. Usando ADC com DMA. Termômetro interno. Cão de guarda analógico.

Temporizadores de uso geral. Gerando uma interrupção em intervalos regulares. Medindo o tempo entre dois eventos.

Captura de sinal por um temporizador usando o exemplo de trabalho com um sensor ultrassônico HC-SR04

Usando um temporizador para trabalhar com um codificador.

Geração PWM. Controle de brilho dos LEDs. Controle de servoacionamento (servos). Geração de som.

Por muito tempo, até muito tempo, não houve novos artigos em nosso artigo, então é hora de atualizar 😉 Hoje começaremos a estudar o STM32F4. E, provavelmente, começaremos criando um novo projeto para esses controladores, embora, para ser sincero, eu não quisesse escrever um artigo sobre isso, pois um novo projeto está sendo criado aqui, em princípio, da mesma forma quanto ao STM32F103 (). Mas ainda acontece que surgem algumas dificuldades com o STM32F4, então, mesmo assim, vamos considerar este processo em detalhes)

Então, vamos lançar o Keil, criar um novo projeto - Projeto -> Novo Projeto uVision. Salvamos o novo projeto em alguma pasta e então seremos solicitados a selecionar o microcontrolador a ser utilizado. Bem, vamos escolher, que seja STM32F407VG:

Pronto, na caixa de diálogo que aparece, clique em “Sim” e o primeiro arquivo será adicionado ao nosso projeto - startup_stm32f4xx.s. Assim como antes, usaremos bibliotecas CMSIS E Biblioteca Periférica Padrão, mas, naturalmente, já para controladores STM32F4xx. Então você precisa baixá-los e adicioná-los arquivos necessários ao nosso projeto ainda vazio. A propósito, já ouvi mais de uma vez de diferentes pessoas que se deparam com algumas bibliotecas “não tão” para F4, e mesmo o projeto mais simples não é montado. Eu mesmo não encontrei isso, no entanto, aqui estão as bibliotecas testadas que eu mesmo uso:

Então baixamos, está tudo pronto, agora adicionamos os arquivos ao projeto. A imagem mostra o que você vai precisar:

Bom, a preparação está completa, agora vamos criar um novo arquivo .c, que conterá nosso código. Vamos para Arquivo->Novo, um arquivo vazio é aberto no Keil, clique Arquivo->Salvar como e salve-o com o nome test.c, por exemplo. Ao salvar, não esqueça de especificar a extensão do arquivo (.c). O arquivo foi criado, ótimo, mas também precisamos adicioná-lo ao nosso projeto. Bem, na verdade, não há nada de complicado nisso 😉 Vamos escrever um programa de teste vazio neste arquivo:

#include "stm32f4xx.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" /*******************************************************************/ int principal() (enquanto (1) (__NOP();)) /*******************************************************************/

Quase tudo está pronto, só falta olhar as configurações do projeto - Projeto->Opções para alvo… Uma janela se abre com muitas abas, estamos interessados ​​​​apenas em algumas aqui. Abra a guia C/C++ e no campo Definir escrevemos:

Bem, no campo você precisa adicionar caminhos a absolutamente todos os arquivos incluídos no projeto. Após concluir esta etapa, você pode pressionar F7 (Build) e o projeto será construído sem erros ou avisos. Como você pode ver, nada complicado)

Mas, em geral, eu pessoalmente faço as coisas de maneira um pouco diferente. Veja a desvantagem dessa abordagem. Então baixamos as bibliotecas CMSIS e SPL em algum lugar, adicionamos arquivos dessas pastas, anotamos os caminhos dos arquivos, está tudo legal. MAS! O projeto não será construído em outro computador, pois os caminhos são todos absolutos, ou seja, apontam para pastas específicas do seu computador. E em outra máquina você terá que executar novamente as etapas para criar um novo projeto. Este é um grande sinal de menos. Então eu costumo criar pasta separada para um novo projeto, nele crio subpastas para CMSIS, SPL e outras bibliotecas utilizadas e coloco nestas pastas todos os arquivos que preciso em cada projeto específico. Por exemplo, vamos criar a pasta STM32F4_Test para nosso novo projeto e as seguintes pastas:

Coloquei tudo nas pastas CMSIS e SPL arquivos necessários, que adicionamos ao criar o projeto no início do artigo. Agora iniciamos o Keil, criamos um novo projeto e salvamos em nossa subpasta Projeto para que todos os arquivos do projeto fiquem em um só lugar e não causem caos)

O projeto foi criado, agora, como antes, basta adicionar a ele todos os arquivos das pastas STM32F4_CMSIS e STM32F4_SPL. Colocamos nosso arquivo de teste .c com a função main() na pasta Source e o adicionamos ao projeto também. Resta definir as configurações =) Tudo é igual - no campo definir escrevemos:

USE_STDPERIPH_DRIVER,STM32F4XX



Montamos o projeto - não há erros, o vôo está normal! Em princípio, no final obtivemos a mesma coisa, mas agora o projeto será imediatamente montado em qualquer outro computador sem problemas, e isso é muito conveniente e útil) Absolutamente todos os arquivos do projeto agora estão localizados lado a lado, na mesma pasta, e os caminhos tornaram-se relativos e não precisam ser mudados.
Isso é tudo, na verdade, num futuro próximo faremos algo para programar o STM32F4, com certeza, então até breve!;)

Projeto completo do artigo de exemplo -

Olá a todos. Como você lembra no último artigo, configuramos o pacote de software para funcionar com microcontroladores STM32 e compilamos o primeiro programa. Neste post conheceremos a arquitetura desta placa, microcontrolador e bibliotecas disponíveis para trabalho.

Abaixo está uma foto da placa Descoberta STM32F3 , onde: 1 — Sensor MEMS. Giroscópio digital de 3 eixos L3GD20. 2 - Sistema MEMS em uma caixa contendo um acelerômetro linear digital de 3 eixos e um sensor geomagnético digital de 3 eixos LSM303DLHC. 4 – LD1 (PWR) – Fonte de alimentação 3,3V. 5 – LD2 – LED vermelho/verde. O padrão é vermelho. Verde significa comunicação entre ST-LINK/v2 (ou V2-B) e PC. Tenho ST-LINK/v2-B, bem como um display personalizado Porta USB. 6. -LD3/10 (vermelho), LD4/9 (azul), LD5/8 (laranja) e LD6/7 (verde). No último post piscamos o LED LD4. 7. – Dois botões: USUÁRIO personalizado e redefinir REINICIAR. 8. - USUÁRIO USB com conector Mini-B.

9 - Depurador/programador USB ST-LINK/V2. 1 0. - Microcontrolador STM32F303VCT6. 11. - Externo gerador de alta frequência 8MHz. 12. – Deveria ter um gerador de baixa frequência aqui, infelizmente não está soldado. 13. – SWD – interface. 14. – Jumpers para seleção de programação de controladores externos ou internos, no primeiro caso devem ser removidos. 15 – Jumper JP3 – jumper projetado para conectar um amperímetro para medir o consumo do controlador. É claro que se for excluído, nossa pedra não iniciará. 16. – STM32F103C8T6 há uma placa de depuração nele. 17. — Regulador LD3985M33R com baixa queda de tensão e nível de ruído, 150mA, 3,3V.

Agora vamos dar uma olhada mais de perto na arquitetura do microcontrolador STM32F303VCT6. Dele especificações técnicas: Gabinete LQFP-100, núcleo ARM Cortex-M4, frequência máxima de núcleo 72 MHz, capacidade de memória de programa 256 KB, tipo de memória de programa FLASH, capacidade BATER SRAM 40 kbytes, RAM 8 kbytes, número de entradas/saídas 87, interfaces (CAN, I²C, IrDA, LIN, SPI, UART/USART, USB), periféricos (DMA, I2S, POR, PWM, WDT), ADC/DAC 4*12 bits/2*12 bits, tensão de alimentação 2...3,6 V, temperatura de operação –40...+85 C. Na figura abaixo há uma pinagem, onde vemos 87 portas de entrada/saída, 45 delas E/S normais (TC, TTa), 42 E/S tolerantes de 5 volts (FT, FTf) – compatível com 5 V. (na placa há pinos de 5 V à direita, 3,3 V à esquerda). Cada linha de E/S digital pode servir como uma linha de E/S geral.
destino ou função alternativa. À medida que os projetos avançam, gradualmente conheceremos a periferia.

Considere o diagrama de blocos abaixo. O coração é um núcleo ARM Cortex-M4 de 32 bits operando até 72 MHz. Possui uma unidade de ponto flutuante FPU integrada e uma unidade de proteção de memória MPU, células de rastreamento de macro integradas - Embedded Trace Macrocell (ETM), que podem ser usadas para monitorar o processo de execução do programa principal dentro do microcontrolador. Eles são capazes de emitir continuamente essas observações através dos contatos do ETM enquanto o dispositivo estiver operando. NVIC (Controlador de interrupção vetorial aninhado) – módulo de controle de interrupção. TPIU (unidade de interface de porta de rastreamento). Contém memória FLASH – 256 KB, SRAM 40 KB, RAM 8 KB. Entre o núcleo e a memória existe uma matriz Bus, que permite a conexão direta de dispositivos. Também aqui vemos dois tipos de matriz de barramento AHB e APB, onde o primeiro é mais produtivo e é utilizado para comunicar componentes internos de alta velocidade, e o último para periféricos (dispositivos de entrada/saída). O controlador possui 4 ADCs de 12 bits (5 Mbit/s) e um sensor de temperatura, 7 comparadores (GP Comparator1 ... 7), 4 programáveis amplificador operacional(OpAmp1...4) (PGA (Programmable Gain Array)), 2 canais de 12 bits DAC (DAC), RTC (relógio de tempo real), dois temporizadores de watchdog - independentes e de janela (WinWatchdog e Ind. WDG32K), 17 gerais temporizadores de propósito e multifuncional.

Em termos gerais, analisamos a arquitetura do controlador. Agora veja as bibliotecas de software disponíveis. Feita uma visão geral, podemos destacar: CMSIS, SPL e HAL. Vamos considerar cada aplicação em exemplo simples LED piscando.

1). CMSIS(Cortex Microcontroller Software Interface Standard) - biblioteca padrão para Cortex®-M. Fornece suporte ao dispositivo e simplifica interfaces de software. CMSIS fornece resultados consistentes e interfaces simples para o núcleo, sua periferia e sistemas operacionais tempo real. Seu uso é uma forma profissional de escrever programas, pois... envolve escrita direta em registros e, portanto, é necessária leitura e estudo constante de fichas técnicas. Independente do fabricante do hardware.
CMSIS inclui os seguintes componentes:
- CMSIS-CORE: Inicialização consistente do sistema e acesso periférico;
- CMSIS-RTOS: Execução Determinística de Software em Tempo Real programas tempo real);
- CMSIS-DSP: Implementação rápida de processamento digital de sinais processamento digital sinais);
- CMSIS-Driver: Interfaces periféricas genéricas para middleware e código de aplicação (Interfaces periféricas gerais para middleware e código de aplicação);
— CMSIS-Pack: Fácil acesso a componentes de software reutilizáveis ​​(Fácil acesso a componentes de software reutilizáveis);
— CMSIS-SVD: Visão consistente para dispositivo e periféricos (representação consistente de dispositivos e periféricos);
- CMSIS-DAP: Conectividade com hardware de avaliação de baixo custo. Software de depuração.

Por exemplo, vamos escrever um programa - piscar um LED. Para isso precisamos de documentação descrevendo os registradores. No meu caso RM0316 Manual de referência STM32F303xB/C/D/E, STM32F303x6/8, STM32F328x8, STM32F358xC, STM32F398xE MCUs avançados baseados em ARM ®, bem como uma descrição da perna específica pela qual é responsável DS9118: Cortex®-M4 32b MCU + FPU baseado em ARM®, até 256 KB Flash + 48 KB SRAM, 4 ADCs, 2 canais DAC, 7 comp, 4 PGA, temporizadores, 2,0-3,6 V. Para começar, vamos cronometrar a porta no programa, pois Por padrão, tudo está desabilitado, o que reduz o consumo de energia. Abra o Manual de Referência e observe a seção Reset e controle de clock, depois o mapa de registros RCC e veja qual registro é responsável por habilitar o IOPEEN

Passemos à descrição do clock dos periféricos deste registro Registro de ativação de relógio periférico AHB (RCC_AHBENR), onde vemos que esta porta está abaixo do 21º bit. Ligue RCC->AHBENR|=(1<<21) . Далее сконфигурируем регистры GPIO. Нас интересует три: GPIOE_MODER и GPIOx_ODR . C помощью них повторим программу с предыдущей статьи, затактируем PE8. Первый отвечает за конфигурацию входа выхода, выбираем 01: General purpose output mode. GPIOE->MODERADOR|=0×10000 . A segunda é para ativar o nível baixo/alto na perna. Abaixo está o programa:

#include "stm32f3xx.h " //Arquivo de cabeçalho do microcontrolador
não assinado int i;
atraso vazio() (
para (eu=0;eu<500000;i++);
}
int principal (vazio) (
RCC->AHBENR|=(1<<21);
GPIOE->MODER|=0×10000;
enquanto (1)(
atraso();
GPIOE->ODR|=0×100;
atraso();
GPIOE->ODR&=~(0×100);
} }

2). SPL(Biblioteca de periféricos padrão)- esta biblioteca destina-se a combinar todos os processadores da ST Electronics.

Projetado para melhorar a portabilidade do código e destinado principalmente a desenvolvedores iniciantes. A ST está trabalhando em um substituto para o SPL chamado "camada baixa" que é compatível com HAL. Os drivers Low Layer (LL) são projetados para fornecer uma camada quase leve e orientada para especialistas, mais próxima do hardware do que o HAL. Além do HAL, APIs LL também estão disponíveis. Um exemplo do mesmo programa em SPL.
Projetado para melhorar a portabilidade do código e destinado principalmente a desenvolvedores iniciantes. A ST está trabalhando em um substituto para o SPL chamado "camada baixa" que é compatível com HAL. Os drivers Low Layer (LL) são projetados para fornecer uma camada quase leve e orientada para especialistas, mais próxima do hardware do que o HAL. Além do HAL, APIs LL também estão disponíveis. Um exemplo do mesmo programa em SPL.
Projetado para melhorar a portabilidade do código e destinado principalmente a desenvolvedores iniciantes. A ST está trabalhando em um substituto para o SPL chamado "camada baixa" que é compatível com HAL. Os drivers Low Layer (LL) são projetados para fornecer uma camada quase leve e orientada para especialistas, mais próxima do hardware do que o HAL. Além do HAL, APIs LL também estão disponíveis. Um exemplo do mesmo programa em SPL.
#incluir
#define LED GPIO_Pin_8
int principal() (
muito tempo eu;
GPIO_InitTypeDef gpio;
// LED azul está conectado à porta E, pino 8 (barramento AHB)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
//Configura a porta E (LED) GPIO_StructInit(&gpio);
//declara e inicializa uma variável de estrutura de dados
gpio.GPIO_Mode=GPIO_Mode_OUT;
gpio.GPIO_Pin = LED;
GPIO_Init(GPIOE, &gpio);
//LEDs piscando
enquanto (1) (
// Sobre
GPIO_SetBits(GPIOE,LED);< 500000; i++);
para (eu = 0; eu
//Tudo desligado
GPIO_SetBits(GPIOE,LED);< 500000; i++);
} }

GPIO_ResetBits(GPIOE,LED); Cada função está descrita na documentação técnica Manual do usuário UM1581 Descrição da biblioteca periférica padrão STM32F30xx / 31xx

3). . Aqui conectamos três arquivos de cabeçalho que contêm os dados necessários, estruturas, funções de reset e controle de sincronização, bem como para configurar portas de entrada/saída. HAL- (Nível de acesso de hardware, camada de abstração de hardware)
- Outra biblioteca comum para desenvolvimento. Com o qual também foi lançado o programa CubeMX para a configuração que utilizamos no último artigo. Lá também escrevemos um programa para piscar um LED usando esta biblioteca. Como podemos ver na figura abaixo, o cubo gera drivers HAL e CMSIS. Bem, vamos descrever os principais arquivos utilizados: - system_stm32f3x.c e sistema_stm32f3x.h
- fornecer conjuntos mínimos de funções para configurar o sistema de cronometragem;
— core_cm4.h – fornece acesso aos registros do núcleo e seus periféricos;
- stm32f3x.h – arquivo de cabeçalho do microcontrolador;

— startup_system32f3x.s — código de inicialização, contém uma tabela de vetores de interrupção, etc.
#include "principal.h"
#include "stm32f3xx_hal.h" vazio SystemClock_Config(void);
/*Declara funções de configuração do relógio*/ vazio estático MX_GPIO_Init (void);
/*Inicializar E/S*/
int principal (vazio) (
/*Reset de todos os periféricos, Inicializa a interface Flash e o Systick.*/
HAL_Init();
/* Configura o relógio do sistema */
SystemClock_Config();
/* Inicializa todos os periféricos configurados */
MX_GPIO_Init();
enquanto (1) ( //Muda o estado da perna
HAL_Atraso(100); )
}
vazio SystemClock_Config (vazio){
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
se (HAL_RCC_OscConfig (& RCC_OscInitStruct)! = HAL_OK){

}
/**Inicializa os clocks dos barramentos CPU, AHB e APB */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
se (HAL_RCC_ClockConfig (& RCC_ClkInitStruct, FLASH_LATENCY_0)! = HAL_OK){
_Error_Handler(__FILE__, __LINE__);
}
/**Configurar o tempo de interrupção do Systick*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configurar o Systick */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* Configuração de interrupção SysTick_IRQn */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/** Configurar pinos como entrada analógica e saída EVENT_OUT EXTI */
vazio estático MX_GPIO_Init (vazio){
GPIO_InitTypeDef GPIO_InitStruct;
/* Ativação do relógio das portas GPIO */
__HAL_RCC_GPIOE_CLK_ENABLE();
/*Configurar nível de saída do pino GPIO */
HAL_GPIO_WritePin (GPIOE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*Configurar pinos GPIO: PE8 PE9 PE10 PE11 PE12 PE13 PE14 PE15 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Speed ​​​​= GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}
void _Error_Handler(char * arquivo, linha int){
MX_GPIO_Init();
} }
#ifdef USE_FULL_ASSERT

Void assert_failed (arquivo uint8_t*, linha uint32_t){
}
#endif
Aqui, assim como no exemplo anterior, podemos visualizar a descrição de cada função na documentação, por exemplo Manual do usuário UM1786 Descrição do STM32F3 HAL e drivers de camada baixa.

Podemos resumir que a primeira opção, utilizando CMSIS, é menos complicada. Existe documentação para cada biblioteca. Em projetos subsequentes usaremos HAL e CMSIS usando o programa de configuração STCube e, se possível, usaremos registros diretamente, sem wrappers de software. Vamos parar por aí hoje. No próximo artigo veremos os princípios básicos da construção de uma casa inteligente. Tchau a todos.

Indiquei que a biblioteca padrão está conectada ao sistema. Na verdade, o CMSIS, um sistema de representação estrutural generalizada do MK, está conectado, bem como o SPL, uma biblioteca periférica padrão. Vejamos cada um deles:

CMSIS
É um conjunto de arquivos de cabeçalho e um pequeno conjunto de códigos para unificar e estruturar o trabalho com o núcleo e a periferia do MK. Na verdade, sem esses arquivos é impossível trabalhar normalmente com o MK. Você pode obter a biblioteca na página de documentação que acompanha o MK.
Esta biblioteca, conforme a descrição, foi criada para unificar interfaces ao trabalhar com qualquer MK da família Cortex. No entanto, na realidade verifica-se que isto só é verdade para um fabricante, ou seja, Ao mudar para um microcontrolador de outra empresa, você é forçado a estudar seus periféricos quase do zero.
Embora os arquivos relacionados ao núcleo do processador do MK sejam idênticos de todos os fabricantes (até porque possuem o mesmo modelo de núcleo do processador - fornecido na forma de blocos IP pela ARM).
Portanto, trabalhar com partes do kernel como registradores, instruções, interrupções e unidades de coprocessador é padrão para todos.
Quanto à periferia, o STM32 e o STM8 (de repente) são quase semelhantes, e isso também é parcialmente verdade para outros MKs lançados pela ST. Na parte prática mostrarei como é fácil utilizar o CMSIS. No entanto, as dificuldades em utilizá-lo estão associadas à relutância das pessoas em ler a documentação e compreender o design do MK.

SPL
Biblioteca Periférica Padrão - biblioteca periférica padrão. Como o nome sugere, o objetivo desta biblioteca é criar uma abstração para a periferia MK. A biblioteca consiste em arquivos de cabeçalho onde são declaradas constantes legíveis para configurar e trabalhar com periféricos MK, bem como arquivos código fonte coletados na própria biblioteca para operações com periféricos.
SPL é uma abstração do CMSIS, apresentando ao usuário uma interface comum para todos os MCUs, não apenas de um fabricante, mas geralmente todos os MCUs com núcleo de processador Cortex-Mxx.
Acredita-se que seja mais conveniente para iniciantes, pois... permite não pensar em como funcionam os periféricos, mas na qualidade do código, na universalidade da abordagem e na restrição das interfaces impõem certas restrições ao desenvolvedor.
Além disso, a funcionalidade da biblioteca nem sempre permite implementar com precisão a configuração de alguns componentes, como USART (universal síncrono-assíncrono porta serial) sob certas condições. Na parte prática também descreverei como trabalhar com esta parte da biblioteca.