Olá caro leitor, este é segundo artigo da série Bibliotecas de Software para FRDM-KL25Z, onde apresentamos as bibliotecas para ADC da FRDM-KL25Z (Freedom Board KL25Z).
Como já foi dito no artigo anterior, essa biblioteca é parte de um conjunto de bibliotecas para outra biblioteca que estou desenvolvendo, para utilizar a FRDM-KL25Z em conjunto com o KiT de Automação Open Hardware.
No primeiro artigo foram apresentadas as funções de acesso aos pinos GPIO (General Purpose Input/Output). E neste segundo vamos apresentar as funções de leitura dos canais do Conversor Analógico Digital (ADC).
As bibliotecas apresentadas são compatíveis com o Kinetis Design Studio IDE e CodeWarrior IDE. Também são facilmente portáveis para as demais placas Freedom Board. Essa biblioteca foi desenvolvida com base na série de artigos sobre o Desenvolvimento de sistemas embarcados com a KL05Z, escrita pelo Rodrigo Almeida.
Conversor Analógico Digital
O microcontrolador presente na Freedom Board FRDM-KL25Z possui conversor analógico digital de 16 bits por Aproximação Sucessiva (SAR ADC) e 14 canais. O ADC suporta tanto gatilhos de software quanto de hardware.
Inicializando o ADC
A seguir serão apresentadas as configurações mínimas para realizar a leitura do conversor analógico digital.
Configurando o CLOCK
O primeiro passo a ser dado é configurar o clock para o periféricos ADC. Para realizar operação deve configurar o registrador SIM_SCGC6 (System Clock Gating Control Register 6). Essa operação deve ser feita utilizando a macro SIM_SCGC5_ADC0_MASK.

A seguir o código fonte demonstrando essa operação:
/* Habilita Clock para ADC */ SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK;
Configurando o ADC
Para configurar o modo de operação do ADC deve-se usar o registrador ADC0_CFG1. Nesse registrador vamos configurar os seguintes itens: resolução da conversão, a fonte de clock e divisor do Clock.

Para configurar a resolução da conversão do ADC, são destinados dois bits do registrador ADC0_CFG1. São os bits 2 e 3 (item MODE do registrador). A seguir a tabela com as opções resoluções do conversor analógico digital.
Essa configuração dever ser feita utilizando a macro ADC_CFG1_MODE( n ). A variável n é o valor descrito na tabela.

Configurando a fonte de clock
Para configurar a fonte de Clock, são reservados os dois primeiros bits do registrador ADC0_CFG1 (1 – 0 ADICLOK). Essa configuração dever ser feita utilizando a macro ADC_CFG1_ADICLK( n ). A variável n é o valor descrito na tabela.

Divisor do Clock
O último item a ser configurado é o divisor interno do Clock do ADC. Este também é configurado em dois bits do registrador ADC0_CFG1, é o item ADIV. Essa configuração dever ser feita utilizando a macro ADC_CFG1_ADIV( n ). A variável n é o valor descrito na tabela.

