SAMD51: using INTREF as ADC voltage reference

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

We're having trouble on the SAMD51 using the ADC with internal bandgap-based voltage references, supplied by the SUPC peripheral. Sample code:

 

#define IGNORED_CHANNEL 0

    struct adc_sync_descriptor adc;

    adc_sync_init(&adc, ADC0, (void*) NULL);

    hri_supc_set_VREF_ONDEMAND_bit(SUPC);
    hri_supc_set_VREF_VREFOE_bit(SUPC);   // May not be necessary, but removing it doesn't fix the problem.
    hri_supc_set_VREF_SEL_bf(SUPC, SUPC_VREF_SEL_1V0_Val);
    adc_sync_set_resolution(&adc, ADC_CTRLB_RESSEL_12BIT_Val);
    // Choose 1.0V (based on internal bandgap value) as reference voltage for ADC.
    adc_sync_set_reference(&adc, ADC_REFCTRL_REFSEL_INTREF_Val);

    // Channel passed in adc_sync_enable_channel is ignored (!).
    // SCALEDIOVCC is 1/4 of VDDIN (1/4 of 3.3V nominal).
    adc_sync_set_inputs(&adc,
                        ADC_INPUTCTRL_MUXPOS_SCALEDIOVCC_Val,   // pos_input
                        ADC_INPUTCTRL_MUXNEG_GND_Val,           // neg_input
                        IGNORED_CHANNEL);                       // channel (this arg is ignored (!))
    adc_sync_enable_channel(&adc, IGNORED_CHANNEL);

    volatile uint16_t reading;

    // The channel listed in adc_sync_read_channel is ignored.
    adc_sync_read_channel(&adc, IGNORED_CHANNEL, ((uint8_t*) &reading), 2);

 

The problem is that `adc_sync_read_channel()` hangs forever waiting for the conversion to be done. It's waiting for `ADC_INTFLAG_RESRDY`.

 

This same code works fine if `adc_sync_set_reference()` uses a non-INTREF choice, like `ADC_REFCTRL_REFSEL_INTVCC1_Val`. Similar code also works fine on SAMD21, using the 1V reference.

 

There's no chip errata for this issue that I can find. Thanks a lot for any clues. I'm not sure if it simply doesn't work, or if I'm setting up the SUPC wrong, or something else.

This topic has a solution.
Last Edited: Sat. Oct 12, 2019 - 06:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try without 

   hri_supc_set_VREF_ONDEMAND_bit(SUPC);

it made a difference for me (although I had version running with the ONDEMAND bit set also, not sure what I changed that prevented this from working).

/Lars

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Lajon - Thanks for the reply! It was the clue I needed. I found it works if and only if ONDEMAND=0 and VREFOE=1. 

 

    hri_supc_set_VREF_SEL_bf(SUPC, SUPC_VREF_SEL_1V0_Val);
    // ONDEMAND must be clear, and VREFOE must be set, or else the ADC conversion will not complete.
    hri_supc_clear_VREF_ONDEMAND_bit(SUPC);
    hri_supc_set_VREF_VREFOE_bit(SUPC);