立即注册 找回密码

微雪课堂

搜索
微雪课堂 首页 STM32 STM32CubeMX系列教程 查看内容

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

2016-5-3 14:09| 发布者: MyMX1213| 查看: 97342| 评论: 26|原作者: MyMX1213

摘要: 本章通过两个例程介绍STM32的模数转换器(ADC),第一个通过ADC采集内部温度传感器通道电压,然后得出MCU内部温度。第二个通过DMA的方式采集两个ADC通道电压。 ... ...
本章通过两个例程介绍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也可以通过三种方式控制。

/** @addtogroup ADC_Exported_Functions_Group2
  * @{
  */
/* I/O operation functions ******************************************************/
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);
 
HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout);
 
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);
 
void              HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc);
 
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);
HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc);
 
uint32_t          HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);
 
void       HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);
void       HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc);
void       HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc);
void       HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc);

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

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint16_t AD_Value = 0;
/* USER CODE END PV */

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

  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
        /*##-1- Start the conversion process #######################################*/  
        HAL_ADC_Start(&hadc1);
 
        /*##-2- Wait for the end of conversion #####################################*/  
         /*  Before starting a new conversion, you need to check the current state of 
                    the peripheral; if it’s busy you need to wait for the end of current
                    conversion before starting a new one.
                    For simplicity reasons, this example is just waiting till the end of the 
                    conversion, but application may perform other tasks while conversion 
                    operation is ongoing. */
        HAL_ADC_PollForConversion(&hadc1, 50);
 
        /* Check if the continous conversion of regular channel is finished */  
        if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC)) 
        {
            /*##-3- Get the converted value of regular channel  ######################*/
            AD_Value = HAL_ADC_GetValue(&hadc1);
            printf("MCU Temperature : %.1f¡æ\r\n",((AD_Value*3300/4096-760)/2.5+25));
        }
        HAL_Delay(1000);
  }
  /* 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的电压值。

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint32_t ADC_Value[100];
uint8_t i;
uint32_t ad1,ad2;
/* USER CODE END PV */

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

  /* USER CODE BEGIN 2 */
    /*##-1- Start the conversion process and enable interrupt ##################*/  
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);
  /* 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)循环中添加应用程序,将采集的数据装换为电压值并输出。

/* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
        HAL_Delay(500);
        for(i = 0,ad1 =0,ad2=0; i < 100;)
        {
            ad1 += ADC_Value[i++];
            ad2 += ADC_Value[i++];
        }
        ad1 /= 50;
        ad2 /= 50;
 
        printf("\r\n******** ADC DMA Example ********\r\n\r\n");
        printf(" AD1 value = %1.3fV \r\n", ad1*3.3f/4096);
        printf(" AD2 value = %1.3fV \r\n", ad2*3.3f/4096);
  }
  /* USER CODE END 3 */

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

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

731

顶一下

刚表态过的朋友 (731 人)

相关阅读

发表评论

最新评论

引用 游客 2019-5-27 20:24
请问一下,这个串口print的工程是哪一个呀,教程里面没有找到。
引用 游客 2019-4-9 10:22
HAL_ADCEx_Calibration_Start这个函数没有啊?难道不是库函数,需要自己写?
引用 游客 2019-3-1 10:54
HAL_ADCEx_Calibration_Start这个函数必须的啊,千万别漏了各位
引用 游客 2019-1-25 15:51
为什么 用ADC1  用两个通道 AD采集只能是给一个通道值  另一个根本没有值
引用 游客 2019-1-2 15:09
: 需要校准!!!HAL_ADCEx_Calibration_Start(&hadc),浪费了一天时间来研究为什么不准,还换了一个芯片,好在有风枪,哭了。 ...
没有这个函数呀?
引用 游客 2018-12-29 17:13
数据长度可以设置半字吗
引用 游客 2018-12-16 21:43
不同芯片的CPU内部温度计算公式不同,需要查找相应的数据手册, 例如STM32F103C8T6的计算公式为:((AD_Value*3300/4096-760)/2.5+25)
引用 游客 2018-11-12 18:24
: 请问一下我读到的数据不会变化是什么原因?
我的也一样,一样的问题
引用 游客 2018-11-12 18:24
我用f103 设置好之后 数值不会变,怎么调也没用
引用 游客 2018-10-24 17:14
请问一下我读到的数据不会变化是什么原因?
引用 游客 2018-8-27 20:04
温度怎么几百的哇
引用 游客 2018-8-8 16:11
需要校准!!!HAL_ADCEx_Calibration_Start(&hadc),浪费了一天时间来研究为什么不准,还换了一个芯片,好在有风枪,哭了。
引用 游客 2018-3-16 22:05
CLK設定多少?
引用 sjh13140 2018-3-8 11:06
请问下NVIC需要配置ADC吗
引用 练皮境 2018-1-22 15:48
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);中定义了数据传输总数量100,while(1)中读完100个数据后,再读不是数组里的数据不变了吗?
引用 游客 2018-1-19 14:37
Decide that you must find the time to exercise.It’s virtually like being a children in a sweet shop, and you just want to dive in and attempt everything! You are so enthusiastic that you have accessibility to this gold info that you may want to execute every advertising approach concurrently. Consumers usually think about an offer and do some research in regard to it prior to deciding whether or not to buy. You need more oxygen, because more oxygen equals more energy. Why do all the work for le ...
引用 游客 2017-11-26 11:17
非常棒么么哒
引用 游客 2017-10-27 16:00
我用这个方法驱动SDADC,电压一直为0V,不知道两种adc驱动方式有什么不同
引用 游客 2017-10-27 15:59
试试看
引用 游客 2017-8-17 17:06
真的不错,代码验证通过,感谢!

查看全部评论(26)

CubeMX教程

微雪官网|产品资料|手机版|小黑屋|微雪课堂. ( 粤ICP备05067009号 )

GMT+8, 2019-12-14 20:55 , Processed in 0.018979 second(s), 19 queries .

Powered by Discuz! X3.2 © 2001-2013 Comsenz Inc & Style Design

返回顶部