目录
基本原理
以一个恒温锅炉为例:通过温度传感器,将温度变化转换为电压变化。通过ADC将模拟的电压变化,转换为数字变化,将其编码。中央处理器根据温度数据,进行计算和逻辑控制。计算结果通过DAC转化为电压/电流信号,控制加热和冷却。
A/D转换一般要经过采样、 保持、量化和编码4个过程,将时间和幅值连续的模拟量转化为时间和幅值离散的数字量。
A/D转换器的几个技术指标
量程:指ADC所能输入模拟信号的类型和电压范围,即参考电压。信号类型包括单极性和双极性。
转换位数:量化过程中的量化位数n。A/D转换后的输出结果用n位二进制数来表示。例: 10位ADC 的输出值就是0~1023。
分辨率: ADC能够分辨的模拟信号最小变化量。公式:分辨率=量程/2n。例:量程为单极性0-5V,8位ADC的分辨率是:5/256= 0.0195V
转换时间:ADC完成一次完整的A/D转换所需要的时间,包括采样、保持、量化、编码的全过程。
基本转换过程
四个过程:采样、保持、量化、编码。
Cubemx相关开发
STM32的ADC资源概述
STM32F103ZE芯片(144脚)中有ADC1、ADC2、ADC3共3个12位逐次逼近型模数转换器,具有18个测量通道,可测量16个外部和2个内部信号源(内部温度和内部参考电压)。这2个内部信号源只能连接到ADC1。各个通道的A/D转换可以单次、连续、扫描或间断模式执行。
按照A/D转换的组织形式来划分,ADC的模拟输入通道分为规则组和注入组两种。ADC可以对一组最多16个通道按照指定的顺序逐个进行转换,这组指定的通道称为规则组。在实际应用中,可能需要中断规则组的转换,临时对某些通道进行转换,好像这些通道注入了原来的规则组,故称注入组,最多由4个通道组成。
A/D转换结果有2种存储方式:左对齐、右对齐(默认)。
ADC 的输入电压范围设定在:0~3.3v,因为 ADC是12位的,那么12位满量程对应的就是 3.3V,12位满量程对应的数字值是:2^12。数值0对应的就是 0V。如果转换后的数值为X,X对应的模拟电压为Y,那么会有这么一个等式成立:2^12 / 3.3 = X / Y=> Y = (3.3 * X ) / 2^12。
Cubemx配置
基础开发时使用默认参数即可
查询方式和中断方式的HAL库函数应用
实例
STM32应用开发,完成功能:
[1]将ADC_ IN1设置为12位ADC,右对齐,启用中断。
[2]分别用查询和中断这2种方式,每隔0.5秒采样一次ADC 的数据。
[3]将每次读取到的ADC采样值转换为对应电压值,发送到上位机。
[4] LED0(PB5)作为采样指示灯,在ADC转换过程中点亮,其余时间熄灭。
cubemx配置
首先对RCC、SYS、时钟树进行配置(参照最开始的文章),然后对ADC进行配置(这里采用默认),打开中断:
初始化LED:
由原理图可以知道,IO口应设置为高电平使其熄灭,低电平亮
配置串口:
生成代码即可。
代码编写
一些定义准备
#define LED_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET)
#define LED_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET)
#include "stdio.h"//因为需使用sprint函数
uint16_t ADC_value = 0,ADC_v = 0;//前者存放ADC采取的数据,后者是电压值
uint8_t str_buff[64];//缓冲区
采用查询方式,并使用串口进行数据发送:
void UR1_Send_Info()
{
sprintf((char *)str_buff,"采样值:%d,电压值:%d.%d%d V\r\n",ADC_value,ADC_v/100,(ADC_v%100)/10,ADC_v%10);
HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000);
}
void ADC_Get_Value()
{
HAL_ADC_Start(&hadc1);
LED_ON();
if(HAL_ADC_PollForConversion(&hadc1,10) == HAL_OK)
{
ADC_value = HAL_ADC_GetValue(&hadc1);
ADC_v = ADC_value * 330 / 4096;
}
UR1_Send_Info();
LED_OFF();
HAL_ADC_Stop(&hadc1);
}
像&hadc1这些实例,可以在相关文件开头看见相关的定义:
然后加到主函数并且延时即可:
接着采用中断方式:
先寻找回调函数:
void UR1_Send_Info()
{
sprintf((char *)str_buff,"²ÉÑùÖµ£º%d£¬µçѹֵ£º%d.%d%d V\r\n",ADC_value,ADC_v/100,(ADC_v%100)/10,ADC_v%10);
HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
ADC_value = HAL_ADC_GetValue(&hadc1);
ADC_v = ADC_value * 330 / 4096;
UR1_Send_Info();
LED_OFF();
}
}
在启动AD的时候开灯:(主函数)