The following code example shows how to perform differential measurements using the
Burst Accumulation with Scaling mode, the PGA with 16x gain and oversampling to achieve
a 16-bit
resolution.
#defineF_CPU3333333ul#include<avr/io.h>#include<math.h>#include<util/delay.h>#defineTIMEBASE_VALUE ((uint8_t) ceil(F_CPU*0.000001))
#defineADC_DIFF_MAX_VALUE (((1 << 12) / 2) - 1) /* In differential mode, the max value is 2047 */#defineADC_DIFF_MAX_VALUE_16BIT ((uint32_t) ADC_DIFF_MAX_VALUE << 4) /* In differential mode, the max value for a 16-bit result is 32752 *//* Defines to easily configure ADC accumulation */#defineADC_SAMPNUM_CONFIG ADC_SAMPNUM_ACC256_gc
/* Left shifting (1 << SAMPNUM) results in the number of accumulated samples */#defineADC_SAMPLES (1 << ADC_SAMPNUM_CONFIG)
/* Volatile variables to improve debug experience */staticvolatile int32_t adc_reading;
staticvolatilefloat voltage;
staticvolatilefloat current;
/*********************************************************************************
ADC initialization
**********************************************************************************/voidadc_init()
{
ADC0.CTRLA = ADC_ENABLE_bm;
ADC0.CTRLB = ADC_PRESC_DIV2_gc; /* fCLK_ADC = 3.333333/2 MHz */
ADC0.CTRLC = ADC_REFSEL_1024MV_gc | (TIMEBASE_VALUE << ADC_TIMEBASE_gp);
ADC0.CTRLE = 17; /* (SAMPDUR + 0.5) * fCLK_ADC = 10.5 µs sample duration */
ADC0.CTRLF = ADC_LEFTADJ_bm | ADC_SAMPNUM_CONFIG; /* Enable left adjust if accumulating < 16 samples */
ADC0.MUXPOS = ADC_VIA_PGA_gc | ADC_MUXPOS_AIN6_gc; /* ADC channel AIN6 -> PA6 */
ADC0.MUXNEG = ADC_VIA_PGA_gc | ADC_MUXNEG_AIN7_gc; /* ADC channel AIN7 -> PA7 */
ADC0.COMMAND = ADC_DIFF_bm | ADC_MODE_BURST_SCALING_gc; /* Burst Accumulation with Scaling *//* Enable PGA with 16x gain.
Set full bias current for fast sampling. Configure ADCPGASAMPDUR according to data sheet. */
ADC0.PGACTRL = ADC_GAIN_16X_gc | ADC_PGABIASSEL_1X_gc | ADC_ADCPGASAMPDUR_6CLK_gc | ADC_PGAEN_bm;
}
intmain(void)
{
adc_init();
while(1)
{
ADC0.COMMAND |= ADC_START_IMMEDIATE_gc;
while(!(ADC0.INTFLAGS & ADC_RESRDY_bm)); /* Wait until conversion is done */
adc_reading = ADC0.RESULT; /* Read 16 bit scaled or left adjusted result *//* Calculate the differential voltage, VREF = 1.024V, 16-bit resolution, 16x gain. */
voltage = (float)((adc_reading * 1.024) / ADC_DIFF_MAX_VALUE_16BIT) / 16;
//current = voltage / 5; /* Uncomment this line if measuring across a 5 ohm resistor in series with the power supply */
_delay_ms(500);
}
}
A use case example of the code above is current measurement. Like shown in the
image below, minor hardware modification must be done to be able to measure the device’s
current consumption. Selecting a resistor size for current measurement depends on
multiple factors. For example, if the resistance is high, it may introduce a big voltage
drop which may lead to shortened battery life in a battery powered application. On the
other hand, if the resistance is low, it may lead to lower resolution. A 5Ω resistor in
this example leads to a measuring step size of 400 nA and a range of 400 nA to 12.8
mA.
Connect the resistor between
VPS and VDD.
Connect PA6 to VPS and
PA7 to VDD.
Figure 5-1. Current Measurement
ConnectionIn software, the following must be done to read the current consumption
measurements:
Uncomment the line below the
voltage calculation in the main() function in the code.
Add a breakpoint in the code and
click Start Debugging to start debugging.
When the program has been halted
at the breakpoint, right click on the current variable and
select Add Watch. The current variable
will now be visible in the watch window.
If controlling the
measurements with a multimeter, the results might deviate. Since the
multimeter also measures at times where the ADC is inactive, it will
normally show a lower current consumption.
The online versions of the documents are provided as a courtesy. Verify all content and data in the device’s PDF documentation found on the device product page.