Skip to main content
Mr_M_from_G
Senior II
January 25, 2019
Solved

ADC1 and 2 timing longer than data sheet values

  • January 25, 2019
  • 8 replies
  • 1263 views

Hello,

I try to setup ADC1 and ADC2, but I don't get the timing values given in reference manual and data sheet. I work with STM32H743 Nucleo

I have setup RCC to clk ADC with 36 MHz from PLL2P. I checked the frequency at master clock out 2 on PC9. To initialize ADC1 and 2 I use this code:

volatile uint32_t wait_cnt;
 // ADC init: for ADC1 and ADC2
 // reset ADC1 and ADC2:
 SetBitMask (RCC->AHB1RSTR, RCC_AHB1RSTR_ADC12RST);
 ClearBitMask (RCC->AHB1RSTR, RCC_AHB1RSTR_ADC12RST);
 // enable ADC clk
 SetBitMask (RCC->AHB1ENR, RCC_AHB1ENR_ADC12EN);
 __DSB (); // needs to be here according to errata, to wait till periph clk is enabled
 
 ClearBitMask (ADC1->CR, ADC_CR_DEEPPWD);
 ClearBitMask (ADC2->CR, ADC_CR_DEEPPWD);
 SetBitMask (ADC1->CR, ADC_CR_ADVREGEN);
 SetBitMask (ADC2->CR, ADC_CR_ADVREGEN);
 
 
 SetPortBit (port_Testpins, pin_ADC_test);
 for (wait_cnt = 0; wait_cnt < 500; wait_cnt++)
 { // wait for ADC voltage regulator to stabilize, this loop is ca 12 µsec
 __NOP ();
 __NOP ();
 }
 ClearPortBit (port_Testpins, pin_ADC_test);
 
 SetBitMask (ADC1->CR, ADC_CR_BOOST);
 SetBitMask (ADC2->CR, ADC_CR_BOOST);
 
 SetBitMask (ADC1->CR, ADC_CR_ADCALDIF | ADC_CR_ADCALLIN);
 SetBitMask (ADC2->CR, ADC_CR_ADCALDIF | ADC_CR_ADCALLIN);
 SetBitMask (ADC1->CR, ADC_CR_ADCAL);
 SetBitMask (ADC2->CR, ADC_CR_ADCAL);
 SetPortBit (port_Testpins, pin_ADC_test);
 while (BitMaskIsNOTClear(ADC1->CR, ADC_CR_ADCAL) || BitMaskIsNOTClear(ADC2->CR, ADC_CR_ADCAL))
 { // wait for calibration to complete
 }
 ClearPortBit (port_Testpins, pin_ADC_test);
 
 SetBitMask (ADC1->ISR, ADC_ISR_ADRD); // to clear it
 SetBitMask (ADC2->ISR, ADC_ISR_ADRD); // to clear it
 SetBitMask (ADC1->CR, ADC_CR_ADEN);
 SetBitMask (ADC2->CR, ADC_CR_ADEN);
 SetPortBit (port_Testpins, pin_ADC_test);
 while (BitMaskIsClear(ADC1->ISR, ADC_ISR_ADRD) || BitMaskIsClear(ADC2->ISR, ADC_ISR_ADRD))
 { // wait for startup to complete
 }
 ClearPortBit (port_Testpins, pin_ADC_test);
 ADC1->SQR1 = (3 << ADC_SQR1_SQ1_Pos) + (1-1);
 ADC1->PCSEL = 1 << 3;
 ADC1->SMPR1 |= 2 << ADC_SMPR1_SMP3_Pos; // 2 = 8,5 ADC clk cycles
 ADC1->ISR = ADC_ISR_EOS;
 SetBitMask (ADC1->CR, ADC_CR_ADSTART);
 
 SetPortBit (port_Testpins, pin_ADC_test);
 while (BitMaskIsClear(ADC1->ISR, ADC_ISR_EOS))
 { // wait for calibration to complete
 }
 ClearPortBit (port_Testpins, pin_ADC_test);

I have set 8.5 clk cycles sampling time + another 8.5 for conversion time, @36MHz I would expect a total conversion time of 472 nsec but I get 670 nsec.

Even more differing from datasheet is the time for calibration. Data sheet says it is 16384 cycles = 455µsec @36MHz but I measure 4.56 msec. Is there a digit missing in data sheet ?

Do I miss some setting in my code?

Any help is welcome

Thanks a lot.

Martin

This topic has been closed for replies.
Best answer by Amel NASRI

hi @Mr_M_from_G​ ,

Could you please provide more details on how you measured the conversion time?

Did you got any improvement when applying @S.Ma​ 's proposal?

Regarding the calibration value, you are almost right saying that there is a missing digit :)

