5.2.1.1 Code Example

The following code example shows how to increase the ADC resolution from 12-bit to 17-bit by using oversampling, and how to calculate the voltage applied to ADC channel AIN6.
#define F_CPU 3333333ul

#include <avr/io.h>
#include <math.h>
#include <util/delay.h>

#define TIMEBASE_VALUE          ((uint8_t) ceil(F_CPU*0.000001))

/* Defines to configure ADC accumulation */
#define OVERSAMPLING_BITS       5 /* 5 bits extra */
#define OVERSAMPLING_MAX_VALUE  ((uint32_t) ((1 << 12) - 1) << OVERSAMPLING_BITS) /* 12 + 5 bits = 17 bits */
#define ADC_SAMPNUM_CONFIG      (OVERSAMPLING_BITS << 1) /* The SAMPNUM bit field setting match this formula */
#define ADC_SAMPLES             (1 << ADC_SAMPNUM_CONFIG) /* 5 bits = 1024 samples */

/* Volatile variables to improve debug experience */
static volatile uint32_t adc_reading;
static volatile float voltage;

/*********************************************************************************
ADC initialization
**********************************************************************************/
void adc_init()
{
	ADC0.CTRLA = ADC_ENABLE_bm;
	ADC0.CTRLB = ADC_PRESC_DIV2_gc; /* fCLK_ADC = 3.333333/2 MHz */
	ADC0.CTRLC = ADC_REFSEL_VDD_gc | (TIMEBASE_VALUE << ADC_TIMEBASE_gp);
	ADC0.CTRLE = 17; /* (SAMPDUR + 0.5) * fCLK_ADC = 10.5 µs sample duration */
	ADC0.CTRLF = ADC_SAMPNUM_CONFIG;

	ADC0.MUXPOS = ADC_MUXPOS_AIN6_gc; /* ADC channel AIN6 -> PA6 */
	ADC0.COMMAND = ADC_MODE_SERIES_gc; /* Series Accumulation mode */
}

int main(void)
{
	adc_init();

	while(1)
	{
		ADC0.COMMAND |= ADC_START_IMMEDIATE_gc;
		while(!(ADC0.INTFLAGS & ADC_SAMPRDY_bm)); /* Wait until conversion is done */
		ADC0.INTFLAGS = ADC_SAMPRDY_bm; /* Clear Sample Ready interrupt flag */

		if(ADC0.INTFLAGS & ADC_RESRDY_bm) /* If result is ready */
		{
			/* Oversampling compensation as explained in the tech brief */
			adc_reading = ADC0.RESULT >> OVERSAMPLING_BITS; /* Scale accumulated result by right shifting the number of extra bits */
			voltage = (float)((adc_reading * 3.3) / OVERSAMPLING_MAX_VALUE); /* Calculate voltage using 17-bit resolution, VDD = 3.3V */
		}

		_delay_ms(1);
	}
}