Search code examples
cavratmegaadc

AVR in C - Storing value of register in variable


I'm using an ATmega328. I am currently doing several measurements using the 10-bit ADC. I would like to store the values it converts in variables in order to be able to operate with them. For example:

int a;
(...)
ADMUX = 0b01000011; //Vref = 5V, ADC3
ADCSRA |= (1<<ADSC); //Starts conversion
while(!(ADCSRA & (1<<ADIF))); //Wait until it finishes
ADCSRA |= (1<<ADIF); //Clear flag

Suppose that the ADC stored the value 576 in ADCH:ADCL. Is it possible to achieve, somehow, the variable a to take that same value? (i.e. a=576;).


Solution

  • The full 16-bit result register should be accessible as such:

    a = ADC;
    

    But if you want to read both parts manually, then

    a = ADCL;
    a |= ADCH << 8;
    

    That has to be done in two separate statements to force ADCH to be read last. The I/O modules have a temporary register to hold the high byte, preventing the module itself from corrupting the read value if it changes the value of the register. (i.e. if the ADC finishes another conversion and stores the new value.)

    If you have interrupts that access the ADC (or need to use the value at a), you'll need to disable them for the duration of the access (that also goes for a = ADC, since it also compiles into multiple 8-bit reads).