5 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 5-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 5-2. VREF.DAC0REF Register
Figure 5-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 5-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.