ADC数模转换

注意:本篇笔记以ZET6为例

其中,12位的分辨率指ADC可将模拟量转化为12位的二进制数。

ADC数模转换-1

每个ADC都有18个通道,其中外部通道有16个。

ADC数模转换-2

内部Vrefint是指内部的参考电压值。

连接内部的Vss是指连接到内部的公共接地端。

模拟量转化为数字量,需要进行采样、转化、编码三个步骤。

因此ADC的转化时间包含了采样时间以及后面的量化/编码时间,即TCONV = 采样时间 + 12.5个采样周期。

ADC数模转换-3

如果ADCCLK的时钟频率为14M,则当个周期时间为1/14M,即14分之一微秒,所以整个TCONV合起来是1us,采样周期是可以在代码当中进行设置的。

一、ADC功能框图

ADC数模转换-4

1、电压输入范围

ADC数模转换-5

ADC数模转换-6

VREF+是模拟参考正级:需要满足表中要求的范围(2.4v<=VREF+<=VDDA)

VREF-是模拟参考负极:一般将模拟参考负极接入到单片机的接地端

因此ADC输入电压的范围实际上就是在0-3.3v之间

2、输入通道

ADC数模转换-7

除了外部通道外,还有一些内部通道(内部温度传感器)

这些ADC通道又被区分为注入通道和规则通道,不同的通道转化的结果会存放在不同的地方。

而注入通道的模拟量转化完成的结果存放至“注入通道数据寄存器”(4个)

规则通道的模拟量转换完成的结果存放至“规则通道数据寄存器”(1个)

在ADCCLK中可以设置ADC的时钟,设置ADC的分频系数。

ADC数模转换-8

ADC数模转换-9

注入通道的转换可以打断规则通道的转换,在注入通道被转换完后,规则通道才得以继续转换。

ADC数模转换-10

在常规的情况下如果没有使用注入通道,那就是使用常规通道轮流转换,从第一个通道到最后一个通道。

如果有使用注入通道,注入通道可以随时打断常规通道的转换,注入通道最多就只有四个通道了,注入

通道轮流转换完后再会得到常规通道进行转换。

如果ADC转化完成后,还可以产生相对应的中断。

ADC的触发方式有很多种,可以软件启动ADC转换,也可以用其他的定时器来触发。

ADC数模转换-11

二、ADC转换编程流程

ADC数模转换-12

方式1 ADC数模转换-13

ADC数模转换-14

第一步,打开ADC的时钟、对应GPIO的时钟

ADC数模转换-15

根据数据手册当中的时钟框图,可以看到ADC的时钟来源于APB2上,所以我们需要打开在APB2的时钟。当然,还有IO口的时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

根据参考手册(8.1.11)可以查询到GPIO使用ADC时,需要使用模拟输入模式:

ADC数模转换-16

GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

第二步,配置ADC的时钟分频系数,ADC的时钟频率最高不能超过14M,超过14M会导致精度丢失。

RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M分频,6分频后ADC时钟为12M

第三步,复位ADC

ADC_DeInit(ADC1);

第四步,初始化ADC

ADC_Mode

ADC数模转换-17

正常情况下,只使用一个ADC单元使用的模式是独立模式。

后面那些同步规则和同步注入的模式适用于同时使用多个ADC单元同时使用的情景。

ADC扫描转换模式与ADC连续转换模式,由于只用了一个通道,所以不需要打开这两个模式,赋值为DISABLE。

ADC数模转换-18

ADC外部触发转换

ADC数模转换-19

上文提到ADC具有多种外部触发条件,这里我们选择直接软件启动。

ADC数模转换-20

从程序可以看出ADC的外部触发有多种条件,其中包括多个定时器的多个通道。

但是这里不需要使用外部触发,我们选择直接软件触发,所以这里设置为None。

ADC数模转换-21

ADC数据对齐方式

中文参考手册可查

ADC数模转换-22

ADC分辨率12位即将输入的电压值转换成12位的二进制数

数据右对齐时,规则组内的数据全部往右边对齐,左边的数据直接补零

数据左对齐则相反,数据往左对其,低位补零。此时该值如果要还原成原来的大小,需要除以2的4次方

因为数据左对齐的数据需要还原比较麻烦,所以一般选择数据右对齐

ADC通道数目

由于我们只使用了一个通道,所以我们在这里赋值为1

ADC数模转换-23

完整的ADC定义:

ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; //只用了一个通道,因此设置为独立模式
ADC_InitStruct.ADC_ScanConvMode = DISABLE; //多通道还是单通道使能
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;  ;//连续模式还是单次模式
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //触发方式选择了软件触发
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;

ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);

ADC数模转换-24

//使能ADC,注意ADC使能完成之后再进行校准
ADC_Cmd(ADC1, ENABLE);

//ADC复位校准
ADC_ResetCalibration(ADC1);

//获取ADC复位校准标志位等待校准
while(ADC_GetResetCalibrationStatus(ADC1)) ;

//ADC开始校准
ADC_StartCalibration(ADC1);

//ADC获取开始校准标志位
while(ADC_GetCalibrationStatus(ADC1));

//校准完成后才开始AD转换,软件启动转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);

获取ADC转换后的值,编写获取转换值的函数
u16 Get_ADCRes() {
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件开启转换
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
    return ADC_GetConversionValue(ADC1);
}