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
Note: MCC also configures other settings for the ADC than shown in this list. These settings are reconfigured by the application code before the ADC is started, and are therefore excluded.

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.

Equation 5-1. ADC Voltage Calculation
V = ADCn.RESULT + OFFSET SAMPNUM × V REF GAIN × RESOLUTION

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.