cancel
Showing results for 
Search instead for 
Did you mean: 

24 ksps on SDADC on STM32F37x

mk
Associate II
Posted on January 04, 2013 at 10:52

We have aSTM32F37x eval board for testing and I'd like to set up some code that will sample 24kHz 16-bit with the SDADC. According to documentation it should be able to sample 50 ksps if you don't use multiplexing. (Nice)

However, I can only make it output ~12 ksps. (That's not enough.) Has anyonesucceededwith more? I have some sample code that I can show: (It's just code from the ST examples through.)

int
sdadc_initialize(
void
)
{
SDADC_AINStructTypeDef SDADC_AINStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint32_t SDADCTimeout = 0;
/* MPX2102_SDADC APB2 interface clock enable */
RCC_APB2PeriphClockCmd(MPX2102_SDADC_CLK, ENABLE);
/* PWR APB1 interface clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Enable MPX2102_SDADC analog interface */
PWR_SDADCAnalogCmd(MPX2102_SDADC_PWR, ENABLE);
/* Set the SDADC divider: The SDADC should run @6MHz */
/* If Sysclk is 72MHz, SDADC divider should be 12 */
RCC_SDADCCLKConfig(RCC_SDADCCLK_SYSCLK_Div12);
/* GPIOE Peripheral clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
/* MPX2102_SDADC channel 8P (PE8) and channel 8N (PE9) */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = MPX2102_GPIO_PIN_P | MPX2102_GPIO_PIN_N;
GPIO_Init(MPX2102_SDADC_GPIO_PORT, &GPIO_InitStructure);
/* Select External reference: The reference voltage selection is available
only in SDADC1 and therefore to select the VREF for SDADC2/SDADC3, SDADC1
clock must be already enabled */
SDADC_VREFSelect(MPX2102_SDADC_VREF);
/* Insert delay equal to ~5 ms */
msleep(5);
/* Enable MPX2102_SDADC */
SDADC_Cmd(MPX2102_SDADC, ENABLE);
/* Enter initialization mode */
SDADC_InitModeCmd(MPX2102_SDADC, ENABLE);
SDADCTimeout = SDADC_INIT_TIMEOUT;
/* wait for INITRDY flag to be set */
while
((SDADC_GetFlagStatus(MPX2102_SDADC, SDADC_FLAG_INITRDY) == RESET) && (--SDADCTimeout != 0));
if
(SDADCTimeout == 0)
{
/* INITRDY flag is not set */
return
1;
}
/* Analog Input configuration conf0: use differential mode and gain = 4 */
SDADC_AINStructure.SDADC_InputMode = SDADC_InputMode_Diff;
SDADC_AINStructure.SDADC_Gain = MPX2102_SDADC_GAIN;
SDADC_AINStructure.SDADC_CommonMode = SDADC_CommonMode_VSSA;
SDADC_AINStructure.SDADC_Offset = 0;
SDADC_AINInit(MPX2102_SDADC, SDADC_Conf_0, &SDADC_AINStructure);
/* select MPX2102_SDADC channel 8 to use conf0 */
SDADC_ChannelConfig(MPX2102_SDADC, MPX2102_SDADC_CHANNEL, SDADC_Conf_0);
/* select channel 8 */
SDADC_InjectedChannelSelect(MPX2102_SDADC, MPX2102_SDADC_CHANNEL);
/* Select an external trigger */
SDADC_ExternalTrigInjectedConvConfig(MPX2102_SDADC, SDADC_ExternalTrigInjecConv_T19_CC2);
/* Select rising edge */
SDADC_ExternalTrigInjectedConvEdgeConfig(MPX2102_SDADC, SDADC_ExternalTrigInjecConvEdge_Rising);
/* Exit initialization mode */
SDADC_InitModeCmd(MPX2102_SDADC, DISABLE);
/* NVIC Configuration */
NVIC_InitStructure.NVIC_IRQChannel = SDADC1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* configure calibration to be performed on conf0 */
SDADC_CalibrationSequenceConfig(MPX2102_SDADC, SDADC_CalibrationSequence_1);
/* start MPX2102_SDADC Calibration */
SDADC_StartCalibration(MPX2102_SDADC);
/* Set calibration timeout: 5.12 ms at 6 MHz in a single calibration sequence */
SDADCTimeout = SDADC_CAL_TIMEOUT;
/* wait for MPX2102_SDADC Calibration process to end */
while
((SDADC_GetFlagStatus(MPX2102_SDADC, SDADC_FLAG_EOCAL) == RESET) && (--SDADCTimeout != 0));
if
(SDADCTimeout == 0)
{
/* EOCAL flag can not set */
return
2;
}
/* Configure and enable TIM19 to trigger the SDADC conversions */
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Enable TIM19 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM19, ENABLE);
/* TIM19 Configuration */
TIM_DeInit(TIM19);
/* Fills each TIM_TimeBaseInitStruct member with its default value */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
/* Time base configuration: MPX2102_SDADC will be triggered each sysclk/Period
= 72MHz/3000 = 24 KHz */
TIM_TimeBaseStructure.TIM_Period = 3000;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM19, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel2 (OC2) */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period/2;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM19, &TIM_OCInitStructure);
/* Enable TIM19 counter */
TIM_Cmd(TIM19, ENABLE); 
return
0;
}

