cancel
Showing results for 
Search instead for 
Did you mean: 

Simple Single ADC conversion can hang up (ADC_CR_ADSTART keeps set)

flyer31
Senior

... just reporting, no question...

Today I had a quite bizarre problem with my ADC when testing the same PCB with RevY and RevV chip.

I operate the ADC in regular single mode (I tried also regular discontinuous mode), very slow sampling (865 cycles)), 8MHz ADC frequency without prescaler... Ad1 + Ad3 always sampling some channel, every about 10msec, so all very "slow and simple" .

I have two PCBs with STM32H750V (LPQFP 100), one with RevY, one with RevV. Further by some jumper bridte on this PCB I can run the PCB with or without CAN bus.

So I could test 4 configurations:

  • RevV no CAN
  • RevV with CAN
  • RevY no CAN
  • RevY with CAN

At first there was always ONE of these configurations, where the ADC Ad3 "hang up" (Ad3 is started directly after Ad1... maybe Ad3 because it is started later... I did not try this in detail).

Such "hanging up" meant, that the bit AD_CR_ADSTART kept beeing set to 1 infinitely , and DR=0, and nothing working any more with this ADC, really bizarre (at least the RefManual does not mention such a possibility, also not in the ADC_CR register description of ADC_CR_ADSTART...).

Only when I finally set the ADC_CR_BOOST bit, then all 4 configurations work now .. really a bit bizarre. I am happy for now ... I just wanted to report it to the forum.

2 REPLIES 2
AB.17
Associate II

Do you have the same code for both revisions? If so, have a look at AN5312, looks like it might matter to your issue.

flyer31
Senior

Yes I have the same code - I know AN5312 ... in fact it would be nice to present some "basic code" there ... but I must admit that ADC is so versatile, that it is difficult to present some standard code.

... but as always it would be nice if STM could somewhere present some "min application standard code" ... .

Here my code for the Init function:

void Init_RCCok( ADC_TypeDef* pADC){
  pADC->CR= 0;
  pADC->CR= ADC_CR_ADVREGEN;
                            // Startup-Time max. 10usec (DS 6.3.30 Tab84)
  Wait_usec( 10);
  //2: PER_CK als Clock-Source, PER_CK= HSE, HSE= 8MHz (XTAL)
  RCC->D3CCIPR |= 2 << BITNR(RCC_D3CCIPR_ADCSEL);
 
  if( pADC== ADC3){
    ADC3_COMMON->CCR= ADC_CCR_TSEN | ADC_CCR_VREFEN; 
  }
  else
    ADC12_COMMON->CCR= 0; 
  pADC->CR= ADC_CR_ADVREGEN | ADC_CR_ADEN | ADC_CR_BOOST;
}

Here my code for the Start of AD conversion:

void StartAD( ADC_TypeDef* pADC, int iCh, int iSmp){
  assertIfDebug( !(pADC->CR & ADC_CR_ADSTART));
  // This assertion will be hit, if the ADC is "hanging"
  // happens always on 2nd invoke of ADC3 (if it happens)
  pADC->PCSEL |= 1<< iCh;
  //0: only 1 Channel!
  pADC->SQR1= 0 | (iCh << BITNR( ADC_SQR1_SQ1));
  if( iCh <= 9)
    pADC->SMPR1 |= iSmp << (3*iCh);
  else
    pADC->SMPR2 |= iSmp << (3* (iCh-10));
  pADC->ISR = 0x07FF;
  pADC->CR |= ADC_CR_ADSTART;
}

Here my code to read out the result:

int ADReadResult( ADC_TypeDef* pADC){
  if( (pADC->ISR & ~0x100F) || !(pADC->ISR & (ADC_ISR_EOSMP | ADC_ISR_EOC )))
    return ADC_ERRORVALUE;
  return pADC->DR;
}

And here my state machine sequence:

... init-part of main:
  RCC->AHB1ENR |= RCC_AHB1ENR_ADC12EN;
  RCC->AHB4ENR |= RCC_AHB4ENR_ADC3EN;
 
  Init_RCCok( ADC1);
  Init_RCCok( ADC3);
 
  
... loop / state machine part of main:
 
for(;;){
  ADStart( ADC1, 3, SMPCLK_810);  
  ADStart( ADC3, 19, SMPCLK_810);   //Ch 19: Internal VRef
  Wait_msec (2);
  ADReadResult( ADC1);
  ADReadRsult(ADC3);
  Wait_msec(1);
}

(sorry, this is a bit "abbreviated" ... I use C++ classes and stripped out the classes here to me "more simple"... and I skipped the #defines, which are quite obvious... and I skipped the macro "BITNR" ... which also is quite obvious.

... I hope ok to understand...

The strange thing is, that the if I do NOT use the ADC_CR_BOOST bit in Init, then I could get ADC_CR_ADSTART bit of ADC3 to "hang" - run into infinite timeout. And strangely this worked only if CAN is NOT used in my conf. If I USE CAN, then it always worked for both Revisions... .

Slightly bizarre... . But as it works when I use the ADC_CR_BOOST, and as documentation also recommends usage of ADC_CR_BOOST (except in low power applications - but my application is "standard power" with internal PLL to 400MHz, HSE=8MHz), I do NOT mind using ADC_CR_BOOST, so all fine for me.