2022-03-17 12:53 PM
Which is the best approach to manage the use of DMA and "control" the flow of data? Implementing some interrupt when the buffer is filled? Is it possible to put one channel of the DMA on "hold" while the other has full priority? Or two DMA are required for this?
At the moment, transmitting the buffer through UART without DMA is acceptable, I can have the CPU occupied for this. Should I then leave the ADC DMA as normal or circular? And then call HAL_UART_Transmit after the buffer is filled. I understand that if I leave the ADC DMA in circular mode, I'll lose some data during the UART transmission, but that may also be acceptable at the moment.
The "first version" I think would be to fill the buffer using ADC DMA in normal mode, once the buffer is filled I transfer it through UART without DMA and then "restart" ADC DMA scan. Which are the key functions to do so?
I'm new to STM32 programming, so any help is appreciated.
Thanks in advance!
Kind regards,
Luiz Guilherme Enger
2022-03-17 01:03 PM
I can already read the signal and fill a buffer using ADC DMA, but then I'm now sure how to proceed.
2022-03-17 02:30 PM
The typical way is to put the ADC into circular DMA mode, and process each half of the buffer (i.e. transmit over UART) during the half- and full-complete flags/callbacks.
Multiple DMA streams can work at once.
Get the ADC part working alone, then get the UART part working alone, then put them together.
2022-03-17 02:53 PM
> Basically, I would like to have some sort of oscilloscope (for positive values only and below 1 MHz signal).
Be aware of the voltage limits on ADC inputs and the amount of bandwidth available in UART. The UART will have considerably lower bandwidth than the amount of data you can generate.
2022-03-18 03:05 AM
Some math:
For a 1 MHz signal the Nyquist theorem require at least 2 mega samples per second.
If your samples are 8 bits you gets 16 M bits/s
On UART 1 byte need 10 bits (start + stop) => 2M * 10 = 20 Mbits/s.
Are you sure you can manage to transmit 20 Mbits/s to your PC?
2022-03-18 09:27 AM
I already got ADC and UART transmission working by itself. Just putting them together sounds a little more complicated. What I would like to do is:
At the moment I have something like this:
#define ADC_BUF_LEN 4096
uint16_t adc_buf[ADC_BUF_LEN];
uint8_t buffer_filled = 0;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, ADC_BUF_LEN);
in the while(1) loop:
if (buffer_filled){
HAL_UART_Transmit(&huart2, ... )
buffer_filled = 0;
(now of course outside the while loop)
void HAL_ADC_ConvCpltCallback() {
buffer_filled = 1;
}
If ADC DMA is set to circular, I get UART data non-stop (I added some delays inside the while loop). Then I don't know if ADC DMA already started to overwrite the first half of the buffer... If I set ADC DMA to normal, I get only one reading, even if I put HAL_ADC_Start_DMA( ) again after buffer_filled = 0
About the 1 MHz frequency, that was just a lambda value. I am interested in signals around 10 kHz, so having an effect 1 Msps from ADC is more than enough. I'm aware of Nyquist theorem, thank you.
2022-03-18 11:10 AM
You need a kind of pipe line: On each ADC buffer you need to do 4 operations:
The ADC DMA only have 2 flip/flop buffer on circular mode. Then you need temporary work buffers. You need 3 temp buffers because you have 3 operations to do on ADC data:
It ADC Copy Comp UART
A0 x x x
ht A1 A0->W0 x x
ct A0 A1 >W1 W0 x
ht A1 A0 >W2 W1 W0
ct A0 A1 >W0 W2 W1
ht A1 A0 >W1 W0 W2
etc
A0/A1 = ADC circular buffers
W0/W1/W2 = work buffers
This works only if the compute task and the DMA transmit task are no longer than 1 ADC data buffer acquisition.
2022-03-21 10:37 AM
Thanks! I implemented part of it and it works. I decided to copy only the first half of the ADC DMA buffer to a work buffer (HalfConvCplt sets a flag to start the copy in the while(1) loop). At the moment the second half is ignored, just to ensure that the values the work buffer is copying won't change during the copy process. Then I'll take a look on how to transmit this work buffer through UART DMA. Using only half the ADC buffer is some waste of resource but it seems that it will ensure that the computation and transmission will be faster than the complete ADC buffer acquisition.