cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 U5 ADC (multi channel) + timer + DMA

Tvoge.1
Associate II

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?

5 REPLIES 5
lbui
Associate

this example for you.

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

Pierre_Paris
ST Employee

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

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

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? 

 

Pierre_Paris
ST Employee

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

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Ditzhak
Associate II

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.