Skip to main content
Graduate
September 30, 2024
Solved

Not able to get required samples from ADC DMA triggered using timer [STM32F103C8]

  • September 30, 2024
  • 3 replies
  • 1997 views

Hello,

I am acquiring samples from 50Hz Sine Wave through a CT and want to get 100 samples of this signal (T=20ms). For this, I need each sample at 200us apart so I get an array of 100 bytes. I have following clock setup:

APB1 = 36Mhz; ADC = 12Mhz

TIM3 Event: 36,000,000/ 7,200 = 5,000Hz = 200us

ADC Sample Time: Sampling Time + 12.5 cycles = 239.5 + 12.5 = 252 cycles => 1/12Mhz X 252 = 21us

Screenshot_44.png

 

TIM3:

Screenshot_45.png

ADC:

Screenshot_46.pngUsing above settings & calculations, SOC is supposed to complete said ADC in 21us and sample time is 200us which is fine. Here is the code:

/* USER CODE BEGIN PV */
uint16_t adc_value[500] = {0};
/* USER CODE END PV */

 /* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start(&htim3);
 HAL_ADCEx_Calibration_Start(&hadc1);
 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_value, sizeof(adc_value));
 /* USER CODE END 2 */

/* ADC Config */
hadc1.Instance = ADC1;
 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.NbrOfConversion = 1;

sConfig.Channel = ADC_CHANNEL_5;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
/* ADC Config */

/* TIM3 Config */
 htim3.Instance = TIM3;
 htim3.Init.Prescaler = 0;
 htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim3.Init.Period = 7200;
 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
/* TIM3 Config */

 

I am getting samples in the 400 byte array but I am supposed to get a complete sine wave cycle in first 100 byte but the cycle is completed in 200 bytes. Even I tried to increased sampling time (Counter Period: 14,400) it shows same the result. Here is the samples vs. data result:

Screenshot_47.png

 

Please guide, what I may be missing in the code or in calculations to get a complete 50Hz Sine Wave cycle in ADC of 100 samples.

 

Regards

Shahid

 

 

    This topic has been closed for replies.
    Best answer by TDK

    > But how come 14400-1 is giving 200us period?

    Oh, now that I understand the issue you're describing, the answer is easy:

    TDK_0-1727722046543.png

     

    The timer clock is 72 MHz, not 36 MHz.

    14400 / 72 MHz = 200 us.

    This all checks out, yes?

    3 replies

    Super User
    September 30, 2024

    It looks like you have 2 complete sine waves in 200 samples, which is 1 per 100 samples, yes?

    Counter period is off by one. It should be 7199.

    x4ceAuthor
    Graduate
    September 30, 2024

    More on this, I have to subtract the offset i.e. 2036 (approx.) then should I get the voltage in float or continue squaring value in integers? What would be the best less computing method you recommend?

    Thanks

    Super User
    September 30, 2024

    > But how come 14400-1 is giving 200us period? ADC tied Timer gives event at each rising/ falling edge?

    > At Counter Period = 7200-1, period is 200us but is it like a PWM signal so ADC is triggered 2 times?

     

    It doesn't make logical sense that these two would have the same period. Perhaps you are not updating the code before running, or not running the code you think you are. Consider toggling a pin in a relevant callback to verify clock settings. Make the pin a PWM output and verify it gets updated at the expected rate.

    TDKAnswer
    Super User
    September 30, 2024

    > But how come 14400-1 is giving 200us period?

    Oh, now that I understand the issue you're describing, the answer is easy:

    TDK_0-1727722046543.png

     

    The timer clock is 72 MHz, not 36 MHz.

    14400 / 72 MHz = 200 us.

    This all checks out, yes?

    x4ceAuthor
    Graduate
    October 1, 2024

    Yes, I have missed that and mistakenly considering 36MHz as Timer 3 clock as well. Thanks for pointing out.

    More on this, I have to subtract the offset i.e. 2036 (approx.) then should I get the voltage in float or continue squaring value in integers? What would be the best less computing method you recommend?

    Thanks

    Super User
    October 1, 2024

    I'd prefer squaring the integers and summing them if you're trying to get RMS or something similar. The STM32F1 doesn't have a math coprocessor so it needs to emulate the float operation in software, which is very slow.