Subversion Repositories Projects

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed


#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#include "analog.h"

volatile uint16_t Adc0, Adc1, Adc2, Adc3, Adc4, Adc5, Adc6, Adc7;
volatile uint8_t ADReady = 1;

/*****************************************************/
/*     Initialize Analog Digital Converter           */
/*****************************************************/
void ADC_Init(void)
{
        uint8_t sreg = SREG;
        // disable all interrupts before reconfiguration
        cli();
        //ADC0 ... ADC7 is connected to PortA pin 0 ... 7
        DDRA = 0x00;
        PORTA = 0x00;
        // Digital Input Disable Register 0
        // Disable digital input buffer for analog adc_channel pins
        DIDR0 = 0xFF;
        // external reference AREF, adjust data to the right
    ADMUX &= ~((1 << REFS1)|(1 << REFS0)|(1 << ADLAR));
    // set muxer to ADC adc_channel 0 (0 to 7 is a valid choice)
    ADMUX = (ADMUX & 0xE0) | 0x00;
    //Set ADC Control and Status Register A
    //Auto Trigger Enable, Prescaler Select Bits to Division Factor 128, i.e. ADC clock = SYSCKL/128 = 156.25 kHz
        ADCSRA = (0<<ADEN)|(0<<ADSC)|(0<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(0<<ADIE);
        //Set ADC Control and Status Register B
        //Trigger Source to Free Running Mode
        ADCSRB &= ~((1 << ADTS2)|(1 << ADTS1)|(1 << ADTS0));
        // Start AD conversion
        ADC_Enable();
    // restore global interrupt flags
    SREG = sreg;
}

/*****************************************************/
/*     Interrupt Service Routine for ADC             */
/*****************************************************/
// runs at 312.5 kHz or 3.2 µs
// if after (60.8µs) all 19 states are processed the interrupt is disabled
// and the update of further ads is stopped


#define ADC0    0
#define ADC1    1
#define ADC2    2
#define ADC3    3
#define ADC4    4
#define ADC5    5
#define ADC6    6
#define ADC7    7

ISR(ADC_vect)
{
    static uint8_t ad_channel = ADC0, state = 0;

    // state machine
        switch(state++)
        {
                case 0:
                        Adc0 = ADC;
                        ad_channel = ADC1;
                        break;
                case 1:
                        Adc1 = ADC;
                        ad_channel = ADC2;
                        break;
                case 2:
                        Adc2 = ADC;
                        ad_channel = ADC3;
                        break;
                case 3:
                        Adc3 = ADC;
                        ad_channel = ADC4;
            break;
                case 4:
                        Adc4 = ADC;
                        ad_channel = ADC5;
                        break;
                case 5:
                        Adc5 = ADC;
                        ad_channel = ADC6;
                        break;
                case 6:
                        Adc6 = ADC;
                        ad_channel = ADC7;
                        break;
                case 7:
                        Adc7 = ADC;
                        ad_channel = ADC0;
                        state = 0;
                        ADReady = 1;
            break;
                default:
                        ad_channel = ADC0;
                        state = 0;
                        ADReady = 1;
                        break;
        }
    // set adc muxer to next ad_channel
    ADMUX = (ADMUX & 0xE0) | ad_channel;
    // after full cycle stop further interrupts
    if(state != 0) ADC_Enable();
}