5.2 Code Implementation
ADC Initialization
The peripherals used in this demo are configured in MPLAB® Code Configurator (MCC). Since the ADC is the peripheral in focus, only the ADC initialization will be described. The initial configuration of the ADC is listed below.
- Burst Accumulation mode
- 256 samples accumulated
- VREF: 1.024V
- Sample duration: 65 CLK_ADC cycles
- Run Standby mode
Shunt Resistor Measurements
The function below runs when measuring the shunt resistors. The function is called with the ADC channel configurations as arguments.
#define OFFSET 0 #define REFERENCE 1.024 #define SAMPLES 256 float adc_diff_16x(ADC_MUXPOS_t muxpos_config, ADC_MUXNEG_t muxneg_config) { /* 16x gain */ ADC0.PGACTRL = ADC_GAIN_16X_gc | ADC_PGAEN_bm; /* Set positive pin */ ADC0.MUXPOS = ADC_VIA_PGA_gc | muxpos_config; /* Enable differential mode and set trigger to MUXNEG write */ ADC0.COMMAND |= ADC_DIFF_bm | ADC_START_MUXNEG_WRITE_gc; /* Set negative pin. This write also starts the burst conversions. */ ADC0.MUXNEG = ADC_VIA_PGA_gc | muxneg_config; /* Wait for result to be ready */ while(!(ADC0.INTFLAGS & ADC_RESRDY_bm)); /* Return averaged ADC result */ /*Amplified and accumulated result divided by the gain value (16), resolution (+/- 2048) and number of samples to reflect measured voltage drop*/ return (((int32_t) ADC0.RESULT) + OFFSET) * (((REFERENCE / 16.0) / 2048.0) / SAMPLES); }
The PGA is activated and set to 16x gain, the Differential mode is enabled, the channels are set, and the burst conversions are started. The returned value is the measured voltage drop across the shunt resistance, calculated from the raw accumulated ADC result.
VDD Measurements
The function below runs when measuring VDD. The function is called with the VDD/10 channel as an argument.
#define OFFSET 0 #define REFERENCE 1.024 #define SAMPLES 256 float adc_single_2x(ADC_MUXPOS_t muxpos_config) { /* 2x gain */ ADC0.PGACTRL = ADC_GAIN_2X_gc | ADC_PGAEN_bm; /* Set ADC channel */ ADC0.MUXPOS = ADC_VIA_PGA_gc | muxpos_config; /* Enable single ended mode and set trigger to start immediate */ ADC0.COMMAND = ADC_MODE_BURST_gc | ADC_START_IMMEDIATE_gc; /* Wait for result to be ready */ while(!(ADC0.INTFLAGS & ADC_RESRDY_bm)); /* Return averaged ADC result */ /* Amplified and accumulated result divided by the gain value (2), resolution (4096) and number of samples to reflect measured voltage drop */ /* Since the measured voltage is VDD/10, the result is also multiplied by 10 */ return (((int32_t) ADC0.RESULT) + OFFSET) * 10 * (((REFERENCE / 2.0) / 4096.0) / SAMPLES); }
The PGA is in this function activated but set to only 2x gain because the expected result is higher and will need less amplification to be measured accurately. Like in the previous function, the returned value is the measured voltage calculated from the ADC result.
Use the following calculation to convert the ADC measurement result to a voltage.
The first part of the equation divides the accumulated result with the average from all samples. In an ideal ADC, the first code transition would happen when the input voltage equals 0.5 LSB, resulting in an offset equal to 0, which is not always the case in an actual ADC. This offset holds the deviation value between the ideal first code transition and the first code transition. There exist several methods to calibrate the ADC regarding the offset. Then the averaged ADC result is converted to a voltage by multiplying with a factor of voltage per LSB.