立即注册 找回密码

微雪课堂

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

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

2016-5-3 14:09| 发布者: MyMX1213| 查看: 118361| 评论: 31|原作者: 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上电位器,输出的电压值会改变。         

895

顶一下

刚表态过的朋友 (895 人)

相关阅读

发表评论

最新评论

引用 游客 2020-8-10 12:05
ADC2不能配置DMA吗
引用 游客 2020-6-18 21:39
为什么输出的电压为PA6和PA7的呢?是因为ADC1中配置的 channel 6 和 channel 7吗?
引用 游客 2020-6-10 08:56
为什么我的电压源转动电压值不变,必须要重新复位才会改变电压值
引用 游客 2020-3-31 10:41
ad1,ad2数值没有清零会一直加下去的。
引用 游客 2020-3-30 01:41
为什么一直为0,我用f103c8t6
引用 游客 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个数据后,再读不是数组里的数据不变了吗?

查看全部评论(31)

CubeMX教程

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

GMT+8, 2020-8-10 19:02 , Processed in 0.022312 second(s), 19 queries .

返回顶部