#sdadc #stm32f37x
7 REPLIES 7
mk
Associate II
Posted on January 04, 2013 at 11:03

The Timer in the above code *will* output 24kHz. (I've tested.) The SDADC is just too slow to keep up. I've also tried using the Timer interrupt instead of the SDADC, like ST do in the eval FW. It doesn't make a difference though. The SDADC is still too slow.

Posted on January 04, 2013 at 11:44

Read the fine manual 🙂

You need to set FAST bit in SDADC_CR2.

JW
mk
Associate II
Posted on January 04, 2013 at 11:50

Well, the fine manual says that the FAST bit is only for ''continuous mode'' ... and I've also tried enabling it. It didn't make a difference ^^

Posted on January 04, 2013 at 12:05

> Well, the fine manual says that the FAST bit is only for ''continuous mode'' ...

.. then obviously ''continuous mode'' is the only way to achieve the advertised 50ksps...

> and I've also tried enabling it. It didn't make a difference ^^

.. tried enabling FAST *and* the ''continuous mode?''

JW

mk
Associate II
Posted on January 04, 2013 at 13:39

You've got a point there. 

It'll be rather tricky to get correct sample rate though. Unless I use a timer to read from the continuous sdadc. They wont be in sync but ... perhaps that won't matter. This needs some study.

Posted on January 04, 2013 at 14:26

BTW Period has an N-1 form

TIM_TimeBaseStructure.TIM_Period = 3000 - 1;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
lowpowermcu
Associate II
Posted on January 08, 2013 at 09:43

Hi all,

reference manual says ''The conversion of each channel normally requires 360 SDADC clock cycles (60 μs at 6 MHz). In fast continuous mode (FAST=1), the first conversion takes still 360 SDADC clocks, but then each subsequent conversion finishes in 120 SDADC clocks''

so if SDADC is clocked at 6 MHz and if fast mode enabled, the conversion takes 6MHz/120 = 50 Ksps.

so if SDADC is clocked at 6 MHz and if fast mode disabled, the conversion takes 6MHz/360 =6 Ksps.

using ST Library just enable the fast mode before enabling the SDADC: /* Enable fast mode */ SDADC_FastConversionCmd(SDADC1, ENABLE); /* Enable SDADC1 */ SDADC_Cmd(SDADC1, ENABLE); MCU Lüfter

BTW Period has an N-1 form

TIM_TimeBaseStructure.TIM_Period = 3000 - 1;