cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G0 ADC with Sequence but not DMA

DRobe.4
Senior

The manual is unclear I believe, when the sequencer is used but DMA is not used.

Relevant code is below, but in a nutshell, after configuring the sequencer and starting the ADC, I wait for EOC, read the data register, wait for EOC, read the data register, etc. I believe the sequencer waits for the DR to be read before continuing the sequence. Is this correct?

ADC1->ISR |= ADC_ISR_CCRDY; // Clear CCRDY Flag
ADC1->CFGR1 |= ADC_CFGR1_CHSELRMOD; // Enable the sequencer
ADC1->CHSELR = 0xF432; // Scan direction: CH2->CH3->CH4
while((ADC1->ISR & ADC_ISR_CCRDY) != ADC_ISR_CCRDY) {}; // Wait for CCRDY=1
ADC1->CR |= ADC_CR_ADSTART; // Start the sequence
while ((ADC1->ISR & BIT(2)) == 0) {}; V0 = ADC1->DR;
....... process the V0 data
while ((ADC1->ISR & BIT(2)) == 0) {}; I0 = ADC1->DR;
..... process the I0 data
while ((ADC1->ISR & BIT(2)) == 0) {}; I1 = ADC1->DR;

.... process the I1 data

The ADC is started and the sequence run every 128 usec. Is this considered low frequency (LFTRIG=1)? Or should AUTOFF be used? Or neither?

6 REPLIES 6
GwenoleB
ST Employee

Hello @DRobe.4 ,

The aim of the EOC signal is to allow the processing to be synchronized with the conversions. 
If the ADC is configured in single conversion mode, the ADC stops until a new conversion trigger. The data in ADC->DR is kept until the next conversion.
If the ADC is now configured in continuous mode, the ADC will chain whole the sequence. If the data is not read before the next conversion:
      -   If OVRMOD = 0, the ADC preserves the data. The old data is maintained and the new conversion is discarded
      -   If OVRMOD = 1, the data register is overwritten, the lost data is lost if processing was not on time

Concerning the low frequency trigger, the LFTRIG must be set if the conversion period is higher than 100µs (sample frequency less than 10kHz. This value is given is the datasheet.

Best Regards,
Gwénolé

 

 

DRobe.4
Senior

Thanks to both of you. Your relies seem to be different, and no wonder since I have chosen an unusual technique for collecting data. To be safe and meet everybody's requirements, I have modified the code as shown below. Please remember that this code runs every 128 usec and is now awkward. I can appreciate that ST has planned for users to run DMA and as easy as that is, I thought that it was an unnecessary complication. Do both of you think this code will work?

ADC1->CR |= ADC_CR_ADEN; // Activate ADC
while((ADC1->ISR & ADC_ISR_ADRDY) == 0) {}; // Wait until ADC is ready
ADC1->ISR |= ADC_ISR_CCRDY; // Clear CCRDY Flag
ADC1->CFGR1 |= ADC_CFGR1_CONT; // Continuous conversion mode seems to be necessary for a sequence of conversions
ADC1->CFGR1 |= ADC_CFGR1_CHSELRMOD; // Enable the sequencer
ADC1->CHSELR = 0xF432432; // Scan direction: CH2->CH3->CH4->CH2->CH3->CH4
while((ADC1->ISR & ADC_ISR_CCRDY) != ADC_ISR_CCRDY) {}; // Wait for CCRDY=1
ADC1->CR |= ADC_CR_ADSTART; // Start the sequence
while ((ADC1->ISR & ADC_ISR_EOC) == 0) {}; V0_1 = ADC1->DR;
while ((ADC1->ISR & ADC_ISR_EOC) == 0) {}; I0_1 = ADC1->DR;
while ((ADC1->ISR & ADC_ISR_EOC) == 0) {}; I1_1 = ADC1->DR;
while ((ADC1->ISR & ADC_ISR_EOC) == 0) {}; V0_2 = ADC1->DR;
while ((ADC1->ISR & ADC_ISR_EOC) == 0) {}; I0_2 = ADC1->DR;
while ((ADC1->ISR & ADC_ISR_EOC) == 0) {}; I1_2 = ADC1->DR;
ADC1->CR &= ~ADC_CR_ADEN; // Stop conversions by turning ADC off, also saving power, but ADC regulator still turned on
V0 = (V0_1 + V0_2)>>1; // Since it is easy to do, average two samples for V0, I0, I1
I0 = (I0_1 + I0_2)>>1;
I1 = (I1_1 + I1_2)>>1;

 

GwenoleB
ST Employee

Dear @DRobe.4 ,

Your proposal looks fine if you ensure that any other interrupt can happen. Else, the overrun may happen.
It could be worth in your case to enable the overrun interrupt of the ADC, configure the overrun mode to preserve the old data (meaning discarded the next one).

Best Regards,
Gwénolé

DRobe.4
Senior

Thanks for your help. Interrupts are disabled during data collection. I have also discovered the WAIT feature that should help to ensure that overruns don't occur.

Your proposal looks fine if you ensure that any other interrupt can happen.


C'mon - "cannot", not "can"... 

Indeed...
Thanks for the correction!