Capturing SPI data with DMA with ESP32 and ch32V307 - Page 1
Forum section: electronics / general

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: June 25, 2025, 01:57:31 pm
content: Hi,I want to capture External ADC data using DMA @50K samples per second, I need your input on how to do it with the AD7606 part, for the ESP32-S3 and CH32V307 parts.Since the Sampling data is relatively fast, I do not want to use interrupts so the only option is using DMA, so the CPU is ready for doing some DSP and calculations on the captured Data.The best scenario for me is to capture data in a dual circular buffer and generate the Interrupt after certain amounts of Data is captured, say 1000 samples.I have configured the DMA to be triggered by a timer to start capturing the ADC data with SPI ( I have done it with UART in this threadhttps://www.eevblog.com/forum/microcontrollers/dma-timed-data-transfer-on-ch32v307/msg5949705/#msg5949705), the problem is that the ADC is 8 channels and at each Timer update the DMA should capture 8 frames, But with this Config each time it would capture only 1 SPI frame.So I should find a way to capture 8 frames of SPI at each timer update and do it 1000 times and then generate an interrupt and switch the Receive buffer to the next one, so the CPU processing can be done on the Updated data.I want your ideas and inputs on how to do it?

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: June 26, 2025, 11:42:22 am
content: Any hints?

author: hgl10
author_rank: Contributor
timestamp: July 01, 2025, 03:38:36 pm
content: use two timers. master to pulse CNV (PWM), slave timer freq 8 times that of master timer. slave timer to trigger dma to transmit and receive SPI.

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: July 02, 2025, 08:28:43 am
content: QuoteHow they should be synced? since the slave timer would overflow 8 times at one overflow of master timer. Also How to get the total 1K sample dma interrupt? should it be done using 3 timers? is it possible?

author: hans
author_rank: Super Contributor
timestamp: July 02, 2025, 11:52:44 am
content: You could take a look at the advanced control timers, as it has a repetition counter.But it would become a convoluted setup:- Have a simple DMA-capable timer at 10kHz to program (via DMA) the advanced timer to start.- Have the advanced timer run at the burst sample speed you need, which generates DMA requests to transmit SPI data.- Have a DMA channel to receive SPI data and put it inside the sample buffer- The advanced timer should stop triggering itself when a certain repetition threshold is reached. I'm not sure if thats possible. At worst, you'll need to find a seperate DMA channel to stop the timer (e.g. trigger SPI Tx on CC1 DMA, and TIM stop on the UPDATE DMA Request, or after 8 transfers have been completed.You could count the 1000 samples on the master timer's DMA channel. Create a buffer with 1000 identical transfer words, and set the DMA stream to circular. You can then get half and full transfer interrupts, no need to swap buffers or reenable/reprogram streams.But all in all, this requires 4 DMA streams and 2 timers. Maybe worth it for 400k interrupts/second.Not sure about how to do this on ESP32, I've never looked into how clever its peripheral design is. You could probably do something as orchestrated as above on there.This is a reason why I look forward to more MCUs featuring linked list DMA controllers. You can avoid the hassle with 4 DMA channels plus timers completely, as you can program a (admittedly large) chain of read/write requests and trigger events to be completed. I think one question that remains unanswered here is how you're going to drive the chip-select pin of the ADC chip, but perhaps you can use either the primary or secondary capture-compare pins in some kind of PWM mode.

author: hgl10
author_rank: Contributor
timestamp: July 02, 2025, 03:54:37 pm
content: Quote from: ali_asadzadeh on July 02, 2025, 08:28:43 amstm32/ch32 timers are pretty powerful. chained them together, use one timer's signal to trigger another to start or reset. slave timer need to be 8 times faster.dma can be configured to fire 1 interrupt for 1000 samples, check ch32's examples (you may want to use half complete interrupt).It use two timers and two DMA channels(slave timer to trigger DMA to send SPI tx(for the sclk), rx dma is auto pushing to buffers).

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: July 03, 2025, 12:10:37 pm
content: thanks hgl10 and hans for your inputs, would you please share some pseudo code too? Also one thing regarding the use of timer came to my mind, suppose we have a convert clock, at the convert edge the ADC needs a minimum amount of time like 4uS to convert the 8 channels, and since chaining timers would spread the read 8 times across the whole converter clock time, I guess maybe one channel data would be over written by the ADC, We should find a way to burst read 8 channels of ADC, then wait for the next conversion.

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: July 09, 2025, 11:12:18 am
content: I tried to test it with STM32 timers in this threadhttps://www.eevblog.com/forum/microcontrollers/stm32f30k-oneplus-dma/But surprisingly I do not get any DMA transfers based on the timer update, do you have any Idea what I'm doing wrong?