cancel
Showing results for 
Search instead for 
Did you mean: 

adc continuous conversion mode and synchronous clocking

Channamallesh Hiremath
Associate II
Posted on November 01, 2017 at 03:46

Hello,

I am confused with so many adc modes available here. My application is very simple. One channel. Keep sampling it a constant frequency of around 1 MHz. How do I set it up in the cubeMx? I need to know the adc sampling frequency also so that I can time the events.  

I chose sync clock mode divided by 4. But I do not know the exact clock frequency.

Can someone explain to me the correct configuration to be used? Attached are the pictures of my setup.

I am using STM32F303VC based STM32F3 discovery kit. 

Mallesh 

5 REPLIES 5
Posted on November 01, 2017 at 03:56

Better to set ADC in maximal mode, and then trigger from a TIM timebase.

Otherwise you're going to have to pay attention to the ADC clock, and bit width and sample time. The gearing is predictable, but not very flexible.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on November 01, 2017 at 09:42

What does it mean by maximal mode? 

Please clarify.

Posted on November 01, 2017 at 15:59

I think I now understand a bit more. ADC clock does not have anything to do with sampling frequency. It does determine the max sampling frequency based on adc sampling and conversion delays. 

So, I can set ADC clock in synchronous mode to 72 MHz and then use single conversion mode. 

Conversions are now triggered by timer which runs at less than 5 MHz. 

Is that correct?

thanks

Posted on November 01, 2017 at 16:37

You can program the ADC to saturate where the bits and sample time dictate the back-to-back rate for delivering conversions. There are finite number, and generally inflexible, set of selections here, but you can compute/fit a solution if you want, requires you to count clocks and gear ratios, and perhaps pick source clocks that are less than 72 MHz and not round/clean.

Maximal in the sense I'm conveying is that you select the bits and sample time which gets you to the best/fastest combination that meets your requirements.

The TIM then defines the sample rate, this also has some inflexibility due to the clock source and integer dividers, but generally provides a broader set of choices, and allows you to tweak the ADC sample time without have to recompute/reconsider the impact to the time line. Provided of course you don't exceed the capabilities.

72/5 = 14.4 which is a non-integer

72/3 = 24

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Preet Mehta
Associate II
Posted on January 15, 2018 at 14:59

I am not able to set my ADC module sourced with PCLK, the synchronous one. When I tried doing it with independent clock 14MHz for ADC, it works but overflows with DMA (which is clocked from AHB/system clock).

following is my code, Please check out and advice me if anything is wrong.

void MyADCInit()

{

/*Configure the TIM17 IRQ priority */

HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 4 ,0); //set at 5 priority

/* Enable the TIM17 global Interrupt */

HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);

//Stop and disable ADC with all the possible affecting bits...

ADC1->CR &= ~(ADC_CR_ADSTP | ADC_CR_ADSTART | ADC_CR_ADDIS | ADC_CR_ADEN);

//ADC1->CFGR2 &=(~ ADC_CFGR2_CKMODE); //select ADCCLK(Asynchronous clock mode)

ADC1->CFGR2 = ADC_CFGR2_CKMODE_1;

EnableADCClock();

// We need ADC->CFGR1 for

// 16DISCEN - Discontinuous Mode - 0 Disable, 1 Enable

// 15AUTOFF - Auto Off Mode - 0 Disable, 1 Enable

// 14WAIT - Wait Mode - 0 Disable, 1 Enable

// 13CONT - continuous Mode - 0 Disable, 1 Enable

// 12OVRMOD - Overrun mgmt mode - 0 Protects old data from overwritting, 1 overwrites

// 11:10EXTEN[1:0] 00 - disable hardware trigger

// 8:6EXTSEL[2:0] 000 - External trigger source

// 5ALIGN - Data Alignment - 0 Right

// 4:3 RES[1:0] - 00 12 bit resolution

//2SCANDIP - 0 Upward scan

// 1DMACFG - 0 DMA one shot mode

// 0DMAEN - 0 DMA Disabled

//TRG4 for TIM15 external trigger enable for rising edge on TRGO!

ADC1->CFGR1 |= ADC_CFGR1_EXTEN_0 | ADC_CFGR1_EXTSEL_2 | ADC_CFGR1_DISCEN;

//ADC1->SMPR &=(~ ADC_SMPR_SMP_0);

ADC1->SMPR |= ADC_SMPR_SMP_0; //max sample time, invert AND for min

ADC1->IER |= ADC_IER_EOCIE; //end of conversion interrupt enable

Calibrate();

ADC_Enable();

}

void Calibrate()

{

/* (1) Ensure that ADEN = 0 */

/* (2) Clear ADEN by setting ADDIS*/

/* (3) Clear DMAEN */

/* (4) Launch the calibration by setting ADCAL */

/* (5) Wait until ADCAL=0 */

if ((ADC1->CR & ADC_CR_ADEN) != 0) /* (1) */

{

ADC1->CR |= ADC_CR_ADDIS; /* (2) */

}

while ((ADC1->CR & ADC_CR_ADEN) != 0)

{

/* For robust implementation, add here time-out management */

}

ADC1->CFGR1 &= ~ADC_CFGR1_DMAEN; /* (3) */

ADC1->CR |= ADC_CR_ADCAL; /* (4) */

while ((ADC1->CR & ADC_CR_ADCAL) != 0) /* (5) */

{

/* For robust implementation, add here time-out management */

}

}

void ADC_Enable()

{

/* (1) Ensure that ADRDY = 0 */

/* (2) Clear ADRDY */

/* (3) Enable the ADC */

/* (4) Wait until ADC ready */

if ((ADC1->ISR & ADC_ISR_ADRDY) != 0) /* (1) */

{

ADC1->ISR |= ADC_ISR_ADRDY; /* (2) */

}

ADC1->CR |= ADC_CR_ADEN; /* (3) */

while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* (4) */

{

/* For robust implementation, add here time-out management */

}

ADC1->CR |= ADC_CR_ADSTART;

}

void EnableADCClock()

{

//Added ADC clock generation PM

//TIM15 is by defaault an upcounter!

SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN); //enable the clock for TIM15

/*RCC->CR2 |= RCC_CR2_HSI14ON;

while((RCC->CR2 & RCC_CR2_HSI14RDY) == 0)

{

For robust implementation, add here time-out management

}*/

}

The above code does not work and takes the system into hanged state at ADC_RDY check!

Moreover I am trying to trigger this by an external TIM15 TRGO (Which I think I got to work!) but the sad part is with the ADC which is not running at PCLK/2 or PCLK/4 i.e. 3 or 1.25 MHz in my case!

Any suggestions?