2017-10-31 07:46 PM
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
2017-10-31 07:56 PM
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.
2017-11-01 02:42 AM
What does it mean by maximal mode?
Please clarify.
2017-11-01 08:59 AM
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
2017-11-01 09:37 AM
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
2018-01-15 05:59 AM
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 minADC1->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?