2019-03-15 03:48 AM
Hello everyone
I am having trouble understanding the relationship between the registers and the callback functions for my application. Briefly put, I am transferring 2 values to the DAC via DMA using TIM6 as interrupt at a rate of 50 Hz. I want to sample another value after each of the two DAC values appears at the output, and for that I set flags in the callbacks to start the ADC in my main loop. Intuitively, I would think that HAL_DAC_ConvHalfCpltCallbackCh1 is called after the first value appears at the output, and HAL_DAC_ConvCpltCallbackCh1 is called after the second value appears at the output, but it seems as though the data registers indicate otherwise when I look at the oscilloscope timing diagrams.
The DAC is set up with the following parameters:
TIM6 is set up with the following parameters:
I start the DAC and TIM6 like this:
And I set a pin to monitor when the callbacks are called:
And another pin in the main while loop to monitor the data registers of the DAC:
The first values that are loaded into the DAC array are 1266 (0x4F2) and 1216 (0x4C0) which is why I am testing for 0x4F2 above.
On the oscilloscope PIN1 is the yellow line corresponding to when the callbacks are called and the blue line is PIN2 that is toggled when the dataholding and data output register is changed. The image is shown below:
The yellow line is a pulse corresponding to 20 milliseconds as expected (since I toggle it in the half and full complete callbacks of a 50 Hz DAC rate). So according to this figure the HAL_DAC_ConvHalfCpltCallbackCh1 is called almost the same time as the DHR12R1 is changed to 0x4F2. And the HAL_DAC_ConvCpltCallbackCh1 is called almost the same time as the DOR1 register is set to 0x4F2.
I don't know if I am missing something but it seems as though the blue pulse should have appeared before the yellow pulse even started? This is causing all of my samples to be delayed by half a cycle (20ms). The first DAC value that I can measure after the half conversion complete callback is not even 1266 but 0 (or 52 mV in this case due to DAC nonlinearity) as shown below:
The yellow line is again the pin that is toggled in the callbacks and the blue line in this case is the DAC output. So it seems as though the value of 0 is loaded into the output and only then is 1266 loaded.
Any help would be greatly appreciated (my masters degree depends on it :))
Cheers
Solved! Go to Solution.
2019-03-16 12:23 PM
Do you really need to use DMA for updating a DAC every 10000 usec?
At this scale, you could manually write the DAC register with Timer callbacks?
2019-03-16 03:36 AM
What's the question?
When the first trigger from TIM6 arrives to DAC, it causes the current value of holding register (which is after reset 0) to be transferred to the output register (ie. nominally 0V is output on the DAC pin), and then triggers a DMA transfer which transfers 1266 to the holding register. As your DMA NDTR is probably set to 2 (says my crystal cube), the DMA half-transfer interrupt occurs. The second trigger from TIM6 20ms later transfers 1266 from the holding register to output register (setting the appropriate voltage on the DAC output pin); then it triggers a DMA transfer which transfers 1216 to holding register, and the DMA transfer complete interrupt occurs.
Read the DAC chapter in the RM. You did not care to tell us which STM32 model are you using; so assuming it's STM32F4, using RM0090 rev.17, chapter 19.4.7 DMA requests quite clearly says:
As DAC_DHRx to DAC_DORx data transfer occurred before the DMA request, the very first
data has to written to the DAC_DHRx before the first trigger event occurs.
JW
2019-03-16 12:23 PM
Do you really need to use DMA for updating a DAC every 10000 usec?
At this scale, you could manually write the DAC register with Timer callbacks?
2019-03-17 12:55 AM
Thank you @Community member. You have pretty much answered my question. I was just confused as to why the value of 0 first appears on the output after the conversion half complete callback. And sorry for not stating it, but I am using the STM32F4.
Regards
Riaan
2019-03-17 12:56 AM
@S.Ma Thank you for the suggestion. I have actually implemented this just now and it works perfectly fine if I just update the value manually in the TIM interrupt every 20 ms.