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); } }