Reading the DAC Internally with the ADC

The analog output of the DAC can be internally connected to other peripherals when the DAC is enabled (ENABLE = 1 in DACn.CTRLA). When the DAC analog output is only being used internally, it is not necessary to enable the pin output driver (OUTEN = 0 in DACn.CTRLA is acceptable).

Referring to the ADC block diagram below, the output of the 10-bit DAC can be used as the internal input to the ADC.

Figure 1. Analog-to-Digital Converter Block Diagram

The DAC voltage reference is initialized as mentioned in Generating Constant Analog Signal Using 10-Bit DAC and the ADC voltage reference is initialized in the same way from the VREF peripheral.

Figure 2. VREF.DAC0REF Register
Figure 3. VREF.ADC0REF Register

The complete VREF initialization is shown below:

VREF.DAC0REF = VREF_REFSEL_2V048_gc /* Select the 2.048V Internal Voltage Reference for DAC */
             | VREF_ALWAYSON_bm; /* Set the Voltage Reference in Always On mode */
VREF.ADC0REF = VREF_REFSEL_2V048_gc /* Select the 2.048V Internal Voltage Reference for ADC */
             | VREF_ALWAYSON_bm; /* Set the Voltage Reference in Always On mode */
/* Wait VREF start-up time */
_delay_us(VREF_STARTUP_TIME);

Then, the ADC must be initialized:

ADC0.CTRLC = ADC_PRESC_DIV2_gc;
ADC0.CTRLA = ADC_ENABLE_bm | ADC_RESSEL_12BIT_gc;

To read the DAC with the ADC, the MUXPOS register of the ADC must be set to 0x48, corresponding to DAC0.

ADC0.MUXPOS = ADC_MUXPOS_DAC0_gc;
Figure 4. MUXPOS DAC Output Selection

The ADC conversion is started by writing the corresponding bit to the ADCn.COMMAND register:

ADC0.COMMAND = ADC_STCONV_bm;

When the conversion is done, the RESRDY bit in the ADCn.INTFLAGS register will be set by hardware.

while(!(ADC0.INTFLAGS & ADC_RESRDY_bm))
{
	;
}

The flag is cleared by either writing a ‘1’ to the RESRDY bit location or by reading the Result (ADCn.RES) register. Writing a ‘0’ to this bit has no effect.

ADC0.INTFLAGS = ADC_RESRDY_bm;

The ADC data can be read from the Result (ADCn.RES) register.

The DAC output can be set to different values, and read with the ADC in a loop:

while (1) 
{
	adcVal = ADC0_read();
	dacVal++;
	DAC0_setVal(dacVal);
}

Tip: The full code example is also available in Appendix.