Skip to main content
Visitor II
January 2, 2022
Question

STM32 U5 ADC (multi channel) + timer + DMA

  • January 2, 2022
  • 4 replies
  • 4467 views

I am working on development project using NUCLEO-U575ZI-Q.

The application is to scan multiple analog signals (4) signals using ADC1 (14 bit). The ADC triggered periodically using Timer 1. The results to be transferred to memory using DMA.

Any sample code available that combines ADC (multi channel) + timer + DMA?

    This topic has been closed for replies.

    4 replies

    Visitor II
    January 3, 2022

    this example for you.

    STM32Cube_FW_L4_V1.17.1\Projects\NUCLEO-L496ZG\Examples_LL\ADC\ADC_SingleConversion_TriggerTimer_DMA

    ST Employee
    September 11, 2023

    Hello @Tvoge.1 ,

    Thank you for your question.

    First, you can download here the STM32Cube MCU Package for STM32U5 series. Under the root "STM32Cube_FW_U5_V1.3.0\Projects\NUCLEO-U575ZI-Q\Examples\ADC\", you will find the ADC_DMA_Transfer project. I suggest you to start from this example and configure the ADC & TIM.

    Here is some guidance about how to configure on CubeMX your application :

    • In Pinout & Configuration > Analog > ADC1
      • Enable Regular Conversions
      • Change the Number Of Conversions to 4
      • Change the External Trigger Conversion Source to Timer 1 Trigger Out event
      • Enable ADC1 global interrupt in NVIC Settings

     

    • In Pinout & Configuration > Analog > TIM1
      • Choose the Clock Source as Internal Clock 
      • Select the PWM Generation no Output for the Channel1 (no output needed since timer is triggering ADC internally)
      • Change your Counter Settings as needed (AutoReload Register, Prescaler...)

    A useful article with more details is "Using Timers to Trigger ADC conversions periodically" and available here. It contains Sample Code using HAL API in it.

    Best regards,

    Pierre

    Visitor II
    March 28, 2024

    Hello  Pierre_Paris,  im trying to do the same project as Tvoge.1 but i want to know if the sampling rat is divided by the number of the channels or the sampling rate is as i determine for all the ADC channels? 

     

    ST Employee
    March 28, 2024

    Hello @Ditzhak

    Thank you for your question and please don't hesitate to create a specific thread for this subject ! 

    In an ADC configuration where multiple channels are being sampled, the sampling time for each channel can be affected by the number of channels being sampled and the time it takes to switch between them. When you configure a timer to trigger the ADC at a certain frequency, this sets the rate at which the ADC conversions are started. If you have multiple channels to sample, ADC will perform a multichannel (scan) contiinuous conversion mode as a sequence.This means that the time required to sample all channels is the sum of the sampling times for each channel plus any additional time required for the ADC to switch between channels.  Each channel have a programmable sampling time.

    Are you aware of AN3116 and this article ?

    What sampling rate do you want to reach ? You can have a look on the DS13737 in ADC characteristics.

    Best Regards,

    Pierre

    Visitor II
    March 28, 2024

    First, thank you for the quick answer. i didn't know any of article you suggested. i'm only two months dealing with the NUCLEO-U575ZI-Q so everything is quite new to me. 

    my project including getting reflections from 4 channels ADC. im using ADC1 and i configured the adc to get External trigger from timer 2. the timer clock is 100M[hz] and i set the auto reload register to a value of 999 (1000-1) to get 100K[hz], for my understanding  this 100K frequency will be use for the ADC sampling rate.

    i have tried to send the data through usart1 to see it in terminal, saved the data as .txt file and convert it through MATLAB to .WAV file then i open the .WAV file in audio software to see spectrogram. the result was for all channels is 25K[hz].

    i have tried to send the data for each channel and the result was decreasing below 15K[hz] which doesnt make sense.

    in the ADC parameters i have configured :

     Scan Conversion Mode - Enabled

    Continuous Conversion Mode - Enabled

    End of sequence of conversion

    Conversion Data Management Mode - DMA Circular mode

    Enable Regular Conversions - Enabled 

    Number Of Conversion - 4

    External Trigger Conversion Source - Timer 2 Trigger Out Event

    Also i'v set the DMA to circular mode, data width for source and destination as half word and i increment the address  destination after transfer.

    this is my definitions & variables:

    #define TXBUFLEN 50

    volatile uint16_t adcResultDMA [20000];

    const int adcChannelCount = sizeof(adcResultDMA)/(sizeof adcResultDMA[0]);

    volatile int adcConversionComplete = 0;

    char txBuf[TXBUFLEN];

    this is what i write in the main:

    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

    HAL_ADC_Start_DMA(&hadc1, (uint16_t*)adcResultDMA, adcChannelCount);

     

    this is what i write in the callback function:

    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

    {

     

    uint32_t i;

    uint32_t ii;

    uint32_t iii;

    uint32_t iiii;

     

     

    for(i = 0; i<=19996; i += 4)

    {

    snprintf (txBuf,TXBUFLEN, /*" CH1 = %d "*/"%d\r\n", adcResultDMA[i]);

    HAL_UART_Transmit(&huart1, (uint8_t*)txBuf, strlen (txBuf), HAL_MAX_DELAY);

    }

     

    for(ii = 1; ii<=19997; ii += 4)

    {

    snprintf (txBuf,TXBUFLEN, " CH2 = %d ", adcResultDMA[ii]);

    HAL_UART_Transmit(&huart1, (uint8_t*)txBuf, strlen (txBuf), HAL_MAX_DELAY);

    }

     

    for(iii = 2; iii<=19998; iii += 4)

    {

    snprintf (txBuf,TXBUFLEN, " CH3 = %d ", adcResultDMA[iii]);

    HAL_UART_Transmit(&huart1, (uint8_t*)txBuf, strlen (txBuf), HAL_MAX_DELAY);

    }

    for(iiii = 3; iiii<=19999; iiii += 4)

    {

    snprintf (txBuf,TXBUFLEN, " CH4 = %d ", adcResultDMA[iiii]);

    HAL_UART_Transmit(&huart1, (uint8_t*)txBuf, strlen (txBuf), HAL_MAX_DELAY);

    }

    }

    can you tell me what i'm doing wrong? thank you again.