/* Configurando o ADC */ ADC0_CFG1 |= (ADC_CFG1_MODE(3) | // 16 bits mode ADC_CFG1_ADICLK(0)| // Input Bus Clock ADC_CFG1_ADIV(1)) ; // Clock divide
A seguir o código fonte header:
/* */ #ifndef SOURCES_ADC_H_ #define SOURCES_ADC_H_ #include "MKL25Z4.h" #define ADC_0 0 // PTE20 #define ADC_1 4 // PTE21 #define ADC_2 3 // PTE22 #define ADC_3 7 // PTE23 #define ADC_4 8 // PTB0 #define ADC_5 9 // PTB1 #define ADC_6 12 // PTB2 #define ADC_7 13 // PTB3 #define ADC_8 14 // PTC0 #define ADC_9 15 // PTC1 #define ADC_10 11 // PTC2 #define ADC_11 5 // PTD1 LED AZUL FRDM-KL25Z //#define ADC_12 6 // PTD5 //#define ADC_13 7 // PTD6 #define _8BIT 0 #define _10BIT 1 #define _12BIT 2 #define _16BIT 3 void adc_init(uint8_t res); uint16_t adc_read(uint16_t ch); //int adc_cal(void); #endif /* SOURCES_ADC_H_ */
Código fonte da função de inicialização adc_init():
/*
*/
void adc_init(uint8_t res)
{
// Enable clocks
SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; // ADC 0 clock
// Configure ADC
ADC0_CFG1 = 0; // Reset register
ADC0_CFG1 |= (ADC_CFG1_MODE(res) | // resolução da conversão
ADC_CFG1_ADICLK(0) | // Input Bus Clock
ADC_CFG1_ADIV(1)); // Clock divide by 2
ADC0_SC3 = 0; // Reset SC3
ADC0_SC1A |= ADC_SC1_ADCH(31); // Disable module
}
Lendo o ADC
Uma vez criada a função para inicializar o conversor analógico digital, agora devemos criar a função para realizar a leitura dos canais ADC.
A seguir o código fonte da função para realizar a leitura do canal ADC:
/* */
uint16_t adc_read(uint16_t ch)
{
ADC0_SC1A = ch & ADC_SC1_ADCH_MASK; //Write to SC1A to start conversion
while(ADC0_SC2 & ADC_SC2_ADACT_MASK); // Conversion in progress
while(!(ADC0_SC1A & ADC_SC1_COCO_MASK)); // Run until the conversion is complete
return ADC0_RA;
}
A função adc_read recebe como parâmetro o número do canal a ser lido e retorna o resultado da conversão.
Na primeira linha temos o registrador ADC0_SC1A, que é responsável iniciar a conversão. Esse registador recebe o resultado da operação “and” entre o número do canal a ser lido e a macro “ADC_SC1_ADCH_MASK”. Essa operação tem como objetivo escrever nos bits ADCH do registrador.

Na segunda linha verifica-se se a conversão está em andamento. Nesta etapa vamos checar o registrador ADC0_SC2, especificamente o bit ADACT. Para realizar esta tarefa deve-se utilizar a macro ADC_SC2_ADACT_MASK.

Na terceira linha fica aguardando o termino da conversão. Essa etapa verifica o bit COCO do registrador ADC0_SC1A. Para essa etapa deve utilizar a macro ADC_SC1_COCO_MASK.
E por fim, na ultima linha é retornado o conteúdo do registrador ADC0_RA, que contém o resultado da conversão.
Exemplo de Aplicação
O projeto que demostra o usa da biblioteca ADC é bem simples. O seu algoritmo é:
- Realiza a leitura do canal ADC_5 (PTB1);
- Se o valor do resultado da conversão for maior do 50000, acende o led vermelho e apaga o led verde;
- Caso o valor seja menor, apaga o led vermelho e acende o led verde.
A seguir o código fonte do projeto:
/*
Projeto: Aplicação com Biblioteca ADC
*/
#include "MKL25Z4.h"
#include "adc.h"
#include "gpio.h"
uint16_t adc = 0;
int main(void)
{
adc_init( _16BIT ); // Inicializa ADC
gpio_direction(PORT_B,18,OUTPUT,NO_PULL_RESISTOR); // Inicializa IO PTB18 - LED Vermelho
gpio_direction(PORT_B,19,OUTPUT,NO_PULL_RESISTOR); // Inicializa IO PTB19 - LED Verde
gpio_set(PORT_B,19,1); // Desliga LED vermelho
gpio_set(PORT_B,18,1); // Desliga LED verde
for (;;)
{
adc = adc_read( ADC_5 ); // Le ADC ~ PTB1
if(adc > 50000)
{
gpio_set(PORT_B,19,0); // Liga LED vermelho
gpio_set(PORT_B,18,1); // Desliga LED verde
}
else
{
gpio_set(PORT_B,18,0); // Liga LED verde
gpio_set(PORT_B,19,1); // Desliga LED vermelho
}
}
}
Conclusão
Neste artigo foi apresentada a biblioteca do conversor analógico digital para a Freedom Board KL25Z e projeto para demonstrar a utilização da biblioteca.
Nos próximos artigos vamos apresentar outras bibliotecas (DAC, Timer, UART e entre outras) para serem utilizadas com esse hardware.
E por fim fica o meu convite para você leitor a contribuir com o desenvolvimento dessa biblioteca. Seja simplesmente testando ou colocando a mão na massa, melhorando as funções existentes ou até criando novas. A biblioteca se encontra no meu GitHub.
Referências
FRDM-KL25Z
Reference Manual
Diretório do GitHub
https://en.wikipedia.org/wiki/Successive_approximation_ADC
https://community.nxp.com/docs/DOC-102951




