场景引入: 描述需要同时或快速轮询采集多个模拟信号的应用(如:多路传感器读取、音频处理、电机控制反馈、电池监控)。
传统方法的痛点:
单通道轮询:速度慢,CPU需要频繁参与启动、等待转换、读取结果。
多通道轮询:同样需要CPU频繁干预,通道切换和读取占用大量CPU时间。
中断方式:每转换完一个点或通道就触发中断,在高采样率或多通道时中断风暴消耗CPU资源。
解决方案登场: 提出ADC多通道扫描 + 连续转换模式 + DMA转运的组合拳。
核心优势:
极低CPU占用: DMA自动搬运数据,CPU只在需要处理完整数据块时才介入。
高效率:ADC连续转换,通道自动扫描,DMA后台搬运,实现接近ADC硬件极限的吞吐率。
确定性:数据存储在循环缓冲区中,易于实现实时处理(如滤波、控制)。
简化软件设计: 数据自动填充到指定数组,程序逻辑更清晰。
一、概念解析
ADC (模数转换器):
简述功能,将模拟电压转换为数字值。
多通道扫描模式 (Scan Mode):ADC自动按预定义顺序依次转换多个通道。
连续转换模式 (Continuous Conversion Mode):ADC完成一次扫描序列后,不停止,立即自动开始下一次扫描序列转换。
DMA (直接存储器访问):
原理:独立于CPU的硬件模块,能在存储器和外设(如ADC)之间直接搬运数据。
作用:在ADC转换完成新数据时,自动将数据寄存器(`ADCx->DR`)的值搬运到内存(数组)中,无需CPU干预。
循环缓冲区 (Circular Buffer):
概念:一块首尾相连的内存区域(通常是数组)。
DMA模式:配置DMA为循环模式(`CIRCULAR`)。当DMA搬运数据到达缓冲区末尾时,自动回到开头重新开始填充,覆盖旧数据。
关键作用:实现数据的连续无缝采集,新数据不断覆盖最旧的数据。程序始终可以访问最近`N`个采样点的数据(`N`为缓冲区大小)。
触发源 (Trigger Source): 什么启动一次ADC转换序列?通常使用内部定时器触发(`TIMx_TRGO`)以实现精确的采样间隔(采样率控制)。
二、效果实现
使用stm32f103c8t6主控芯片,cubemx配置,HAL库编程
关键配置步骤
基础时钟配置我就不多说了,直接上关键配置
开启ADC连续循环模式

打开DMA
开启循环转运,其他的都是默认配置,具体设置就是循环从寄存器搬运出数据

最后别忘记设置ADC时钟频率

三、代码实现
主循环外
uint16_t buffer[5]; //DMA转运接收数组
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)buffer, 3); //开启DMA,循环转运三个数据,也就是数组的0、1、2.
//因为配置的时候选择的半字,所以定义数组是uint16_t,这个函数需要uint32_t,最好强转一下
HAL_ADCEx_Calibration_Start(&hadc1); //ADC校准
主循环想要用的时候,直接查看数组的值就可以了,这里我串口打印出来
sprintf(amd,"%d %d %d \r\n",buffer[0],buffer[1],buffer[2]);
HAL_UART_Transmit(&huart1, (uint8_t *)amd, strlen((char *)amd), HAL_MAX_DELAY);
HAL_Delay(1000);
看最终效果
总结
ADC多通道连续循环DMA采集的核心价值:高效、低CPU占用、实时性强。
关键配置要素:扫描序列、连续模式、定时器触发、DMA循环模式、合理缓冲区。
后续可探索方向:过采样提高分辨率、与DAC配合、更复杂的数据处理算法。

3826

被折叠的 条评论
为什么被折叠?



