1.多通道DMA传输

adc配置连续转换模式,ADC在完成一次转换(或一次扫描序列)后,自动开始下一次转换,无需再次调用 HAL_ADC_Start
DMA配置
代码
/* ADC buffer for DMA */
uint16_t adc_buffer[3]; // DMA缓冲区

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  
     /* 校准ADC */
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
  /* 启动ADC和DMA */
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, 3);    //数据存入adc_buffer

  while (1)
  {
  }
}

2.多通道DMA传输(乒乓缓存)

简述:
  • 当DMA将数据传输到 buffer1(Ping)时,CPU可以同时处理 buffer2(Pong)中的数据。
  • 当 buffer1 填满后,DMA切换到 buffer2,CPU则处理刚填满的 buffer1。
  • 如此循环,形似“乒乓”球的来回切换。
原理:
存储6个数据进入缓冲区
前3个存入Buffer1,使能DMA半中断处理buffer1
后3个存入buffer2,使能DMA中断处理adc_buffer2
 uint16_t adc_buffer1[3]; // 第一个缓冲区(保证两个地址是连续的)
 uint16_t adc_buffer2[3]; // 第二个缓冲区(保证两个地址是连续的)
 
   /* 启动ADC和DMA */
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer1, BUFFER_SIZE*2);
  // 前3个存入Buffer1,后3个存入buffer2
代码配置:
确保dma中断使能
主程序
/* ADC buffers for ping-pong mechanism */
uint16_t adc_buffer1[3]; // 第一个缓冲区(保证两个地址是连续的)
uint16_t adc_buffer2[3]; // 第二个缓冲区(保证两个地址是连续的)
uint16_t* current_adc_buffer = adc_buffer1; // 当前就绪的缓冲区
volatile uint8_t buffer_ready = 0; // 缓冲区就绪标志
volatile uint32_t sample_counter = 0; // 采样计数器,用于控制输出频率


//DMA半中断
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
  if (hadc->Instance == ADC1)
  {
    current_adc_buffer = adc_buffer1; // 处理第一个缓冲区
    buffer_ready = 1;
  }
}

//DMA全中断
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  if (hadc->Instance == ADC1)
  {
    current_adc_buffer = adc_buffer2; // 处理第二个缓冲区
    buffer_ready = 1;
  }
}


int main(void)
{
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();

  HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);  /* 校准ADC */
  /* 启动ADC和DMA */
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer1, 3*2); //存储6个数据进入缓冲区,前3个存入Buffer1,后3个存入buffer2

  while (1)
  {
    /* 检查缓冲区是否就绪 */
    if (buffer_ready)
    {
      buffer_ready = 0; // 重置标志
      sample_counter++;

      /* 每4000次采样输出一次(约1秒,视ADC时钟和采样时间调整) */
      if (sample_counter >= 10000)
      {
        sample_counter = 0;
        char adc_str[64];
        sprintf(adc_str, "CH1: %u, CH2: %u, Temp: %u\n",
                current_adc_buffer[0], // ADC1_IN1
                current_adc_buffer[1], // ADC1_IN2
                current_adc_buffer[2]); // Temperature Sensor
        SEGGER_RTT_printf(0, "%s", adc_str);
      }
    }
  }
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