STM32—ADC(模数转换)
一.模拟信号和数字信号
1.模拟信号
在时间和数值上均具有连续性,即对应于任意时间值 t均有确定的函数值 u或 i,并且 u或 i的幅值是连续取值的
2.数字信号
在时间和数值上均具有离散性,u或 i的变化在时间上不连续,总是发生在离散的瞬间,且它们的数值是一个最小量值得整数倍
3.模数转换过程
采样:(Sample)是在发送端将模拟信号转换为离散信号的过程。
量化:(Quantifcation)抽样信号在各抽样时刻的幅度反映了模拟信号的幅度变化,因此任然是连续的,必须在编码前,将幅度抽样只用预先规定的有限个取值来表示。
编码:(Coding)将量化器输出量化信号在各个离散时刻的取值用指定位数的二进制码表示,从而得到数字信号。
二.ADC
1.用途
采集传感器数据;测量输入电压;检查电池电量剩余;检测温湿度
2.ADC0809模块
1.框图
2.引脚
IN0-IN7:8路模拟量输入端
D0-D7:8位数字量输出端
ADDA、ADDB、ADDC:3位地址输入线,用于选通8路模拟输入中的一路
ALE:地址锁存允许信号,输入高电平有效
START: A/D转换启动脉冲输入端,输入一个正脉冲(至少100ns宽)使其启动(脉冲上升沿使0809复位,下降沿启动A/D转换)
EOC:A/D转换结束信号,当A/D转换结束时,此端输出一个高电平(转换期间一直为低电平)
OE:数据输出允许信号,输入高电平有效。当A/D转换结束时,此端输入一个高电平,才能打开输出三态门,输出数字量
CLK:时钟脉冲输入端。要求时钟频率不高于640KHZ
VREF(+)、VREF(–):基准电压
Vcc:电源,单一+5V
GND:地
3.工作原理
1.首先输入3位地址(ADDA、ADDB、ADDC),并使ALE=1,将地址存入地址锁存器中。
2.此地址经译码选通8路模拟输入之一到比较器。START上升沿将逐次逼近寄存器复位。
3.下降沿启动 A/D转换,之后EOC输出信号变低,指示转换正在进行。
4.直到A/D转换完成,EOC变为高电平,指示A/D转换结束,结果数据已存入锁存器,这个信号可用作中断申请。
5.当OE输入高电平时,输出三态门打开,转换结果的数字量输出到数据总线上。
比较器:用于将两个电压或电流进行比较,并输出比较结果。比较器的一端为输入电压,另一端为DAC器件所产生的电压输入
测量电压范围:即DAC器件产生的电压范围 VREF +-对应的电压范围,例如:VREF + 为3.3V VREF – 为0V,则测量范围为0-3.3V
8位逐次逼近型:
8位:转换后的数据范围为8位,即输出数据范围为0-255
逐次逼近:DAC器件产生电压和输入电压比较,相等/最接近时即为待测电压数值STMF
三.STM32F407的ADC
1.主要特性
12位ADC是逐次趋近型模数转换器。有19个复用通道,可测量来自16个外部源,2个内部源和VBAT通道的信号。这些通道的A/D转换可在单次,连续,扫描或不连续采样模式下进行。ADC的结果存储在一个左对齐或右对齐的16为数据寄存器中。ADC具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或下限。
2.框图
分辨率
分辨率:分辨率表示精度,位数越高精度越高,同时也表示最小可检测电压变化。例如12位分辨率,即ADC输出数据范围为0-4095。
ADC输入
ADCx_IN0-ADCx_IN15+ 温度传感器 + VREFINT + VABT
测量范围
参考电压:即测量范围,VREF+ VRE-
转换通道
通道选择
:选择由哪个通道对外部输入进行转换
规则通道:可以按照设置的转换顺序进行转换的通道。一个规则转换组最多由 16 个转换构成。
注入通道:可以“插队”,也就是说,注入通道的转换可以打断规则通道的转换,在注入通道被转换完成之后,规则通道才可以继续转换。一个注入转换组最多由 4 个转换构成。
转换顺序
转换顺序选择:转换顺序即为通道中对应输入的顺序,配置方式如下
转换方式
转换方式
:
STM32
对于通道内转换序列的转换方式包括
连续
\
单次
,
扫描
\
非扫描
单次模式:转换一次后,就停止转换
连续模式:转换一次后,接着进行下一次转换,不断连续
扫描模式:对于对通道的转换按设置顺序依次转换
非扫描模式:对于对通道的转换按设置顺序依次转换,但是每个序列转换需要
转换结果寄存器
保存方式:
左对齐或者右对齐
。
3.固件库ADC API 接口介绍
3.1 时钟使能
adc时钟使能:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCx, ENABLE);
gpio时钟使能:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
3.2 GPIO初始化
由于GPIO
为模拟功能,因此配置模式时需要选择为模拟模式
Configure these ADC pins in analog mode using GPIO_Init();
3.3 ADC配置
#include "adc.h"
/*
[..]
(#) Enable the ADC interface clock using
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCx, ENABLE);
(#) ADC pins configuration
(++) Enable the clock for the ADC GPIOs using the following function:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
(++) Configure these ADC pins in analog mode using GPIO_Init();
(#) Configure the ADC Prescaler, conversion resolution and data
alignment using the ADC_Init() function.
(#) Activate the ADC peripheral using ADC_Cmd() function.
(+) To configure the ADC regular channels group features, use
ADC_Init() and ADC_RegularChannelConfig() functions.
(+) To activate the continuous mode, use the ADC_continuousModeCmd()
function.
(+) To configurate and activate the Discontinuous mode, use the
ADC_DiscModeChannelCountConfig() and ADC_DiscModeCmd() functions.
(+) To read the ADC converted values, use the ADC_GetConversionValue()
function.
*/
void adc_Init()
{
//PF7/TIM11_CH1/FSMC_NREG/ADC3_IN5
//1.使能ADC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
//2.使能GPIO时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
//配置光敏电阻模块的GPIO
GPIO_InitTypeDef gpio;
gpio.GPIO_Mode = GPIO_Mode_AN;
gpio.GPIO_Pin = GPIO_Pin_7;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;// 没有上下拉 不对模拟输入波形有任何干扰
GPIO_Init(GPIOF,&gpio);
//配置ADC
ADC_CommonInitTypeDef adc_Com;
adc_Com.ADC_Mode = ADC_Mode_Independent;//独立模式
adc_Com.ADC_Prescaler = ADC_Prescaler_Div4;// 设置采样时钟 --- FAPB2/4 = 21MHZ
adc_Com.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;// 禁止DMA模式
adc_Com.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;// 设置采样间隔
ADC_CommonInit(&adc_Com);
ADC_InitTypeDef adc;
adc.ADC_Resolution = ADC_Resolution_12b;// 设置分辨率 为 12bit
adc.ADC_ScanConvMode = DISABLE;// 设置扫描/(非扫描模式)
adc.ADC_ContinuousConvMode = DISABLE;// 设置连续/(单次模式)
adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;// 设置外部触发边沿 选择不由外部触发------>软件触发
/*
选择ADC的外部触发源,上一个参数没有选择外部触发,所以本参数可以不设置
adc.ADC_ExternalTrigConv
*/
adc.ADC_DataAlign = ADC_DataAlign_Left;// 设置数据对齐方式 为 左对齐
adc.ADC_NbrOfConversion = 1;// 指定规则通道的转换数量
ADC_Init(ADC3,&adc);
// 4. 使能ADC外设
ADC_Cmd(ADC3, ENABLE);
// 5. 将外部输入到rank指定的规则通道序列中,并设置采样时间
ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);
}
// 获取ADC转换数据 --- ADC转换模式 单次非扫描,每转换一次就需要触发一次
uint16_t ADC_GetData()
{
// 软件触发
ADC_SoftwareStartConv(ADC3);
// 转换结束 EOC标志会被设置 --- 等待EOC标志被设置
while ( ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET );
ADC_ClearFlag(ADC3, ADC_FLAG_EOC);
// 获取转换的结果
return ADC_GetConversionValue(ADC3);
}
#ifndef __ADC_H_
#define __ADC_H_
#include "stm32f4xx.h"
void adc_Init();
uint16_t ADC_GetData();
#endif
四,ADC-光敏传感器
1.原理图
2.代码实现
#include "adc.h"
/*
[..]
(#) Enable the ADC interface clock using
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCx, ENABLE);
(#) ADC pins configuration
(++) Enable the clock for the ADC GPIOs using the following function:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE);
(++) Configure these ADC pins in analog mode using GPIO_Init();
(#) Configure the ADC Prescaler, conversion resolution and data
alignment using the ADC_Init() function.
(#) Activate the ADC peripheral using ADC_Cmd() function.
(+) To configure the ADC regular channels group features, use
ADC_Init() and ADC_RegularChannelConfig() functions.
(+) To activate the continuous mode, use the ADC_continuousModeCmd()
function.
(+) To configurate and activate the Discontinuous mode, use the
ADC_DiscModeChannelCountConfig() and ADC_DiscModeCmd() functions.
(+) To read the ADC converted values, use the ADC_GetConversionValue()
function.
*/
void adc_Init()
{
//PF7/TIM11_CH1/FSMC_NREG/ADC3_IN5
//1.使能ADC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
//2.使能GPIO时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
//配置光敏电阻模块的GPIO
GPIO_InitTypeDef gpio;
gpio.GPIO_Mode = GPIO_Mode_AN;
gpio.GPIO_Pin = GPIO_Pin_7;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;// 没有上下拉 不对模拟输入波形有任何干扰
GPIO_Init(GPIOF,&gpio);
//配置ADC
ADC_CommonInitTypeDef adc_Com;
adc_Com.ADC_Mode = ADC_Mode_Independent;//独立模式
adc_Com.ADC_Prescaler = ADC_Prescaler_Div4;// 设置采样时钟 --- FAPB2/4 = 21MHZ
adc_Com.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;// 禁止DMA模式
adc_Com.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;// 设置采样间隔
ADC_CommonInit(&adc_Com);
ADC_InitTypeDef adc;
adc.ADC_Resolution = ADC_Resolution_12b;// 设置分辨率 为 12bit
adc.ADC_ScanConvMode = DISABLE;// 设置扫描/(非扫描模式)
adc.ADC_ContinuousConvMode = DISABLE;// 设置连续/(单次模式)
adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;// 设置外部触发边沿 选择不由外部触发------>软件触发
/*
选择ADC的外部触发源,上一个参数没有选择外部触发,所以本参数可以不设置
adc.ADC_ExternalTrigConv
*/
adc.ADC_DataAlign = ADC_DataAlign_Left;// 设置数据对齐方式 为 左对齐
adc.ADC_NbrOfConversion = 1;// 指定规则通道的转换数量
ADC_Init(ADC3,&adc);
// 4. 使能ADC外设
ADC_Cmd(ADC3, ENABLE);
// 5. 将外部输入到rank指定的规则通道序列中,并设置采样时间
ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 1, ADC_SampleTime_3Cycles);
}
// 获取ADC转换数据 --- ADC转换模式 单次非扫描,每转换一次就需要触发一次
uint16_t ADC_GetData()
{
// 软件触发
ADC_SoftwareStartConv(ADC3);
// 转换结束 EOC标志会被设置 --- 等待EOC标志被设置
while ( ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET );
ADC_ClearFlag(ADC3, ADC_FLAG_EOC);
// 获取转换的结果
return ADC_GetConversionValue(ADC3);
}
/* acd.h */
#ifndef __ADC_H_
#define __ADC_H_
#include "stm32f4xx.h"
void adc_Init();
uint16_t ADC_GetData();
#endif
/* main.c */
#include "main.h"
#include "systick.h"
#include "BSP_LED.h"
#include "DHT11.h"
#include "stdio.h"
#include "uart.h"
#include "adc.h"
int main()
{
//uint8_t temp = -1, humi = -1;
//LED_Init(LED0GPIO, LED0Pin);
Usart1Init();
SysTick_Config(168000);
adc_Init();
while(1)
{
uint16_t temp = ADC_GetData()>>4;
// windows中换行符和\r\n
printf("light sensor:%d\r\n", temp);
delayMs(1000);
}
return 0;
}
作者:offer速速来