ADC problems in BSP analog.c I think.

froeber

Well-known member
Paul, I'm adapting the ADC code you provide in the BSP analog.c source file for my own application. Primarily I need to change it to support the LLS low power mode which resets the ADC each time you go to sleep. I found some issues in working with the code and testing it.
1) The way you trigger a calibration cycle causes it to fail every time. Your code doesn't check the CALF flag in ADC0_SC3 but if it did you would find it set. The problem is because you change the ADC0_SC3 register in the same instruction as starting the calibration. That seems to be the cause of the failure because when I use the code:
Code:
    ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(3);
    ADC0_SC3 |= ADC_SC3_CAL;
Calibration works but your code:
Code:
   ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(3);
Fails. It's a simple change I think you might want to make.

2) I noticed some odd things about how you set up the voltage reference (VREF). Your code does:
Code:
	VREF_TRM = 0x60;
	VREF_SC = 0xE1;		// enable 1.2 volt ref
One issue is that you turn on the voltage reference VREF and then start an immediate calibration cycle. I couldn't find any details on calibration but I assume it uses the configured reference (in this case VREF). But VREF can take a while to stabilize (tens of microseconds). I thought it was safe and easy to just add a stabilization delay loop after turning on VREF and before starting the calibration. Also, you set the VREF_TRM register to a particular value. But the reference manual indicates that the TRIM field in that register is set "to the factory configured trim value" at reset. I think it's more correct to just "or in" the CHOPEN control bit and leave the TRIM field as is. Granted, on my chip that result is the same as what you end up with because the factory trim setting is a "middle of the range" 0x40. Finally, you set the VREF mode to 1 which is high buffer strength. That's needed if people hook up and use the external VREF_OUT signal coming off the board. But for most people who only use the VREF for sources like the ADC internal to the processor, then mode 2 (low buffer strength) is a better choice and uses 1/2 the power of mode 1. I'm not saying your mode choice was wrong since it's the most general purpose but some people worried about power use (like me) might want to change it. In the end, the setup code I used was:

Code:
/* VREF SC Register bit fields */
#define VREF_SC_VREFEN       0x80u
#define VREF_SC_REGEN        0x40u
#define VREF_SC_ICOMPEN      0x20u
#define VREF_SC_VREFST       0x04u
#define VREF_SC_MODE_LV_MASK 0x03u
#define VREF_SC_MODE_LV_0    0x00u   // Bandgap on only (for startup)
#define VREF_SC_MODE_LV_1    0x01u   // High power buffer mode enabled
#define VREF_SC_MODE_LV_2    0x02u   // Low power buffer mode enabled

/* VREF TRM Register bit fields */
#define VREF_TRM_CHOPEN      0x40u

    VREF_TRM |= VREF_TRM_CHOPEN;
    VREF_SC = VREF_SC_VREFEN | VREF_SC_REGEN | VREF_SC_ICOMPEN |
              VREF_SC_MODE_LV_2;
    while ((VREF_SC & VREF_SC_VREFST) == 0) ;

That's all I have. As usual, I was impressed with how the analog code did a lot of stuff in a straightforward way that worked. I only had that one calibration issue.
 
Last edited:
Back
Top