cancel
Showing results for 
Search instead for 
Did you mean: 

Require exact synchronization between start of DAC DMA and start of ADC DMA

CactusPete
Associate III

Our measurements required an exact time between successive DAC and ADC DMA conversions.  Time measurements are in the microsecond level and we currently have too much variation in timing triggering DMA transfers via software and using a software time delay between DAC and ADC DMA conversions.

We selected STM chips based on HAL to reduce the time to production and therefore are seeking a solution via HAL.  We are using the H753ZI and V chip.  I've been working on trying to use linked timers for over a week, but I believe the HRTIM may be the best option, but is far too complex and would probably takes months to figure out.

Would it be possible to get a simple example of DAC DMA and ADC DMA that are started at N microseconds apart and using a 1000 point buffer each using HAL?

This is really the only issue barring us from moving to production.

 

Thanks,

Peter

 

 

14 REPLIES 14
TDK
Guru

You can trigger the DAC with CH1 and the ADC with CH2 of the same timer. HRTIM not needed. Perfectly in sync (and if not, timing can be adjusted with 10ns or so precision).

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

How would one start a DAC DMA transfer and ADC DMA transfer?  Toggling the sampling is not the issue. I need to start each DMA transfer with an exact time delay and be able to do this whenever required.  If one timer can start two DMA transfers with a delta time I cannot see how this can be done.

I was able to use timer 12 to start a DAC DMA transfer, but no way to really get any further. Any chance of an example?

 

Thanks,

Peter

> If one timer can start two DMA transfers with a delta time I cannot see how this can be done.

If (for example) CH1 and CH2 trigger the ADC and DAC, respectively, set CCR1 and CCR2 based on the delay you want. This is the "Pulse" value in CubeMX.

 

ADC setup:

TDK_0-1741387178899.png

 

DAC setup (send data to DAC->DR on CH2 event):

TDK_1-1741387242003.png

 

Not sure if all of this is clickable in CubeMX but a lot of it is. I'd recommend getting each piece working separately, then combine.

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

I followed your guidance and have attached a sample project.  The ioc file is based on the full project hence the extra bits that are not referenced.   I'm not able to get the DAC or ADC DMA transfers to trigger based on TIM1.  I've set it up similar to your suggestion.  I'm assuming that these two lines will do nothing until timer 1 channels start sending update events against the DMA transfers setup in software??  Not really sure how things tie together.  I did setup the pulses section of channel 1 and 2.

I'm using the blue button to try and trigger the DAC / ADC cycle and timing I'm trying to get working.  I have a simple ramp setup for DAC output.  But nothing ever triggers since I do not ever get an event in HAL_DAC_ConvCpltCallbackCh1 or HAL_ADC_ConvCpltCallback.

Not sure what I'm missing.  I assume I need to setup the DMA transfers in software and then start timer 1.

Thanks,

Peter

CactusPete
Associate III

 I just found some issues with my project. Let me work on this a bit more and don't waste time looking at the above code.

Thanks so much,

Peter

CactusPete
Associate III

Been trying for two days to follow your example, but I cannot get this working.  I must be missing something.  I'm using TIM2 since it's on the same bus (TIMERS on APB1 bus: TIM2,3,4,5,6,7,12,13,14) as other timers I may need.

This is my TIM2 setup

CactusPete_2-1741632707030.png

 

This is my ADC setup - using TIM2 channel 2

CactusPete_0-1741632564823.png

 

This is my DAC setup - I do not see TIM2 Channel 1 event even though it is setup

CactusPete_1-1741632645347.png

I start TIM2 in button pressed ( HAL_TIM_Base_Start(&htim2); ) and only ever see the DAC HAL_DAC_ConvCpltCallbackCh1 event trigger.  Never see HAL_ADC_ConvCpltCallback trigger.

I'm really frustrated and running out of time.  I not sure what I'm missing.  Could you have a look at my test app to see what I'm doing wrong or missing?

Thanks,

Peter

 

 

The following code/project does a burst of 1000 synchronized ADC+DAC samples at 1ms increments using HAL using TIM1. One is triggered on update event, the other on CC1 event, so change the channel 1 pulse value to change the time between them.

 

// global variables
#define CAPACITY 1000
volatile uint16_t gDacBuffer[CAPACITY];
volatile uint16_t gAdcBuffer[CAPACITY];

...

  // code to start samples
  if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)gAdcBuffer, CAPACITY) != HAL_OK) {
      Error_Handler();
  }
  if (HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (uint32_t*)gDacBuffer, CAPACITY, DAC_ALIGN_12B_R) != HAL_OK) {
      Error_Handler();
  }
  if (HAL_TIM_Base_Start(&htim1) != HAL_OK) {
      Error_Handler();
  }

 

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

I'm doing exactly that, but no matter what value I put into the OC channel pulse value the ADC delay does NOT change.  Also, the OC channel never starts with what is above.  I have to add HAL_TIM_OC_Start_IT( &htim2, TIM_CHANNEL_2 );

Note: ADC1 cannot use tim2 channel 1 also for tim1 ADC1 cannot use channel1  (but the issue is no change in delay when pulse value is changed).

I have a 1 millisecond period setup in timer2.  I have channel2 setup for 'Output Compare Channel2'.  Mode is Toggle.

Pulse value of 1000 should equal a 1 second delay. Changing it to 5000 should give a 5 second delay - easy to see since I have two different coloured LEDs in the complete events for ADC and DAC.   ADC does trigger after DAC, but changes to PULSE do nothing.

I've seen similar posts, but no solution. Is HAL just completely unusable??? This should be easy, but I have no learned from register level due to how long that takes. Thought I could use HAL - up until now it's been fine.

Without an exact delay between DAC and ADC (1us to 1000 us) this project is over, so I'm hoping someone knows why this is happening. Either with a HAL fix or some register level code to replace all this.  It's only using one timer and the timer is really the problem.

 

Thanks,

Peter

Peter,

I went back to my project and changed the timer so that it had an update rate of 10 Hz, then I changed the CH1 pulse to be half of ARR and changed the capacity to 5. I then looked at the tick (HAL_GetTick()) to see how many ticks elapsed until each change in the DMA NDTR register, which marks when the data was received from ADC or sent to DAC. We should see 100 ticks between updates and they should be offset by 50, and that is exactly what we see:

TDK_0-1741736179679.png

This shows the code is doing what you want--ADC and DAC are converted with a delay with respect to each other, with DAC being converted 50 ms before the ADC.

 

I then changed pulse to be 20% of ARR. Results are as expected:

TDK_1-1741736254341.png

 

I know it's frustrating, but unfortunately with code you do usually need to get it 100% correct or it doesn't work. Consider using the provided example exactly until you have it up and running. You may need to do some minor translating of the IOC settings to your chip. You do not need to start the timer channel.

There are many other ways to set this up, but this is one that works.

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