小蜜蜂笔记
嵌入式开发与物联网应用教育践行者

【STM32基础教程09】STM32的ADC开发基础

独家干货:本课程对应视频的B站链接:
https://www.bilibili.com/video/av87017878?p=9

STM32的ADC资源概述

STM32F103ZE芯片(144脚)中有ADC1ADC2ADC3共3个12位逐次逼近型模数转换器,具有18个测量通道,可测量16个外部2个内部信号源(内部温度和内部参考电压)。这2个内部信号源只能连接到ADC1
ADC的各个通道的A/D转换可以单次连续扫描间断模式执行。
A/D转换结果以左对齐右对齐的方式,存储在16位规则组或者注入组数据寄存器中。

按照A/D转换的组织形式来划分,ADC的模拟输入通道分为规则组和注入组两种。
ADC可以对一组最多16个通道按照指定的顺序逐个进行转换,这组指定的通道称为规则组
在实际应用中,可能需要中断规则组的转换,临时对某些通道进行转换,好像这些通道注入了原来的规则组,故称注入组,最多由4个通道组成。

ADC启动与停止相关的HAL库函数

//查询,阻塞方式,启动ADC
HAL_StatusTypeDef    HAL_ADC_Start(ADC_HandleTypeDef* hadc);
//查询,阻塞方式,停止ADC
HAL_StatusTypeDef    HAL_ADC_Stop(ADC_HandleTypeDef* hadc);
//中断,非阻塞方式,启动ADC
HAL_StatusTypeDef    HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);
//中断,非阻塞方式,停止ADC
HAL_StatusTypeDef    HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);

ADC转换结果读取的HAL库函数

uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);

参数1:hadc,ADC实例指针。
返回值:uint32_t,ADC转换结果。

查询方式,阻塞式A/D转换HAL库函数

HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout);

参数1:hadc,ADC实例指针。
参数2:Timeout,超时时间。
返回值:HAL_StatusTypeDef,函数执行状态。
应用实例:用查询的方式,进行一次A/D采样并将结果读出。
uint16_t  ADC_Value = 0;
//以查询的方式启动ADC
HAL_ADC_Start(&hadc);
//等待一次规则组的ADC转换完成,并将结果读出
if(HAL_OK == HAL_ADC_PollForConversion(&hadc1,10))
{
    ADC0_Value = HAL_ADC_GetValue(&hadc1);
}

中断方式,非阻塞式A/D转换HAL库函数

应用实例:用中断的方式,进行一次A/D采样并将结果读出。
uint16_t  ADC_Value = 0;
//以中断的方式启动ADC
HAL_ADC_Start_IT(&hadc);
//重写ADC转换完成中断回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    ADC0_Value = HAL_ADC_GetValue(&hadc1);
}

实训案例:ADC单次数据采样与电压换算

XMF07AXMF07C开发板上,利用STM32CubeMXKeil5协同开发,完成以下的功能: 
【1】将ADC_IN0设置为12位ADC,右对齐,启用中断。
【2】分别用查询中断这2种方式,每隔0.5秒采样一次ADC的数据。
【3】将每次读取到的ADC采样值转换为对应电压值,发送到上位机。
【4】LED1作为采样指示灯,在ADC转换过程中点亮,其余时间熄灭。

#include "stdio.h"

#define LED1_ON()  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)
#define LED1_OFF()  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)

uint16_t ADC0_Value = 0, ADC0_Volt = 0;
uint8_t str_buff[64];
void UR1_Send_Info()
{
    sprintf((char *)str_buff,"采样值:%d,电压值:%d.%d%dV\r\n",ADC0_Value,ADC0_Volt/100,(ADC0_Volt%100)/10,ADC0_Volt%10);
    HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000);
}

用查询,阻塞的方式来实现

void Get_ADC_Value()
{
    HAL_ADC_Start(&hadc1);
    LED1_ON();
    if(HAL_OK == HAL_ADC_PollForConversion(&hadc1,10))
    {
        ADC0_Value = HAL_ADC_GetValue(&hadc1);
	DC0_Volt = ADC0_Value * 330 / 4096;
    }
    UR1_Send_Info();
    LED1_OFF();
    HAL_ADC_Stop(&hadc1);
}
//在mian()函数中添加以下代码:
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
    Get_ADC_Value();        //启动一个阻塞式的ADC转换并读取数据
    UR1_Send_Info();        //向上位机发生采样值和电压值
    HAL_Delay(500);         //延时0.5秒,再进行下一次ADC采样
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

用中断,非阻塞的方式来实现

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)
    {
	ADC0_Value = HAL_ADC_GetValue(&hadc1);    //读取ADC转换结果
	ADC0_Volt = ADC0_Value * 330 / 4096;      //将采样值换算成电压值
	UR1_Send_Info();                          //向上位机发生ADC采样信息
	LED1_OFF();                               //关闭LED1采样指示灯
    }
}
//在mian()函数中添加以下代码:
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
    HAL_ADC_Start_IT(&hadc1);   //启动一个非阻塞式的ADC转换并读取数据
    LED1_ON();                  //点亮LED1采样指示灯
    HAL_Delay(500);             //延时0.5秒,再进行下一次ADC采样
   /* USER CODE END WHILE */
   /* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
赞(34)
未经允许不得转载:小蜜蜂笔记 » 【STM32基础教程09】STM32的ADC开发基础

小蜜蜂笔记 更专业 更方便 更高效

联系我们精品小店