A maior rede de estudos do Brasil

Grátis
256 pág.
Descobrindo o STM32

Pré-visualização | Página 40 de 47

pode produzir qualquer entrada entre 0 e 3,3 V.
A aplicação irá ler continuamente a entrada analógica e, se for acima
de 3, 3/2 Volts, acender o LED verde, ou desligar o LED caso contrário. Até
agora você já deve saber como fazer o seguinte:
• Configurar os clocks para GPIOA, GPIOC, e o ADC.
• Configurar a porta PA6 como entrada analógica.
• Configure a porta PC9 como saída push/pull.
Configurar o ADC segue um padrão familiar:
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv =
↪→ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// Configure ADC_IN6
ADC_RegularChannelConfig(ADC1, ADC_Channel_6 , 1,
↪→ADC_SampleTime_55Cycles5);
// Enable ADC
ADC_Cmd(ADC1, ENABLE);
Observe que ao configurar o canal, temos que selecionar um “tempo de
amostragem”. O mínimo para 12 bits de precisão é um tempo de amostragem
de 13,5 ciclos. Escolhendo o tempo de amostragem “certo” pode ser compli-
cado se é desejável combinar velocidade e precisão. Nossas exigências para
este exemplo são pequenas.
214 Revision: (None) ((None))
14.1. SOBRE ADCS DE APROXIMAÇÃO SUCESSIVAS
Ao contrário de outros periféricos, o ADC precisa ser calibrado. O
hardware suporta calibração automática como mostrado no código a seguir.
Novamente para este exemplo, nós provavelmente podemos dispensar calibra-
ção.
Revision: (None) ((None)) 215
CAPÍTULO 14. ADC : CONVERSÃO ANALÓGICA DIGITAL
// Check the end of ADC1 reset calibration register
while(ADC_GetResetCalibrationStatus(ADC1));
// Start ADC1 calibration
ADC_StartCalibration(ADC1);
// Check the end of ADC1 calibration
while(ADC_GetCalibrationStatus(ADC1));
O que resta é ler o resultado da conversão:
ain = ADC_GetConversionValue(ADC1);
Só resta então criar um aplicativo funcional.
Exercise 14.2 Conversão Dirigida pelo Timer
Neste exercício, iremos converter o exercício anterior, para ser dirigido
por um temporizador com um manipulador de interrupção para executar sem-
pre que a conversão for concluída. Nós teremos que alterar um pouco o código
de inicialização do ADC, configurar um temporizador, e configurar o NVIC.
Você deve configurar o NVIC para habilitar ADC1_IRQn – a prioridade
específica é relativamente pouco importante. Configure TIM3 para gerar um
evento TRG0 a cada 1ms. Configure o ADC como se segue:
216 Revision: (None) ((None))
14.1. SOBRE ADCS DE APROXIMAÇÃO SUCESSIVAS
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv =
ADC_ExternalTrigConv_T3_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6 , 1,
ADC_SampleTime_55Cycles5);
ADC_ITConfig(ADC1, ADC_IT_EOC , ENABLE);
ADC_ExternalTrigConvCmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
Mova o código que alterna a LED para um manipulador de interrupção
com a seguinte estrutura:
void ADC1_IRQHandler(void)
{
// read ADC DR and set LED accordingly
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
}
Exercise 14.3 Gravador de Voz
TBD
Revision: (None) ((None)) 217
Capítulo 15
NewLib
Ao longo deste livro temos trabalhado sem as bibliotecas-padrão C
(libc), apesar de uma implementação dela ser distribuída com as ferramentas
Sourcery que utilizamos para a construção dos projetos. A principal razão
para termos evitado a biblioteca (libc), até agora, é manter a clareza sobre
qual código estamos realmente executando – como veremos, o uso da libc
pode rapidamente levar a ocultação dos códigos. Uma segunda razão é que a
libc é uma devoradora de memória – com apenas 8k de SRAM disponível no
processador da Discovery Board, não há muito espaço de sobra. No entanto, a
primeira consideração é agora discutível – você teve uma introdução bastante
completa sobre como escrever códigos para o STM32, e a segunda consideração
é muito menos importante, se você passar para os membros maiores da família
de processadores STM32. Há muitas vantagens em usar a libc incluindo o
acesso às funções da biblioteca padrão.
A implementação da libc distribuída com as ferramentas Sourcery e
amplamente utilizada para sistemas embarcados é a “newlib”. A newlib inclui
as stdlib (p. ex.: abs, atoi, atoll, malloc, e suporte a unicode ), stdio
(printf, sprintf, scanf, ...), suporte a string, e muitos outras. A newlib
também inclui uma implementação da biblioteca matemática padrão, libm.
Infelizmente, as funções stdio são devoradoras de memória visto que elas
alocam grandes buffers de memória para suportar os sistemas de I/O. Além
disso, por padrão (por exemplo, a distribuição Sourcery) a newlib não está
configurada para minimizar o uso de memória. Assim, também mostraremos
como compilar a newlib a partir do código fonte de maneira a otimizar o uso
da memória.
A arquitetura da newlib requer uma implementação externa das prin-
cipais funções do sistema, incluindo – open, close, read, write, e sbrk – o
Revision: (None) ((None)) 219
CAPÍTULO 15. NEWLIB
último deles é o alicerce sobre o qual a malloc é construída. A fim de usar
a libc, é necessário fornecer pelo menos um esboço para estas e outras fun-
ções. Vamos mostrar como projetar esses esboços para suportar o I/O padrão
utilizando a USART da STM32.
Este capítulo está organizado da seguinte forma. Vamos começar com
um exemplo simples – “hello world” (surpresa!) para mostrar os problemas que
precisam ser resolvidos, a fim de usar a newlib, e os problemas de memória que
ele suscita. Lembre-se que, no Capítulo 3, salientou-se que “hello world” é na
verdade um programa complexo, embora a maioria da complexidade esta “sob
o capô”. Finalmente, vamos mostrar como compilar a libc de uma maneira
que minimize os requisitos de memória (especialmente SRAM). Se você for
usar a libc em uma variante do STM32 com SRAM substancial (pelo menos
20k), este passo é desnecessário – você pode usar as bibliotecas distribuídas
com as ferramentas Sourcery.
15.1 Hello World
“Hello World” é o exemplo de programação mais famoso no universo
C. Como dissemos no Capítulo 3, é realmente muito complexo. Considere o
programa:
#include <stdio.h>
main() {
printf("hello world\n");
}
printf é uma função da biblioteca que recebe uma string de formato e
uma lista opcional de parâmetros. Deve transformar esses parâmetros em uma
única string fundindo com a string de formato, e escrever a string resultante
para a stdout. O que é stdout ? É uma “buffered stream” – as bibliotecas
stdio gerenciam buffered streams (fluxos de buffers). Os dados são bufferi-
zados a medida em que são escritos, e então os dados no buffer são gravados
em um arquivo ou dispositivo. Neste caso, a nossa intuição é que este fluxo
deve estar de alguma forma ligado a uma UART para imprimir em uma tela
em algum lugar. Enquanto o nosso uso de printf é trivial, invocações mais
complexas alocam memória, a fim de ter espaço para a realização de todas as
conversões.
Se tentarmos compilar “hello world” (crie um projeto e tente isso !), sa-
beremos de imediato que há uma série de funções indefinidas (Listagem 15.1).
220 Revision: (None) ((None))
15.1. HELLO WORLD
undefined reference to `_sbrk'
undefined reference to `_write'
undefined reference to `_close'
undefined reference to `_fstat'
undefined reference to `_isatty'
undefined reference to `_lseek'
undefined reference to `_read'
Listing 15.1: Undefined Functions in newlib
Em um ambiente desktop, todos eles correspondem às chamadas do
sistema operacional – libc é apenas uma biblioteca

Crie agora seu perfil grátis para visualizar sem restrições.