cancel
Showing results for 
Search instead for 
Did you mean: 

Simultaneous sampling (USART+DMA+Timer)

ardavantycoon
Associate II
Posted on February 13, 2016 at 22:26

Hi guys

I recently started to learn STM32F407. I'm sticking to a problem which likes drinking a glass of water for you, so please help me, I studied many tutorials and watched many videos but 

none explains these modules when they are used together.

I want to continuously sample two channel simultaneously at 10 ksps-12 bit, then send its data through UART to MATLAB.

I used Cubemx to create configuration and initialization for this project but it doesn't use HAL library for multi channels ADC. According to HAL driver user Manual:

Multi mode ADCs Regular channels configuration

 

  • Select the Multi mode ADC regular channels features (dual or triple mode) and configure the DMA mode using HAL_ADCEx_MultiModeConfigChannel() functions.
  • Start the ADC peripheral using HAL_ADCEx_MultiModeStart_DMA(), at this stage the user specify the length of data to be transferred at each end of conversion
  • Read the ADCs converted values using the HAL_ADCEx_MultiModeGetValue() function.

My 1st problem is how to handle this part.

My 2nd problem is general question. Is it correct to use ''HAL_TIM_PeriodElapsedCallback()''  to trigger ADC to start sampling plus send its data through UART?

If you help me by utilizing Cubemx, I am really appreciate. Otherwise I still thanks you for any help  likes example code(which include all these parts together) and whatever you can provide.

#adc #multi-mode-adc #dual-mode-adc-stm32f4 #stm32f4 #dma #usart #no-hablo-hal
6 REPLIES 6
ardavantycoon
Associate II
Posted on February 14, 2016 at 11:56

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6ie&d=%2Fa%2F0X0000000btw%2FVl4HJXI5tfeHfAhk2DdtoVhcevOFW3X90BsRsXVi2hw&asPdf=false
Posted on February 14, 2016 at 19:12

Seems no one wants to contribute!

Pondering the forum participation irony there.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
TDK
Guru
Posted on February 14, 2016 at 19:38

Here's how I would do it:

Set up the ADCs to trigger off of a timer and record into a circular buffer in DMA mode.  Not sure off-hand how to made ADC1 and ADC2 sample simultaneously, but I'm sure there's a way.

On the DMA half-complete transfer, send the first half of the buffer out through UART.

On the DMA complete transfer, send out the second half of the buffer.

If you feel a post has answered your question, please click "Accept as Solution".
ardavantycoon
Associate II
Posted on February 14, 2016 at 20:58

When I finish this project, I will create a full tutorial for it. I know many people will find it useful especially with this new HAL_driver!

I found many post of you (you have two users?) helping people with their projects. I hope you like to continue your collaboration. I know one day these helps will come back to you. 

ardavantycoon
Associate II
Posted on February 14, 2016 at 21:39

Sure, of course I am using DMA. But I don't know how implement it correctly. 

I am going to use ''HAL_ADCEx_MultiModeGetValue(&hadc1);''

according to its definition, it return ADC_CDR which contains both ADC1 & ADC2 values. 

I am going to do this. Do you think I am correct?

char senddata1[];

char senddata2[];

__IO uint32_t ADC_val=0;

__IO uint16_t ADC1_val=0;

__IO uint16_t ADC2_val=0;

ADC_val=HAL_ADCEx_MultiModeGetValue(&hadc1); // it is 32 bit value, I am not sure

ADC1_val=(ADC_val)&0xFFFF; //extract lower 16 bit

ADC2_val=(ADC_val>>16)&0xFFFF; //extract higher 16 bit

sprintf(senddata1,''%d'', ADC_val1); 

sprintf(senddata2,''%d'', ADC_val2); 

HAL_UART_Transmit(&huart3, (uint8_t*)&senddata1,1,10000); //transmit every time interrupt happen.

Is Size=1 correct?

HAL_UART_Transmit(&huart3, (uint8_t*)&senddata2,1,10000);

My second question:  for single conversion I am using ''HAL_ADC_ConvCpltCallback'' in order to initiate uart transmission, but I can't find any call back for multi mode! how about using ''ADC_MultiModeDMAConvCplt'' ?

This the function definition:

uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef* hadc)

{

  /* Return the multi mode conversion value */

  return ADC->CDR;

TDK
Guru
Posted on February 15, 2016 at 03:43

> I am going to use ''HAL_ADCEx_MultiModeGetValue(&hadc1);''

according to its definition, it return ADC_CDR which contains both ADC1 & ADC2 values. 

I am going to do this. Do you think I am correct?

Not sure, I'd put known voltages on the lines and see if they match your expectation.

> My second question:  for single conversion I am using ''HAL_ADC_ConvCpltCallback'' in order to initiate uart transmission, but I can't find any call back for multi mode! how about using ''ADC_MultiModeDMAConvCplt'' ?

I'd imagine since you're using ADC1 as the master ADC, the callback is the same as for single mode.  That is, HAL_ADC_ConvCpltCallback will trigger when the conversion is done, if you've set things up correctly.

> HAL_UART_Transmit(&huart3, (uint8_t*)&senddata1,1,10000); //transmit every time interrupt happen. 

Is Size=1 correct?

It looks like you're sending a string of variable length, so you should be using strlen(senddata1) + 1 instead.  Note that since your baud rate is 92.1x your sample rate, you only have enough time to send 92 bits across UART, which I doubt is enough for your cose.  You'll likely need to send these asynchronously (via DMA), or pool a bunch of values and send them all at once.

It may help to start with a simpler example, such as doing only a single ADC instead of two.  Even if it's not exactly what you want, you end up learning things in the process.

If you feel a post has answered your question, please click "Accept as Solution".