STM32F103 ADC hangs with short sample times

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
heiko
Posts: 2
Joined: Sat Jun 28, 2014 8:00 pm

STM32F103 ADC hangs with short sample times

Post by heiko »

Hi,

for a motor controller application, I am trying to sample voltage using ADC1 as often as possible. I have configured the ADC clock to 14MHz by setting in mcuconf.h:

Code: Select all

#define STM32_NO_INIT                       FALSE
#define STM32_HSI_ENABLED                   TRUE // 8MHz HSI RC -> 4MHz PLL Source
#define STM32_LSI_ENABLED                   FALSE
#define STM32_HSE_ENABLED                   FALSE
#define STM32_LSE_ENABLED                   FALSE
#define STM32_SW                            STM32_SW_PLL
#define STM32_PLLSRC                        STM32_PLLSRC_HSI //STM32_PLLSRC_HSE
#define STM32_PLLXTPRE                      STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE                  14 // -> SYSCLK 56MHz; 72MHz ist only possible with external oscillator (HSE); 56MHz chosen to be able to have 14MHz ADC clock
#define STM32_HPRE                          STM32_HPRE_DIV1 // AHB Prescaler: /1
#define STM32_PPRE1                         STM32_PPRE1_DIV2 // APB 1 Prescaler: /2 -> APB1 frequency 28MHz; 36MHz max; to TIM2-7,12-14 etc
#define STM32_PPRE2                         STM32_PPRE2_DIV1 // APB 2 Prescaler: /1 -> APB2 frequency 56MHz; 72MHz max (only with HSE); to TIM1,8-11, ADC prescaler etc
#define STM32_ADCPRE                        STM32_ADCPRE_DIV4 // ADC Prescaler: /4 -> ADC clock frequency 14MHZ; 14MHz max
#define STM32_USB_CLOCK_REQUIRED            TRUE
#define STM32_USBPRE                        STM32_USBPRE_DIV1P5
#define STM32_MCOSEL                        STM32_MCOSEL_NOCLOCK
#define STM32_RTCSEL                        STM32_RTCSEL_NOCLOCK //STM32_RTCSEL_LSI //STM32_RTCSEL_HSEDIV
#define STM32_PVD_ENABLE                    FALSE
#define STM32_PLS                           STM32_PLS_LEV0


My Conversion Group is:

Code: Select all

#define ADC_GRP1_NUM_CHANNELS   1
#define ADC_GRP1_BUF_DEPTH      1
static adcsample_t samples1[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];

static const ADCConversionGroup adcgrpcfg1 = {
  TRUE,
  ADC_GRP1_NUM_CHANNELS,
  adccallback,
  adcerrorcallback,
  0, ADC_CR2_TSVREFE,           // ADC_CR1, ADC_CR2; ADC_CR2_TSVREFE = Temperature sensor and V REFINT enable
  0, // ADC sample time register 1 (ADC_SMPR1)
  ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5),                            // SMPR2
  ADC_SQR1_NUM_CH(ADC_GRP1_NUM_CHANNELS),  // ADC regular sequence register (ADC_SQRx)
  0,
  ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
};


Now the problem is that the controller appears to hang when the sample time is too short. I have a breakpoint set to when the main() function is called and the controller always reaches this breakpoint. However, the shorter the sample time, the more likely it is that the controller hangs afterwards. With ADC_SAMPLE_239P5, it works most of the time, and I never got it working with 28P5 or less.
When I sample two channels in the group, I can set one to 1P5, but cannot set the second channel to less than 28P5 or it will always hang.

I have read Chibios documentation, STM reference manual and searched the web up and down and am still without a clue.

There are non-chibios examples that show that sampling with 1P5 on one channel is possible (http://www.micromouseonline.com/2009/05 ... the-stm32/) and with a conversion time of 14 cycles I should be able to get 1Mio samples per second.

What am I doing wrong? Any ideas?

Thanks a lot in advance!

Heiko
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: STM32F103 ADC hangs with short sample times

Post by Giovanni »

Hi,

Probably it is saturating the CPU with ISRs, you sample just one channel so the ADC sends an interrupt about every microsecond, the ISR alone takes more than that time.

You may try to sample that channel in a large circular buffer, this way the driver has to serve just two interrupt, one at half buffer, the one at end buffer. For example use a 256 samples buffer and process 128 samples at time.

If filling a buffer is not a solution for you then you should implement your own sample code and use it instead of adcConvert(), I suggest to not use ISRs nor DMA, just poll the ADC for data.

Giovanni
Post Reply