基于DMA的ADC数据采集 | 8月更文挑战

363 阅读4分钟

这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战

嵌入式系统开发经常会遇到采集模拟量的功能需求,这时就会用到ADC,STM32系列MCU提供了强大的ADC功能,其提供的多通道采集和DMA方式极大的方便了ADC相关的开发流程,本文主要记录一下,如何使用ADC实现基于DMA的多通道模拟量采集功能。

关于ADC的配置,同样可以通过STM32CubeMX来实现,下面是STM32型号和STM32CubeMX的版本信息:

  • MCU:STM32F103C8T6
  • STM32CubeMX:5.5.0

下面是具体的配置步骤

系统基本配置

时钟配置

首先,配置系统时钟,本文基于STM32F103C8T6的一款开发板进行开发,其提供的外部晶振频率为8MHz,所以,对于时钟我们的配置为:

<img src="material/RCC.png"/>

下面进行ClockConfiguration相关的配置,第一步选择时钟源为HSE:8MHZ,第二步选择APB2的时钟源为32MHz,最后一步选择ADC1的时钟频率为8MHz,最终的配置结果如下:

<img src="material/ClockConfig.png"/>

打开ST-Link调试

对于MCU的程序下载和调试,我们选用的是ST-Link,所以选择系统的调试模式为Serial Wire,配置如下:

<img src="material/ST-Link.png"/>。

注:对于通过ST-Link或JTAG下载、调试程序时,需要配置该选项,否则无法下载程序以及在线调试MCU。

配置ADC

功能需求是:

  • 使用ADC1实现模拟量的采集;
  • 两路模拟量采集;
  • 基于DMA实现外设到内存的数据传输;

基本配置

首先是,基本配置选择将要使用的ADC,这里我们使用的是ADC1,其次是选择用于模拟量采集的ADC通道,这里我们选择是ADC1的通道6和通道7,具体配置如下:

<img src="material/ADC_base_config_1.png"/>。

下面是关于ADC的参数配置,主要分为两部分:第一部分为ADC_Setting,第二部分为ADC_Regular_ConversionMode,下面分别解决一下:

  1. ADC_Setting:

    • Data Alignment:Right alignment。表示ADC的regular data register寄存器16bit数据的对齐方式为向右对齐。
    • Scan Conversion Mode:Enable。当使用DMA采集多路模拟量时,使能该选项可以自动扫描ADC的模拟量数据通道,采集模拟量数据。
    • Continuous Conversion Mode:Enable。使能该项时,可以对各个模拟量通道进行循环、连续的数据采集。
  2. ADC_Regular_ConversionMode:

    • Enable Regular Conversions: Enable。打开Regular数据转换模式。对于Regular Conversion和Injected Conversion两种模式的区别可以简单的理解为:Regular Conversion为轮询采集的工作模式,Injected Conversion为中断采集工作模式,并且Injected Conversion比Regular Conversion的优先级高。
    • Nunber of Conversion:2。表示采集的通道数量。
    • Rank 1:表示第一个采集通道,即通道Channel 7,Sample Time为1.5 Cycles,1个Cycle为ADC驱动时钟频率的倒数,本文为 1 Cycle = 1/8M s。
    • Rank 2:表示第二个采集通道,即通道Channel 6,Sample Time为1.5 Cycles,同上。

<img src="material/ADC_base_config_2.png"/>。

DMA配置

进入ADC的DMA配置选项,关于ADC的DMA配置方式如下:

  1. 添加DMA Request:添加ADC1为DMA Reuest,Channel为DMA1 Channel 1,DMA的数据传输方向为:peripheral To Memory(外设到内存),Priori为Low。

  2. 配置DMA Requeset Settings:

  • Mode:Circular。表示DMA循环、连续采集各个ADC通道的模拟量。
  • Data Width为Word。表示DMA传输的数据的基本大小为Word,即四字节。

<img src="material/DMA_Config.png"/>。

好了,配置基本完成了,下面是MCU的PinView,大家可以参考一下。点击Generate Code生成工程代码。

<img src="material/MCU_PinViewpng.png"/>。

功能实现

基于STM32CubeMX生成的代码,完善ADC采集代码,主要就是调用HAL_ADC_Start_DMA启动ADC采集,实现HAL_ADC_ConvCpltCallback接口,当DMA采集完一轮数据之后,会调用该接口通知APP,APP可以在这里完成模拟量的转换功能。

/*其中,pData表示DMA的目标内存地址,Length表示外设向内存传输的数据项的个数。*/

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);

/*处理DMA数据*/
uint32_t val[2];//保存外设通过DMA传输的过来的数据
float v[2];//保存当前采集到的模拟量

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	for(int8_t i = 0; i < 2; i++) {
	v[i] = (val[i] / 4095.0) * 3.274; //参考电压为:3.274V	
}

好了,至此基本完成了基于DMA的ADC采集方式的功能需求。

测试

编译程序,通过ST-Link下载到MCU,搭建好电路,在线监测实时采集到的模拟量数据,模拟量数据源为两路电压模拟量。

<img src="material/test.png"/>。