2019-01-25 07:42 AM
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
Solved! Go to Solution.
2019-01-28 12:52 AM
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 Accept as Solution on the reply which solved your issue or answered your question.
2019-01-25 08:22 AM
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.
2019-01-25 08:50 AM
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?
2019-01-28 12:52 AM
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 Accept as Solution on the reply which solved your issue or answered your question.
2019-01-28 01:36 AM
>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
2019-01-29 01:09 AM
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
2019-01-29 02:21 AM
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
2019-01-29 03:58 AM
> 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
2019-01-29 04:51 AM
Hello Amel,
my apologies for coming up again with the longer calibration time, and thanks to Jan for pointing me to this. I didn't see the second part of your post because I didn't click "show more".
I mark your post as best and my question is completely solved now.
Thanks to all who contributed.
Martin