Here's an example of using DMA-based ADC sampling with STM32 (HAL library) to read analog temperature sensor data at regular intervals with minimal CPU load.
Goal:
- Use ADC + DMA to sample analog voltage (e.g., from an NTC or LM35 sensor).
- Use TIM3 to trigger ADC every 100ms.
- Store data in a buffer.
- Process temperature data later in your code (e.g., compute average).
Hardware Requirements:
- STM32 microcontroller (e.g., STM32F103C8T6 or STM32F4 series)
- Analog temperature sensor (e.g., LM35 → outputs 10mV/°C)
- Analog input pin (e.g., PA0)
STM32CubeMX Configuration:
1. Enable ADC1:
- Mode: Scan Conversion Disabled
- Continuous Conversion: Disabled
- DMA Continuous Requests: Enabled
- External Trigger: Timer 3 TRGO
- Resolution: 12-bit
2. Enable DMA:
- Circular Mode: Enabled
- Direction: Peripheral to Memory
3. Configure Timer 3:
- Set period to trigger ADC every 100 ms
- TRGO event: Update Event
4. Configure PA0 as analog input
Auto-Generated HAL Code
In main.c:
Define ADC buffer:
c #define ADC_BUF_LEN 16 uint16_t adc_buffer[ADC_BUF_LEN];
Start ADC + DMA:
c HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_BUF_LEN);
This begins continuous DMA transfer from ADC to memory.
Processing Data
In main.c inside the main loop:
c float read_temperature_from_adc(uint16_t raw) { float voltage = (raw / 4095.0f) * 3.3f; // Assuming Vref = 3.3V float temp_c = voltage * 100.0f; // For LM35: 10mV/°C return temp_c; } while (1) { HAL_Delay(1000); uint32_t sum = 0; for (int i = 0; i < ADC_BUF_LEN; i++) sum += adc_buffer[i]; uint16_t avg = sum / ADC_BUF_LEN; float temp = read_temperature_from_adc(avg); printf("Temperature: %.2f°C\r\n", temp); }
Optional: Debug Output
Redirect printf() via UART or SWO for debugging.
Notes:
- DMA in circular mode keeps filling the buffer without CPU intervention.
- If needed, you can use DMA complete callback (HAL_ADC_ConvCpltCallback) to process each batch.
- For multiple channels, enable scan mode and increase DMA buffer accordingly.
Top comments (0)