Free running ADC on mega.

Hi all,

I'm writing a new TFT driver and I want to test it out by drawing an oscilloscope style wave form to get a benchmark on line drawing; I'm just struggling with the ADC functionality. I found many good articles for setting it up on a smaller mcu ( 168/328 ) however the 2560 data sheet is quite involved.
What I'm after is a ADC set to free running mode using an ISR to capture the readings. I have only a need for 8-bit resolution at a pre-scale value of 32 for 500khz sampling.
I used the example code below in an attempt to get something running, however an error reports ADFR as not being declared.

ADCSRA |= ( 1 << ADPS2 ) | ( 1 << ADPS1 ) | ( 1 << ADPS0 ); // Set ADC prescaler to 128 - 125KHz sample rate @ 16MHz       
ADMUX |= ( 1 << REFS0 ); // Set ADC reference to AVCC 
ADMUX |= ( 1 << ADLAR ); // Left adjust ADC result to allow easy 8 bit reading 
ADCSRA |= ( 1 << ADFR );  // Set ADC to Free-Running Mode 
ADCSRA |= ( 1 << ADEN );  // Enable ADC 
ADCSRA |= ( 1 << ADIE );
ADCSRA |= ( 1 << ADSC );

I also haven't seen much use of the DIDR register(s) is this important/beneficial?

I'll keep searching, however any ideas/useful links would be great. 8)

pYro_65:
Hi all,

I'm writing a new TFT driver and I want to test it out by drawing an oscilloscope style wave form to get a benchmark on line drawing; I'm just struggling with the ADC functionality. I found many good articles for setting it up on a smaller mcu ( 168/328 ) however the 2560 data sheet is quite involved.
What I'm after is a ADC set to free running mode using an ISR to capture the readings. I have only a need for 8-bit resolution at a pre-scale value of 32 for 500khz sampling.
I used the example code below in an attempt to get something running, however an error reports ADFR as not being declared.

ADCSRA |= ( 1 << ADPS2 ) | ( 1 << ADPS1 ) | ( 1 << ADPS0 ); // Set ADC prescaler to 128 - 125KHz sample rate @ 16MHz       

ADMUX |= ( 1 << REFS0 ); // Set ADC reference to AVCC
ADMUX |= ( 1 << ADLAR ); // Left adjust ADC result to allow easy 8 bit reading
ADCSRA |= ( 1 << ADFR );  // Set ADC to Free-Running Mode
ADCSRA |= ( 1 << ADEN );  // Enable ADC
ADCSRA |= ( 1 << ADIE );
ADCSRA |= ( 1 << ADSC );




I also haven't seen much use of the DIDR register(s) is this important/beneficial?

I'll keep searching, however any ideas/useful links would be great. 8)

According to the databook, to setup free running mode, you set bits 0, 1 and 2 of the ADCSRB register to 0. You also need to set bit 6 (ACME) to a 1 to enable single ended mode.

Also, strangely, the ADMUX bits 0 through 4 are in the ADMUX register, but ADMUX bit 5 is bit 3 of ADCSRB.

A classic example of "Plan Ahea
d"

There is no ADFR register. ADFR is in internal processor signal.

Thanks for the reply, I got it working eventually and it performs well, cheers.
I didn't notice any change from setting the ACME, maybe this is a default value or gets set by Arduino's init() function.

pYro_65:
Thanks for the reply, I got it working eventually and it performs well, cheers.
I didn't notice any change from setting the ACME, maybe this is a default value or gets set by Arduino's init() function.

I also found that slowing the A/D clock seems to give much cleaner readings. Here's some code that I use (on a 328P) but it should translate easily to the Mega:

/*** this part in main() or setup()
        ADCSRA |= (_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADEN)); // a/d prescaler = sysclk/128, a/d enable
        ADMUX = (_BV(7) | _BV(6)); // use internal 1.1v ref & clear channel bits
***/

uint16_t readAnalog(uint8_t port)
{
        uint8_t hi;
        uint8_t lo;

        ADMUX |= port; // OR in desired channel
        ADCSRA |= _BV(ADSC); // Start ADC conversion

        while(ADCSRA & _BV(ADSC)) { ; } // wait for a/d complete

        lo = ADCL; // must read ADCL first
        hi = ADCH;

        return (hi << 8) | lo;
}

The first line of code (the "// a/d prescaler = sysclk/128, a/d enable" part) is what sets the A/D converter clock.

Hope this helps.

-- Roger