DMA with ADC lets your microcontroller collect data continuously without using the CPU all the time. This saves power and makes your program faster.
0
0
DMA with ADC for continuous sampling in Embedded C
Introduction
You want to measure sensor data like temperature or light continuously.
You need to record analog signals without missing any samples.
You want to free the CPU to do other tasks while data is collected.
You want smooth and fast data collection for real-time processing.
You want to avoid delays caused by manual reading of ADC values.
Syntax
Embedded C
1. Configure ADC for continuous conversion mode. 2. Set up DMA to transfer ADC data to memory buffer. 3. Enable DMA and ADC. 4. Start ADC conversion. 5. Use interrupts or polling to process data when buffer is full.
DMA automatically moves ADC data to memory without CPU help.
Continuous mode means ADC keeps sampling without stopping.
Examples
This sets the ADC to keep sampling automatically.
Embedded C
/* Configure ADC in continuous mode */ ADC_InitTypeDef ADC_InitStruct = {0}; ADC_InitStruct.ContinuousConvMode = ENABLE; ADC_Init(&ADC_InitStruct);
DMA is set to circular mode to keep filling the buffer repeatedly.
Embedded C
/* Configure DMA to transfer ADC data to buffer */ DMA_InitTypeDef DMA_InitStruct = {0}; DMA_InitStruct.Direction = DMA_PERIPH_TO_MEMORY; DMA_InitStruct.PeriphInc = DMA_PINC_DISABLE; DMA_InitStruct.MemInc = DMA_MINC_ENABLE; DMA_InitStruct.Mode = DMA_CIRCULAR; DMA_InitStruct.BufferSize = BUFFER_SIZE; DMA_Init(&DMA_InitStruct);
This starts the ADC conversions and DMA transfers.
Embedded C
/* Start ADC and DMA */
DMA_Cmd(ENABLE);
ADC_Cmd(ENABLE);
ADC_SoftwareStartConv();Sample Program
This program sets up ADC1 to sample channel 0 continuously. DMA2 Stream0 moves ADC data to adc_buffer in circular mode. The CPU can use adc_buffer anytime without stopping ADC.
Embedded C
#include "stm32f4xx.h" #define BUFFER_SIZE 10 uint16_t adc_buffer[BUFFER_SIZE]; void ADC_DMA_Config(void) { // Enable clocks RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // Configure DMA2 Stream0 for ADC1 DMA2_Stream0->CR = 0; DMA2_Stream0->PAR = (uint32_t)&ADC1->DR; // ADC data register DMA2_Stream0->M0AR = (uint32_t)adc_buffer; // Memory buffer DMA2_Stream0->NDTR = BUFFER_SIZE; DMA2_Stream0->CR |= DMA_SxCR_CHSEL_0; // Channel 0 for ADC1 DMA2_Stream0->CR |= DMA_SxCR_MINC; // Memory increment DMA2_Stream0->CR |= DMA_SxCR_CIRC; // Circular mode DMA2_Stream0->CR |= DMA_SxCR_PL_1; // Priority high DMA2_Stream0->CR |= DMA_SxCR_DIR_0; // Peripheral to memory DMA2_Stream0->CR |= DMA_SxCR_EN; // Enable DMA stream // Configure ADC1 ADC1->CR2 = 0; ADC1->CR2 |= ADC_CR2_DMA; ADC1->CR2 |= ADC_CR2_DDS; // DMA requests continuous ADC1->CR2 |= ADC_CR2_CONT; // Continuous conversion ADC1->SQR3 = 0; // Channel 0 ADC1->SMPR2 = ADC_SMPR2_SMP0_0 | ADC_SMPR2_SMP0_1; // Sample time ADC1->CR2 |= ADC_CR2_ADON; // Enable ADC for (volatile int i=0; i<1000; i++); // Delay ADC1->CR2 |= ADC_CR2_SWSTART; // Start conversion } int main(void) { ADC_DMA_Config(); while(1) { // Main loop can process adc_buffer data // For example, check adc_buffer[0] value if (adc_buffer[0] > 2000) { // Do something } } }
OutputSuccess
Important Notes
Make sure DMA and ADC clocks are enabled before configuration.
Use circular DMA mode to keep filling the buffer without stopping.
Remember to set ADC sample time to get stable readings.
Summary
DMA with ADC lets you collect analog data continuously without CPU load.
Configure ADC in continuous mode and DMA in circular mode for smooth data flow.
Use the buffer filled by DMA to process data anytime in your program.