How to Using ADC Scan Mode with DMA in STM32F407

 In STM32F407, the ADC (Analog-to-Digital Converter) can be used in Scan Mode with DMA (Direct Memory Access) to efficiently sample multiple analog channels without CPU intervention.




📚 1. Overview

  • ADC Scan Mode: Allows the ADC to scan through multiple channels sequentially.
  • DMA (Direct Memory Access): Automatically transfers ADC conversion results from ADC data registers to a specified memory location.
  • Use Case Example: Reading multiple analog sensors (e.g., temperature, light, voltage sensors).

⚙️ 2. Hardware Setup

  • Microcontroller: STM32F407 (e.g., STM32F4 Discovery board)
  • Analog Inputs: Connect analog sensors to ADC channels (e.g., PA0, PA1, PA2).
  • Power Pins: Ensure VREF+ is connected to 3.3V and VREF- to GND.
  • DMA Channel: DMA2 Stream0 (ADC1).

🛠️ 3. Configuration Steps

Step 1: Enable Peripheral Clocks

Enable clocks for ADC1, GPIOA, and DMA2.

Step 2: Configure GPIO Pins for ADC

  • Set GPIO pins (e.g., PA0, PA1, PA2) as analog mode.

Step 3: Configure ADC in Scan Mode

  • Enable Scan Mode.
  • Set Resolution (12-bit recommended).
  • Enable Continuous Conversion Mode.
  • Configure Channels in the desired sequence.

Step 4: Configure DMA

  • Use DMA2, Stream0, Channel 0 for ADC1.
  • Set Peripheral Address: ADC1 Data Register.
  • Set Memory Address: Memory buffer in RAM.
  • Enable Circular Mode for continuous data transfer.

Step 5: Start ADC and DMA

  • Enable DMA Stream.
  • Start ADC conversions.

💻 4. Example Code (STM32CubeIDE)

c

#include "stm32f4xx.h" #define ADC_CHANNELS 3 uint16_t ADC_Buffer[ADC_CHANNELS]; void ADC_DMA_Init(void) { // 1. Enable Clocks RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // Enable GPIOA clock RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // Enable ADC1 clock RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // Enable DMA2 clock // 2. Configure GPIOA (PA0, PA1, PA2 as Analog Mode) GPIOA->MODER |= (3 << (0 * 2)) | (3 << (1 * 2)) | (3 << (2 * 2)); // 3. Configure DMA DMA2_Stream0->CR = 0; // Clear control register DMA2_Stream0->PAR = (uint32_t)&ADC1->DR; // Peripheral address (ADC data register) DMA2_Stream0->M0AR = (uint32_t)ADC_Buffer; // Memory address (buffer) DMA2_Stream0->NDTR = ADC_CHANNELS; // Number of data to transfer DMA2_Stream0->CR |= (0 << 25) | // Channel 0 (3 << 16) | // Priority level: High (1 << 10) | // Memory increment mode (0 << 11) | // Peripheral increment mode (disabled) (1 << 8) | // Circular mode enabled (1 << 6); // Memory size: Half-word (16-bit) DMA2_Stream0->FCR = 0x00000000; // FIFO control disabled DMA2_Stream0->CR |= (1 << 0); // Enable DMA Stream // 4. Configure ADC ADC1->SQR3 = (0 << 0) | (1 << 5) | (2 << 10); // Channels: 0 -> 1 -> 2 ADC1->SQR1 = (ADC_CHANNELS - 1) << 20; // 3 conversions ADC1->CR1 = ADC_CR1_SCAN; // Enable scan mode ADC1->CR2 = ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_CONT | ADC_CR2_ADON; // Enable DMA, DDS, continuous mode, ADC on // Start Conversion ADC1->CR2 |= ADC_CR2_SWSTART; } int main(void) { ADC_DMA_Init(); while (1) { // ADC_Buffer[0] -> PA0 // ADC_Buffer[1] -> PA1 // ADC_Buffer[2] -> PA2 uint16_t sensor1 = ADC_Buffer[0]; uint16_t sensor2 = ADC_Buffer[1]; uint16_t sensor3 = ADC_Buffer[2]; // Add application code here } }

📝 5. Explanation of Key Settings

  1. ADC Configuration:

    • Scan Mode: Multiple channels scanned sequentially.
    • Continuous Conversion Mode: ADC continuously converts channels.
    • DMA Mode: DMA automatically transfers data to memory.
  2. DMA Configuration:

    • Memory Increment Mode: Allows writing to consecutive memory addresses.
    • Circular Mode: DMA restarts after completing a transfer.
    • Peripheral Address: ADC Data Register.
    • Memory Address: ADC_Buffer array in RAM.

📊 6. Verifying ADC Data

  • Use a debugger to monitor ADC_Buffer[] in memory.
  • Connect known analog voltages to PA0, PA1, PA2.
  • Calculate voltage from ADC value:
Vout=ADC_Value4095×VREFV_{\text{out}} = \frac{{ADC\_Value}}{{4095}} \times V_{\text{REF}}
  • With a 3.3V reference:
Vout=ADC_Value4095×3.3V_{\text{out}} = \frac{{ADC\_Value}}{{4095}} \times 3.3

🛡️ 7. Common Troubleshooting Tips

  1. DMA Not Transferring Data:

    • Check DMA stream enable bit.
    • Verify ADC1 is set to trigger DMA.
  2. Unexpected ADC Values:

    • Ensure GPIO pins are set to Analog Mode.
    • Verify reference voltage and hardware connections.
  3. DMA Overflow Errors:

    • Ensure buffer size matches the number of ADC channels.

🎯 8. Conclusion

Using ADC Scan Mode with DMA on STM32F407 is an efficient way to read multiple analog inputs while minimizing CPU load. This approach is ideal for applications like sensor arrays, data acquisition systems, and robotics.

评论

此博客中的热门博文

How to interface CPLD with microcontroller?

How to Make an Alarm System on an FPGA?

The difference between Microcontrollers and Microprocessors