cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L0 ADC "Latches" Data Using DMA

roger99
Associate III

Hello,

I am using an STM32L031G6U6 device. (28-UQFN)

Summary: There are 6 ADC channels configured for DMA. After having a nominal voltage (2.9V or less) applied to Channel 0 / ADC_IN0 / Pin 6, and then removing the source, the value remains in the register.

 

Description:

It is configured using HAL. It uses channels 0,1,2,4,5,6. I am using a DMA transfer, word size, circular mode, along with 8x oversampling. Some data fields are voltage scaled, a couple sources use a buffer, but in each channel voltage data is correct and verified. Pin 5, VDDA, is at 3V0 and filtered using a 4.7u  + 100n cap. The 3V0 supply is relatively noise free.

After booting up and beginning execution, every 10 secs a string of values is printed out, starting at channel 0. I apply a voltage of 2.9V or less to ADC0. The value is correct. All other channels are correct. Then I completely remove the voltage source from Channel 0. It continues to print out a voltage value (or ADC counts if you prefer) that are somewhat less, typically anywhere from 0.8V to 1.5V less. I can leave it for an hour and the value will remain relatively stable. here is what I have tried to "flush" and reset the ADC after a read, and before the next one. Note: all buffers and values are cleared between reads.

1 - HALT the DMA using HAL_ADC_Stop_DMA(&hadc); 

2 - De initialize the ADC peripheral using HAL_ADC_MspDeInit(&hadc); (also stops clock)

At the end of the 10 second period, I then:

1 - HAL_ADC_MspInit(&hadc);
2 - HAL_Delay(5);
//recal ADC
3 - HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED);
//start ADC
4 - HAL_ADC_Start_DMA(&hadc, (uint32_t*)adcDMABuffer, DMA_SIZE);

And the peripheral starts up, all values are correct and as expected, EXCEPT for ADC0, which continues on with the same value it had before performing all the above. Something's not getting cleared!

I have discovered one thing that will clear it. I use a serial port to send commands to the device, so I added a command to perform a soft reset using NVIC_SystemReset(). When it comes out of reset, the system resumes updating every 10 seconds, and the value that was on ADC0 is gone. I apply a voltage and voltage appears and is correct. I remove the source and value remains...repeat...same thing.

I have scoured through the peripheral libraries to see if there's any addition function that can be used to reset the ADC after shutting it down, but seemingly nothing more than what I have tried. So the question is this:

What does the RESET/RESTART do to the ADC peripheral that "HAL_ADC_MspDeInit(&hadc)" does not?

Is there a bit in one of the registers I can set to clear ADC0 from latching this value, or fully resetting the peripheral? I've been fighting with this for the last couple of days but really spinning the wheels.

Thanks for any suggestions on this!

 

 

 

 

 

3 REPLIES 3

It's like a capacitor holding charge.

Suggest you sample a pin that's grounded, say as an injected channel. Or perhaps something else, like VREFINT, TEMP

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
roger99
Associate III

Something I considered and tested. I used a 5 ohm resistor and grounded that input after disabling the supply and held it there. After going through the noted cycle as posted, still the value exists. 

It cannot be a capacitor holding a charge. If it is, why does it work AFTER a call NVIC_SystemReset() ? As I mentioned, it  clears after that, but no matter what you do before then, the value will not disappear. If the cap was holding a charge, in the 2 seconds that it takes to execute NVIC_SystemReset(), the capacitor should still be holding the charge. Not happening. And so back to my question.

What function can I call, what register can I set to make the ADC peripheral the exact same state as it is after a power-up sequence? If I can know that, I will make the same call(s) and it should get cleared.

 

BTW - in the actual working program the RTOS is actually put into STOP2, so these calls I described are made before STOP2, and after exiting STOP2. But I've tried without going into STOP2, and it makes no difference. Meaning, STOP mode has nothing to do with the ADC behavior. In fact, I can loop through and repeatedly print out the data, place the source voltage on ADC0, and remove it, and see the voltage derivative still there.

Serious issue.

 

 

 

 

roger99
Associate III

This channel has more filtering capacitance than the others, and after removing the source (or source goes to 0) it takes about an hour for the ADC register to begin falling, and takes about 10 minutes. I can take a lead that is grounded, touch that input pin on the board (after source is removed) and that ADC register still stays the same. Even tried setting ADC1->DR to 0 after every cycle. Nope. There's about 400uF capacitance (ceramic) on that line. DMM says there's no volts on that line!

BUT - still unexplainable as to why I can do a power down reset or a reflash and it comes up as no ADC counts.

Would be nice to have an expert weigh in and provide some possibilities.