0
\$\begingroup\$

I am using a simple code to read from ADC pin A0. When I read from ADCH and ADCL. The result is correct only once in the startup. When I change the analog value in A0, output from the ADC don't change at all. Unless I have reset the mcu.

In the datasheet it is not state clearly that there is a register called ADC. They highlight ADCH and ADCL.

reading from register ADC work fine.

This is my simple code that don't work.

/*
 * Section: Function Defintion
 */
void ADC_Setup(){
    // Enable the ADC
    ADCSRA |= 1<<ADEN;
    // Select the refence voltage to be AVcc, which is connected to Vcc in the Arduino Nano board
    ADMUX |= 1<<REFS0;
    // Set Prescaler to 128, so that the ADC clock is 16M/128= 125Khz
    ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
    ADCSRA |= (1<<ADSC) | (1<<ADATE) | (1<<ADIF) | (1<<ADIF);
    sei();
    
}
void ADC_StartConvert(){
    ADCSRA |= (1<<ADSC);
}
uint16_t ADC_read(){
    uint16_t i = ADCH*256 + ADCL;
    // if changed to i = ADC; it work fine!!
    return i;
}

What is could be the cause to make the ADC hold conversion because of reading from ADCL?

\$\endgroup\$
3
  • \$\begingroup\$ use "(((uint16_t)(ADCH))<<8 +ADCL)" \$\endgroup\$
    – Deepak
    Oct 5 '20 at 14:50
  • 2
    \$\begingroup\$ I whoud try this uint16_t i = (uint16_t) (ADCL + (ADCH*256)); becouse ADCL must be read first, then ADCH \$\endgroup\$
    – G36
    Oct 5 '20 at 15:09
  • \$\begingroup\$ @G36, thanks it worked. However, no any logical explanation for this. \$\endgroup\$ Oct 5 '20 at 21:20
1
\$\begingroup\$

ADCL must be read first before ADCH, as stated in the datasheet.

Use this code

/*
 * Section: Function Defintion
 */
void ADC_Setup(){
    // Enable the ADC
    ADCSRA |= 1<<ADEN;
    // Select the refence voltage to be AVcc, which is connected to Vcc in the Arduino Nano board
    ADMUX |= 1<<REFS0;
    // Set Prescaler to 128, so that the ADC clock is 16M/128= 125Khz
    ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
    ADCSRA |= (1<<ADSC) | (1<<ADATE) | (1<<ADIF);
    sei();
    
}
void ADC_StartConvert(){
    ADCSRA |= (1<<ADSC);
}
uint16_t ADC_read(){
    uint16_t i = ADCL + (((uint16_t)(ADCH))<<8);
    return i;
}
\$\endgroup\$
2
  • \$\begingroup\$ I looked again in the datasheet and it is said that ADCL must be read first. As G36 suggested \$\endgroup\$ Oct 5 '20 at 21:22
  • 1
    \$\begingroup\$ @AshrafAlmubarak thanks for correcting me, So I am editing the code. \$\endgroup\$
    – Deepak
    Oct 6 '20 at 4:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.