Pular para conteúdo

Conversor Analógico Digital (ADC)

O conversor analógico digital realiza conversão por aproximação sucessiva utilizando uma resolução de 10 bits.

Possui 8 canais, associados ao PORTA, multiplexados ao conversor, com circuito que garante o valor da amostra durante o tempo de conversão.

A referência de tensão do conversor é o GND e a tensão de fundo de escala pode ser aplicada ao pino AVcc ou através de uma tensão de referência interna de 1.1V.

Um diagrama simplificado pode ser visto na Figura 1.

Figura 1: Diagrama de blocos simplificado do ADC
DiagramaDeBlocos
Fonte: Adaptado pelo autor de Datasheet

Os registradores de configuração do ADC são:

Figura 2: ADC Multiplexer Selection Register
DiagramaDeBlocos
Fonte: Datasheet
Figura 3: DC Control and Status Register A
DiagramaDeBlocos
Fonte: Datasheet
Figura 4: Digital Input Disable Register 0
DiagramaDeBlocos
Fonte: Datasheet

Código fonte de exemplo

main.c
#include "lcd.h"
#include "adc.h"

int main(void)
{
    adc_init();
    lcd_init();

    lcd(0,0," x:      y:     ");

    while( 1 )
    {
        if( adc_available() )
        {
            lcd_num(0, 4,adc_ch0(),4);
            lcd_num(0,11,adc_ch1(),4);
            adc_start();
        }
    }
    return( 0 );
}
bits.h
#ifndef BITS_H
#define BITS_H

#define BITVAL(bit)         (1<<bit)

#define SETBIT(var,bit)     (var |=  (1<<bit))
#define CLRBIT(var,bit)     (var &= ~(1<<bit))
#define TOGBIT(var,bit)     (var ^=  (1<<bit))
#define TSTBIT(var,bit)     (var &   (1<<bit))

#endif
adc.h
#ifndef ADC_H
#define ADC_H

void adc_init();
void adc_start( void );
char adc_available( void );
int adc_ch0( void );
int adc_ch1( void );

#endif
adc.c
#include <avr/io.h>
#include <avr/interrupt.h>
#include "adc.h"
#include "bits.h"


// -------------------------------------- Vars
unsigned int adc0_value = 0;
unsigned int adc1_value = 0;
unsigned int adc_value;
unsigned char adc_available_flag = 0;



// -------------------------------------- adc_init
    // Seleção de tensão de referência
#define ADC_AVCC    BITVAL(REFS0)
#define ADC_1V1     (BITVAL(REFS1)|BITVAL(REFS0))
#define ADC_AREF    0

// Seleção de canal para conversao
#define ADC_CH0     0
#define ADC_CH1     1
#define ADC_CH2     2
#define ADC_CH3     3
#define ADC_CH4     4
#define ADC_CH5     5


    // Ajuste de bits (Left Adjust Result)
#define ADC_LAR    BITVAL(ADLAR)

// --------------------------------------
    // Habilita conversor AD
#define ADC_EN      BITVAL(ADEN)
    // Inicia a conversao AD
#define ADC_START   BITVAL(ADSC)
    // Habilita Trigger Automatico
#define ADC_ATE     BITVAL(ADATE)
    // Habilita Interrupcao
#define ADC_IE      BITVAL(ADIE)
    // Fator de divisao - ADC Prescaler
#define ADC_FREQ_DIV_2      0x1
#define ADC_FREQ_DIV_4      0x2
#define ADC_FREQ_DIV_8      0x3
#define ADC_FREQ_DIV_16     0x4
#define ADC_FREQ_DIV_32     0x5
#define ADC_FREQ_DIV_64     0x6
#define ADC_FREQ_DIV_128    0x7



// -------------------------------------- adc_init
void adc_init( void )
{
    cli();
    ADMUX = (ADC_AVCC | ADC_CH1 );
    ADCSRA = (ADC_EN | ADC_IE | ADC_FREQ_DIV_128);
    sei();
    adc_start();
}



// -------------------------------------- adc_start
void adc_start( void )
{
    SETBIT(ADMUX, MUX0);        // CH1
    SETBIT(ADCSRA, ADSC);       // START
    adc_available_flag = 0;
}



// -------------------------------------- adc_interrupt
ISR( ADC_vect )
{
    adc_value = ADC;
    if( TSTBIT(ADMUX, MUX0) )   // CH1
    {
        adc1_value = adc_value;
        CLRBIT(ADMUX, MUX0);        // CH0
        SETBIT(ADCSRA, ADSC);       // START
    }
    else                        // CH0
    {
        adc0_value = adc_value;
        adc_available_flag = 1;
    }
}



// -------------------------------------- adc available
char adc_available( void )
{
    return( adc_available_flag );
}


// -------------------------------------- adc result
int adc_ch0( void )
{
    return( adc0_value );
}
int adc_ch1( void )
{
    return( adc1_value );
}