一、ADC介绍
1、这里使用的12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部 信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右 对齐方式存储在16位数据寄存器中。
2、ADC主要特征:
1)12位分辨率
2)转换结束、注入转换和发生模拟看门狗事件时产生中断
3)单次和连续转换模式
4)从通道0到通道n的自动扫描模式
5)自校准
6)带内嵌数据一致性的数据对齐
7)采样间隔可以按通道分别编程
8)规则转换和注入转换均有外部触发选项
9)间断模式
10)双重模式(带2个或以上ADC的器件)
11)ADC转换时间:
─ STM32F103xx增强型产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)
─ STM32F101xx基本型产品:时钟为28MHz时为1μs(时钟为36MHz为1.55μs)
─ STM32F102xxUSB型产品:时钟为48MHz时为1.2μs
─ STM32F105xx和STM32F107xx产品:时钟为56MHz时为1μs(时钟为72MHz为1.17μs)
12)ADC供电要求:2.4V到3.6V
13)ADC输入范围:VREF- ≤ VIN ≤ VREF+
14)规则通道转换期间有DMA请求产生。
注意:如果有VREF-引脚(取决于封装),必须和VSSA相连
3、ADC开关控制
通过设置ADC_CR2寄存器的ADON位可给ADC上电。当第一次设置ADON位时,它将ADC从断 电状态下唤醒。 ADC上电延迟一段时间后(tSTAB),再次设置ADON位时开始进行转换。 通过清除ADON位可以停止转换,并将ADC置于断电模式。在这个模式中,ADC几乎不耗电(仅 几个μA)。
4、ADC时钟
由 时钟控制器提供的ADCCLK时钟和PCLK2(APB2时钟)同步。RCC控制器为ADC时钟提供一个 专用的可编程预分频器,详见小容量、中容量和大容量产品的复位和时钟控制(RCC)章节。
5、ADC通道选择
有16个多路通道。可以把转换组织成两组:规则组和注入组。在任意多个通道上以任意顺序进 行的一系列转换构成成组转换。例如,可以如下顺序完成转换:通道3、通道8、通道2、通道 2、通道0、通道2、通道2、通道15。
规则组由多达16个转换组成。规则通道和它们的转换顺序在ADC_SQRx寄存器中选择。规 则组中转换的总数应写入ADC_SQR1寄存器的L[3:0]位中。
注入组由多达4个转换组成。注入通道和它们的转换顺序在ADC_JSQR寄存器中选择。注入 组里的转换总数目应写入ADC_JSQR寄存器的L[1:0]位中。
如果ADC_SQRx或ADC_JSQR寄存器在转换期间被更改,当前的转换被清除,一个新的启动脉 冲将发送到ADC以转换新选择的组。
6、单次转换模式
单次转换模式下,ADC只执行一次转换。该模式既可通过设置ADC_CR2寄存器的ADON位(只 适用于规则通道)启动也可通过外部触发启动(适用于规则通道或注入通道),这时CONT位为0。 一旦选择通道的转换完成:
● 如果一个规则通道被转换: ─ 转换数据被储存在16位ADC_DR寄存器中 ─ EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。
● 如果一个注入通道被转换: ─ 转换数据被储存在16位的ADC_DRJ1寄存器中 ─ JEOC(注入转换结束)标志被设置 ─ 如果设置了JEOCIE位,则产生中断模拟/数字转换(ADC)
然后ADC停止
7、连续转换模式
在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启 动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。 每个转换后:
● 如果一个规则通道被转换: ─ 转换数据被储存在16位的ADC_DR寄存器中 ─ EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。
● 如果一个注入通道被转换: ─ 转换数据被储存在16位的ADC_DRJ1寄存器中 ─ JEOC(注入转换结束)标志被设置 ─ 如果设置了JEOCIE位,则产生中断。
8、时序图
ADC在开始精确转换前需要一个稳定时间tSTAB。在开始ADC转换和14个时钟周期 后,EOC标志被设置,16位ADC数据寄存器包含转换的结果。
9、ADC中断
规则和注入组转换结束时能产生中断,当模拟看门狗状态位被设置时也能产生中断。它们都有 独立的中断使能位。
注: ADC1和ADC2的中断映射在同一个中断向量上,而ADC3的中断有自己的中断向量。 ADC_SR寄存器中有2个其他标志,但是它们没有相关联的中断:
● JSTRT(注入组通道转换的启动)
● STRT(规则组通道转换的启动)
中断事件 事件标志 使能控制位
规则组转换结束 EOC EOCIE
注入组转换结束 JEOC JEOCIE
设置了模拟看门狗状态位 AWD AWDIE
二、应用光照强度获取和烟雾浓度获取
1、光敏电阻原理图
使用PA5管脚
2、ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。-----这里使用6分频(系统时钟72MHZ)
它最大只能输入3.6V电压,而光敏电阻的供电为5V,所以设计了R19分压电阻,
设光敏电阻的阻值为xΩ,PA5的电压为y,可得以下公式:
y/1500=5/(x+2500)
STM32的ADC精度为12位,则最大值为4096。采集到的AD值与电压成线性对应关系,系统中最高的电压值为3.3V的电源电压,它与4096对应。假设PA5感受到的电压y对应的AD值为z,则:
y/z=3.3/4096
联立两式,消去y,得到关于x的表达式:
x=10240000/(1.1×z)-2500
使用ADC得到z以后,就可以根据上式算出光敏电阻的值了
3、光敏电阻器是利用半导体的光电效应制成的一种电阻值随入射光的强弱而改变的电阻器。主要用于光的测量、光的控制、和光电转换。光敏电阻器都制成薄片结构,以便能够吸收更多的光能。该类电阻器的特点是入射光越强,电阻值就越小,入射光越弱,电阻值就越大
adc.c
#include "adc.h"
#include "stdio.h"
uint16_t Illu = 0;
uint16_t smoke = 0;
uint16_t ADC_Buff[20] = {0};
uint8_t lvgl_Illu[100] = {0};
uint8_t lvgl_smoke[100] = {0};
//PA5 光照
void Adc_Config(void)
{
//IO开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);
//配置IO
GPIO_InitTypeDef GPIO_Adc = {0};
GPIO_Adc.GPIO_Pin = GPIO_Pin_5;
GPIO_Adc.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Adc.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA,&GPIO_Adc);//配置函数:初始化外设 GPIOx 寄存器
GPIO_Adc.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOC,&GPIO_Adc);//配置函数:初始化外设 GPIOx 寄存器
//ADC1开时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置 ADC 时钟 RCC_PCLK2_Div6:六分频
//ADC1配置
ADC_InitTypeDef ADC_InitStructure = {0};
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;// ADC1,ADC2 独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式 规则组的每个通道都采集一遍
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;// 软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;// 右对齐
ADC_InitStructure.ADC_NbrOfChannel = 2;//(规则组通道数据个数);规定了顺序进行规则转换的 ADC 通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据 ADC_InitStruct 中指定的参数初始化外设 ADCx 的寄存器
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
ADC_RegularChannelConfig(ADC1,ADC_Channel_5,1,ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_239Cycles5);//ADC_Channel_11->被设置的 ADC 通道
//开启ADC
ADC_Cmd(ADC1,ENABLE);
//开启ADC的DMA通道
ADC_DMACmd(ADC1,ENABLE);
//ADC校准:
//1.重置校准寄存器
ADC_ResetCalibration(ADC1);//重置指定的 ADC 的校准寄存器 CR2
while(ADC_GetResetCalibrationStatus(ADC1));//获取 ADC 重置校准寄存器的状态
//2.开始校准
ADC_StartCalibration(ADC1);//开启指定的ADC校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准结束
//启动ADC
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能或者失能指定的 ADC 的软件转换启动功能
}
void Get_AdcVal(void)
{
Illu = 0;//光照值存放
smoke = 0;//烟雾值存放
for(uint8_t i=0;i<20;i+=2)
{
Illu += ADC_Buff[i];
smoke += ADC_Buff[i+1];
}
Illu =410 - (Illu /100);
smoke /= 10;
}
adc.h
#ifndef _ADC_H_
#define _ADC_H_
#include "stm32f10x.h"
extern uint16_t Illu;
extern uint16_t smoke;
extern uint8_t lvgl_Illu[100];
extern uint8_t lvgl_smoke[100];
void Adc_Config(void);
void Get_AdcVal(void);
#endif