Skip to main content
Visitor II
April 26, 2024
Question

How to take ADC data at 166ksps with calculation

  • April 26, 2024
  • 1 reply
  • 1204 views

I want to take ADC data at 166ksps but I am getting after 2 second. Can anyone suggest How can I take ADC data and also perform calculation ? Please give some guidance. 

I am attaching my main.c file.

    This topic has been closed for replies.

    1 reply

    ST Employee
    April 29, 2024

    Hello,

    if I understand right to your problem, program need to read data from ADC and at the same time need to compute some data. For this need there is a DMA which can transfer data from ADC to memory independently on the running program:

    Getting started with ADC - stm32mcu

    Also in your code MCU is computing average of ADC results in program. That can be partially replaced by using longer sampling time in ADC settings and reduce CPU load.

     

    ms10Author
    Visitor II
    April 30, 2024

    Hi @Hl_st 

    Thank you for your response. I have tried as you say by using DMA and using longer ADC sampling time. But it is taking more time.
    As I am using STM32F030F4P6 its clock frequency is 48MHz and 12 bit ADC. It can read ADC up to 1 Mbps.

    I want to read at 166ksps first I was using timer trigger of 6.024 to read adc in that I am getting 166K adc sample at 1 sec but after adding averaging calculation it is giving data after 2 sec.

    is it possible to read adc calculation output at 1 sec ?
    Here I am attaching the DMA ADC code that you have suggest.  Please review if I am doing something wrong.

    ST Employee
    May 13, 2024

    Hello,

    you can try to configure DMA in circular mode and ADC using timer trigger, it will be continuously transferring adc results into the buffer. If the buffer will be for example for 16 values, program can pooling in while loop and based on DMA position in the buffer (DMA1_Channelx->CNDTR) can compute average from every last 8 values. So the code should looks like this:

     

    uint16_t adc_data[16] = {0};
    /* Start ADC and circular DMA transfer */
    HAL_TIM_Base_Start(&htim1);
    HAL_ADC_Start_DMA(&hadc1, adc_data, 16);
     
    uint8_t buf_avrg_ptr = 8;
    while (1){
          if (buf_avrg_ptr == 8 && DMA1_Channel1->CNDTR <= 8){
                /* Compute average from adc_data[0],..., adc_data[7]*/
                buf_avrg_ptr = 16;
          }else if (buf_avrg_ptr == 16 && DMA1_Channel1->CNDTR > 8){
                /* Compute average from adc_data[8],..., adc_data[15]*/
                buf_avrg_ptr = 8;
          }
    }