单片机
返回首页

STM32CubeMX系列教程7:模数转换(ADC)

2020-06-23 来源:eefocus

本章通过两个例程介绍STM32的模数转换器(ADC),第一个通过ADC采集内部温度传感器通道电压,然后得出MCU内部温度。第二个通过DMA的方式采集两个ADC通道电压。


1.ADC

本章程序在串口printf工程的基础上修改,复制串口printf的工程,修改文件夹名。击STM32F746I.ioc打开STM32cubeMX的工程文件重新配置。ADC1外设选择温度传感器通道。


ADC1配置如下,选择默认设置。其Date Alignment设置为数据右对齐。


生成报告以及代码,编译程序。在adc.c文件中可以看到ADC初始化函数。

在stm32f7xx_hal_adc.h头文件中可以找到如下ADC操作函数。和串口一样,ADC也可以通过三种方式控制。


01

/** @addtogroup ADC_Exported_Functions_Group2

02

  * @{

03

  */

04

/* I/O operation functions ******************************************************/

05

HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);

06

HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc);

07

HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);

08

  

09

HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout);

10

  

11

HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);

12

HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);

13

  

14

void              HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc);

15

  

16

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

17

HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc);

18

  

19

uint32_t          HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);

20

  

21

void       HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);

22

void       HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc);

23

void       HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc);

24

void       HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc);


在main()函数前面声明变量保存AD采集的值。


1

/* USER CODE BEGIN PV */

2

/* Private variables ---------------------------------------------------------*/

3

uint16_t AD_Value = 0;

4

/* USER CODE END PV */


在main()函数while(1)循环里面添加函数声明变量保存AD采集的值。


01

/* USER CODE BEGIN WHILE */

02

while (1)

03

{

04

/* USER CODE END WHILE */

05

 

06

/* USER CODE BEGIN 3 */

07

      /*##-1- Start the conversion process #######################################*/ 

08

      HAL_ADC_Start(&hadc1);

09

 

10

      /*##-2- Wait for the end of conversion #####################################*/ 

11

       /*  Before starting a new conversion, you need to check the current state of

12

                  the peripheral; if it’s busy you need to wait for the end of current

13

                  conversion before starting a new one.

14

                  For simplicity reasons, this example is just waiting till the end of the

15

                  conversion, but application may perform other tasks while conversion

16

                  operation is ongoing. */

17

      HAL_ADC_PollForConversion(&hadc1, 50);

18

 

19

      /* Check if the continous conversion of regular channel is finished */ 

20

      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))

21

      {

22

          /*##-3- Get the converted value of regular channel  ######################*/

23

          AD_Value = HAL_ADC_GetValue(&hadc1);

24

          printf('MCU Temperature : %.1f¡ærn',((AD_Value*3300/4096-760)/2.5+25));

25

      }

26

      HAL_Delay(1000);

27

}

28

/* USER CODE END 3 */


HAL_ADC_Start(&hadc1)为启动ADC装换,

HAL_ADC_PollForConversion(&hadc1, 50);表示等待转换完成,第二个参数表示超时时间,单位ms.

HAL_ADC_GetState(&hadc1)为换取ADC状态,HAL_ADC_STATE_REG_EOC表示转换完成标志位,转换数据可用。

HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC)就是判断转换完成标志位是否设置。

HAL_ADC_GetValue(&hadc1);读取ADC转换数据,数据为12位。查看数据手册可知,寄存器为16位存储转换数据,数据右对齐,则转换的数据范围为0~2^12-1,即0~4095.


AD_Value*3300/4096为将转换后的数据转化为电压,单位为mV,参考电压为3.3V。查询数据手册可以电压和温度的关系。经过计算公式装换后等到MCU内部温度值。


编译程序并下载到开发板。打开串口调试助手。设置波特率为115200。串口助手上会显示MCU温度。


2.ADC_DMA

前面介绍了通过ADC轮询的方式采集单通道的数据。现在介绍一下通过DMA方式采集多通道的数据。

复制串口printf工程的工程,修改文件夹名。点击STM32F746I.ioc打开STM32cubeMX的工程文件重新配置。本实验使用微雪Analog Test Board接到SPI1接口。更具原理图配置PA6,PA7管脚作为ADC1的输入管脚。


ADC1配置:使能扫描转换模式(Scan Conversion Mode),使能连续转换模式(Continuous Conversion Mode),使能DMA连续请求。ADC规则组选择转换通道数为2(Number Of Conversion)。其他为默认设置。


添加DMA设置,设置为连续传输模式,数据长度为字。

生成报告以及代码,编译程序。在adc.c文件中可以看到ADC初始化函数。

在main函数前面添加变量。其中ADC_Value作为转换数据缓存数组,ad1,ad2存储PA6,PA7的电压值。


1

/* USER CODE BEGIN PV */

2

/* Private variables ---------------------------------------------------------*/

3

uint32_t ADC_Value[100];

4

uint8_t i;

5

uint32_t ad1,ad2;

6

/* USER CODE END PV */


在while(1)前面以DMA方式开启ADC装换。HAL_ADC_Start_DMA()函数第二个参数为数据存储起始地址,第三个参数为DMA传输数据的长度。


1

/* USER CODE BEGIN 2 */

2

  /*##-1- Start the conversion process and enable interrupt ##################*/ 

3

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);

4

/* USER CODE END 2 */


由于DMA采用了连续传输的模式,ADC采集到的数据会不断传到到存储器中(此处即为数组ADC_Value)。ADC采集的数据从ADC_Value[0]一直存储到ADC_Value[99],然后采集到的数据又重新存储到ADC_Value[0],一直到ADC_Value[99]。所以ADC_Value数组里面的数据会不断被刷新。这个过程中是通过DMA控制的,不需要CPU参与。我们只需读取ADC_Value里面的数据即可得到ADC采集到的数据。


其中ADC_Value[0]为通道6(PA6)采集的数据,ADC_Value[1]为通道7(PA7)采集的数据,ADC_Value[2]为通道6采集的数据,如此类推。数组偶数下标的数据为通道6采集数据,数组奇数下标的数据为通道7采集数据。


在while(1)循环中添加应用程序,将采集的数据装换为电压值并输出。


01

/* USER CODE BEGIN WHILE */

02

  while (1)

03

  {

04

  /* USER CODE END WHILE */

05

  

06

  /* USER CODE BEGIN 3 */

07

        HAL_Delay(500);

08

        for(i = 0,ad1 =0,ad2=0; i < 100;)

09

        {

10

            ad1 += ADC_Value[i++];

11

            ad2 += ADC_Value[i++];

12

        }

13

        ad1 /= 50;

14

        ad2 /= 50;

15

  

16

        printf('rn******** ADC DMA Example ********rnrn');

17

        printf(' AD1 value = %1.3fV rn', ad1*3.3f/4096);

18

        printf(' AD2 value = %1.3fV rn', ad2*3.3f/4096);

19

  }

20

  /* USER CODE END 3 */


程序中将数组偶数下标数据加起来求平均值,实现均值滤波的功能,再将数据装换为电压值,即为PA6管脚的电压值。同理对数组奇数下标数据处理得到PA7管脚的电压值。


编译程序并下载到开发板。打开串口调试助手。设置波特率为115200。串口助手上会显示采集到的电压值,旋转Analog Test Board上电位器,输出的电压值会改变。 

编译程序并下载到开发板。打开串口调试助手。设置波特率为115200。串口助手上会显示采集到的电压值,旋转Analog Test Board上电位器,输出的电压值会改变。       


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • 短波AM发射器电路设计图

  • 带有短路保护系统的5V直流稳压电源电路图

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章