In fact the correct value of this parameter is 165010 cycles instead of 16384 cycles. Datasheet will be updated accordingly.

-Amel

8 replies

MNapi
Senior II
January 25, 2019

I cannot comment on this. But I setup ADC in Cube MX for STM32F446 and it was like the data sheet said 1.5 Msps for 12 bit resolution. I did measure the speeds with oscilloscope.

S.Ma
Principal
January 25, 2019

Try to run the code with interrupts disabled as they could slow down the process. Same for dma memory access if activated. Then compare. Is the vdda same as in the spec or different?

Amel NASRI
Amel NASRIBest answer
ST Technical Moderator
January 28, 2019

hi @Mr_M_from_G​ ,

Could you please provide more details on how you measured the conversion time?

Did you got any improvement when applying @S.Ma​ 's proposal?

Regarding the calibration value, you are almost right saying that there is a missing digit :)

In fact the correct value of this parameter is 165010 cycles instead of 16384 cycles. Datasheet will be updated accordingly.

-Amel

To give better visibility on the answered topics, please click on "Best Answer" on the reply which solved your issue or answered your question.
waclawek.jan
Super User
January 28, 2019

>Could you please provide more details on how you measured the conversion time?

>> SetPortBit (port_Testpins, pin_ADC_test);

>> ClearPortBit (port_Testpins, pin_ADC_test);

Sounds much like wiggling GPIO pin and observing by oscilloscope/LA...

JW

Mr_M_from_G
Senior II
January 29, 2019

Hello all,

thanks for your messages.

Here are my answers:

This code is bound to be the initialization routine for ADC1+2. Therefore it is placed before enabling interrupts and DMA.

Sorry I frequently forget to add my macros, I am so used to them...

#define SetBitMask(Var,BitMask) (Var|=(BitMask))

#define SetPortBit(Port,BitNr) (Port->BSRRL=1U<<(BitNr))

#define ClearPortBit(Port,BitNr) (Port->BSRRH=1U<<(BitNr))

So I set and clear a GPIO pin around everything I want to measure. These are the time to wait for voltage regulator, calibration time, waiting for ADC ready, which seems to be one conversion and a conversion.

Meanwhile I did two more experiments:

When I add this line

 SetBitMask (ADC12_COMMON->CCR, ADC_CCR_PRESC_0);

after voltage regulator is up and before the BOOST lines I get a calibration time of 9.18 msec and a conversion time of 1.24 µsec.

Setting ADC_CCR_PRESC_1 results in 18.35 msec and 2.44 µsec resp.

And again without any ADC_CCR_PRESC bit set and changed after ADC is ready to this:

 ADC1->SQR1 = (3 << ADC_SQR1_SQ1_Pos) | (3 << ADC_SQR1_SQ2_Pos) | (3 << ADC_SQR1_SQ3_Pos) | (3 << ADC_SQR1_SQ4_Pos) | (4-1);
 ADC1->PCSEL = 1 << 3;
 ADC1->SMPR1 |= 2 << ADC_SMPR1_SMP3_Pos; // 2 = 8,5 ADC clk cycles
 ADC1->ISR = ADC_ISR_EOS;
 SetBitMask (ADC1->CR, ADC_CR_ADSTART);
 
 SetPortBit (port_Testpins, pin_ADC_test);
 while (BitMaskIsClear(ADC1->ISR, ADC_ISR_EOS))
 { // wait for conversion sequence to complete
 ADC1->ISR = ADC_ISR_EOC;
 }
 ClearPortBit (port_Testpins, pin_ADC_test);

which is setting up a sequence of 4 conversions and permanently clearing bit EOC to start a new conversion as fast as possible (sequence seems not to be continued if EOC stays high, this is in contrast to section ADC overrun on page 941 in RM0433 Rev5 which I understand so that conversions always continue until sequence is through only the way of storing data depends on OVRMOD)

The sequence loop now measures 2.13 µsec which is 533 nsec per conversion. So conversion time is getting closer to the expected value.

I will set up a DMA to read out ADC_DR as fast as possible and come back with results.

Any comment on the ten times longer calibration time is welcome.

best regards

Martin

Mr_M_from_G
Senior II
January 29, 2019

Hello again,

I setup a DMA to run a number of conversions and I can confirm the calculated 470 nsec per conversion. The difference seems to be caused by the loop and GPIO set and clear.

Still I have 4.5 msec calibration time :)

Martin

waclawek.jan
Super User
January 29, 2019

> Still I have 4.5 msec calibration time

Yes, but wasn't that explained by the second part of Amel's answer above?

> I can confirm the calculated 470 nsec per conversion. The difference seems to be caused by the loop and GPIO set and clear.

So if this is settled, can you please mark some of the posts as Best (maybe Amel's) so that the thread is tagged as solved?

Thanks,

JW