在这里我说一下,不管是什么或者哪家的芯片,外设功能以及作用都是一样的,唯一不同的是每个厂家提供的库函数不一样而已,所以只要有一个单片机你熟悉了,其本上市面上大部分单片机你都不会有问题的。
还有就是不要觉得啰嗦,我写这个的最初目的是给一些刚入门以及自己回顾用的。
在介绍ADC之前我们先说一下ADC大致应用到哪些领域。比如无线通信、软件无线电、数据采集、光通讯、仪器设备等领域用到的非常多,举个非常简单的例子,比如你要获取电池电压的用电情况这时候就需要用到ADC这个东西。当然了ADC又可以分很多种,这里就不在说了,这里可以去网上查查。看看多了解了解。
其实在自然界存在的大都是模拟量,像温湿度、时间、速度、压力、流量等都是模拟量,但是吧,兄弟们,我们在使用这些东西的时候需要把这玩意用计算机转换成数字量,这样才能更有效的进行一些控制。
因此这就需要他们之间有一个桥梁,这个桥梁就是ADC和DAC这两个。本章只介绍ADC,DAC将会在下一章介绍。
典型的数字控制系统流图如下图所示:
根据图中的信息可知道,非电模拟量需要使用特定的传感器将模拟信号转换成电信号,然后使用ADC将电信号转换成数字信号,经嵌入式系统处理后,再通过DAC将数字信号转换成模拟信号去控制执行机构。
我们首先说一下ADC的转换过程,然后说一下原理,当然如果嫌啰嗦可以直接跳过。
ADC是英文Analog-to-Digital Converter缩写,翻译过来就是模数转换器,是指将连续变化的模拟信号转换为离散的数字信号的器件。A/D转换的作用是将时间连续、幅值也连续的模拟信号转换为时间离散、值也离散的数字信号,因此,**A/D转换一般要经过采样、保持、量化及编码4个过程,**如下图所示。在实际电路中,这些过程有的是合并进行的。例如,采样和保持、量化和编码往往都是在转换过程中同时实现的。
1、ADC:模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
2 、在进行模/数转换时,要按一定的时间间隔,对模拟信号进行采样,然后再把采样得到的值转换为数字量。因此,模/数转换的基本过程由**①采样、②保持、③量化和④编码组成。**通常,采样和保持两个过程由采样–保持电路完成,量化和编码又常在转换过程中同时实现。
ADC有很多的类型大致可以分为**逐次比较逼近型、并行比较型、积分型、Σ-Δ调制型、及压频变换型。**这些个类型。具体是什么请自行百度。
当然这些类型収各自的优点和缺点。看下图:
先来看两幅图:
从上图可以知道一下几点:
(1)当vs为高电平时,S闭合,采样阶段,vo=vI;
(2)当vs为低电平时,S断开,保持阶段,此时由于电容无放电回路,所以vO保持在上一次采样结束时输入电压的瞬时值上。
将A/D转换输出的数字信号,再进行D/A转换,得到的模拟信号与原输入信号的接近程度,与采样频率密切相关。
啥事采样?
定义事这样的:
采样是在间隔为T的T、2T、3T、…时刻抽取被测模拟信号幅值,相邻两个采样时刻之间的间隔T也被称为采样周期。
只有当采样频率fs大于或等于模拟信号v最高频率分量fmax的2倍时(fs≥2fmax),所采集的信号样值才能不失真地反映原来模拟信号的变化规律。
例如:若被采样信号的最高频率分量的频率为100Hz,则采样频率应该不低于200Hz。
1、什么是量化?
我们在对对模拟信号进行采样后,会得到一个时间上离散的脉冲信号序列,但每个脉冲的幅度仍然是连续的。然而,CPU所能处理的数字信号不仅在时间上是离散的,而且数值大小的变化也是不连续的,因此,必须把采样后每个脉冲的幅度进行离散化处理,得到被CPU处理的离散数值,这个过程就称为量化。
说白了就是A/D转换过程中,必须将采样-保持电路的输出电压,按某种近似方式规划到与之相应的离散电平上。
2、啥是编码?
把量化的结果二进制表示出来称为编码。而且,一个n位量化的结果值恰好用一个n位二进制数表示。这个n位二进制数就是ADC转换完成后的输出结果。
说白了就是量化过程,只是把模拟信号按量化单位作了取整处理,只有用代码表示量化后的值,才能得到数字量。当然常用的编码是二进制编码。
当然了编码有两种方式:看下图:
1.取整时只舍不入,就是说当电压在0-1v的时候电压都是0,1-2v的时候电压都是1,按照这样以此类推。采用这种方法,输入电压总是比输出电压高的,所以产生的量化误差是不可能为负的。
2.取整时有舍有入(也就是四舍五入):也就是0-0.5V取0,0.5-1.5V取1,以此类推后面的都是这样的。从这就看到这里的量化误差是有正有负的。
其实量化说白了及时把模拟信号进行一个取整处理的一个过程。
指从接到转换控制信号开始,到输出端得到稳定的数字输出信号所需要的时间。通常用完成一次A/D转换操作所需时间来表示转换速度。
例如,某ADC的转换时间T为10ms,则该A/D转换器的转换速度为1/T=100次/s。
分辨率也可以叫做分解度。用来描述刻度划分。常以输出二进制代码的位数来表示分辨率的高低。位数越多,说明量化误差越小,则转换的精度越高。摄像头数字化处理用到的地方多。
量化误差是指量化产生的误差,就是上面说的那两种情况。
精度指产生一个给定的数字量输出,所需模拟电压的理想值与实际值之间总的误差,其中包括量化误差、零点误差及非线性等产生的误差。用来描述物理量的准确程度。
特别注意一下:精度和分辨率是不一样的。
输入模拟电压范围指ADC允许输入的电压范围。超过这个范围,A/D转换器将不能正常工作。例如 :STM32F429输入电压范围是:单极性0~V_ref。
转换时间(conversion time)是ADC完成一次A/D转换所需要的时间,是指从启动ADC开始到获得相应数据所需要的总时间。
经过上面的内容我们已经对ADC的基本有一个大致的了解。
下面就说说STM32中的ADC。
12位分辨率
转换结束、注入转换结束和发生模拟看门狗事件时产生中断
单次和连续转换模式
从通道0到通道n的自动扫描模式
自校准
带内嵌数据一致性的数据对齐
采样间隔可以按通道分别编程
规则转换和注入转换均有外部触发选项
间断模式
双重模式(带2个或以上ADC的器件)
ADC转换时间:时钟为56MHz时,ADC最短转换时间为1μs
ADC供电要求: 2.4V到3.6V
ADC输入范围: VREF- ≤ VIN ≤ VREF+
规则通道转换期间有DMA请求产生。
STM32F429IGT6带3个ADC控制器:其核心为模拟至数字转换器,它由软件或硬件触发,在ADC时钟ADCLK的驱动下对规则通道或注入通道中的模拟信号进行采样、量化和编码。
1、12 位 ADC 是逐次趋近型模数转换器,可配置为10 位、8 位或 6 位分辨率。
2、多达 19 个复用通道,可测量来自 16 个外部源、两个内部源和VBAT通道的信号。
3、A/D 转换可在单次、连续、扫描或不连续
采样模式下进行。
4、ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中。
5、ADC具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或下限。
6、多种ADC转换触发方式:软件方式、定时器、EXTI 中断线。
7、可触发DMA功能(可看DMA章节)。
ADC电源引脚功能如图所示:
从上面看到:ADC在开始精确转换前需要一个稳定时间tSTAB。在开始ADC转换和14个时钟周期后, EOC标志被设置, 16位ADC数据寄存器包含转换的结果。
ADC_CR2寄存器中的ALIGN位选择转换后数据储存的对齐方式。数据可以左对齐或右对齐。注入组通道转换的数据值已经减去了在ADC_JOFRx寄存器中定义的偏移量,因此结果可以是一个负值。 SEXT位是扩展的符号值。对于规则组通道,不需减去偏移值,因此只有12个位有效。
ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。
通过设置ADC_CR2寄存器的CAL位启动校准。一旦校准结束, CAL位被硬件复位,可以开始正常转换。建议在上电时执行一次ADC校准。校准阶段结束后,校准码储存在ADC_DR中。
STM32F4系列微控制器的ADC是逐次比较逼近型,因此必须使用驱动时钟。所有ADC共用时钟ADCCLK,它来自经可编程预分频器分频的APB2时钟,该预分频器允许ADC在fPCLK2/2、fPCLK2/4、fPCLK2/6或fPCLK2/8等频率下工作。ADCCLK最大频率为36MHz。
1-规则通道组:相当正常运行的程序。最多16个通道。 规则通道和它的转换顺序在ADC_SQRx寄存器中选择,规则 组转换的总数 写入ADC_SQR1寄存器的L[3:0]中
规则通道组共用一个转换数据寄存器!
2-注入通道组:相当于“中断”。最多4个通道。 注入组和它的转换顺序在ADC_JSQR寄存器中选择。注入组里转换的总数应写入ADC_JSQR寄存器的JL[1:0]中每个注入通道都有一个独立的转换数据寄存器。
STM32F4的ADC的各通道可以①单次,②连续,③扫描或者④间断模式执行。
总的来说有以下两种方式:
1)、软件触发:ADC 使能 可以由 ADC 控制寄存器 2: ADC_CR2 的 ADON 这个位来控制,写 1 的时候开始转换,写 0 的时候 停止转换,这个是最简单也是最好理解的开启 ADC 转换的控制方式。
另:(1)位SWSTART:启动规则组。(2)位JSWSTART:启动注入组
2)、外部事件触发转换:触发源有很多,具体选择哪一种触发源,由 ADC 控制寄存器2:ADC_CR2 的 EXTSEL[2:0]和JEXTSEL[2:0]位来控制。
(1)EXTSEL[2:0]用于选择规则通道的触发源;
(2)JEXTSEL[2:0]用于选择注入通道的触发源。
当模拟看门狗状态位和溢出状态位分别置 1 时,规则组和注入组在转换结束时可能会产生中 断。可以使用单独的中断使能位以实现灵活性。
使用看门狗功能,可以限制ADC转换模拟电压的范围(低于阈值下限或高于阈值上限,定义在ADC_HTR和ADC_LTR这两个寄存器中),当转换的结果超过这一范围时,会将ADC_SR中的模拟看门狗状态位置1,如果使能了相应中断,会触发中断服务程序,以及时进行对应的处理。
由于规则组通道只有一个ADC_DR,因此,对于多个规则组通道的转换,使用 DMA非常有帮助。
比如:
ADC1规则组转换4个输入通道信号时,需要用到DMA2的数据流0的通道0,在扫描模式下,在每个输入通道被转化结束后,都会触发DMA控制器将转换结果从规则组ADC_DR中的数据传输到定义的存储器中。
//ADC1为例子
1-开启PA口时钟和ADC1时钟,设置PA1为模拟输入。
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
GPIO_Init();
2-初始化模拟信号输入的GPIO引脚为模拟方式:
GPIO_Init();
3-复位ADC1。
ADC_DeInit(ADC1);
4-初始化ADC_CCR寄存器。ADC通用控制寄存器。
ADC_CommonInit();
5-初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
6-配置规则通道参数:
ADC_RegularChannelConfig();
7-如果要用中断,使能ADC中断,配置ADC的NVIC 。
使能ADC1的转换结束中断:
ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
配置ADC的NVIC:
NVIC_Init();
8-使能ADC
ADC_Cmd(ADC1, ENABLE);
9-开启软件转换:ADC_SoftwareStartConvCmd(ADC1);
10-等待转换完成,读取ADC值
ADC_GetConversionValue(ADC1);
11-中断服务程序
void ADC_IRQHandler(void);
void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
//这些参数用来配置ADC_CCR寄存器的相关参数
typedef struct
{
uint32_t ADC_Mode; //多重ADC模式选择
uint32_t ADC_Prescaler; //ADC预分频
uint32_t ADC_DMAAccessMode; //DMA访问模式
uint32_t ADC_TwoSamplingDelay; //2个采样阶段之间的延迟
}ADC_CommonInitTypeDef;
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
ADCx,可以是ADC1、ADC2等
typedef struct
{
uint32_t ADC_Resolution; //ADC分辨率
FunctionalState ADC_ScanConvMode; //是否使用扫描模式。ADC_CR1位8:SCAN位
FunctionalState ADC_ContinuousConvMode; //单次转换OR连续转换:ADC_CR2的位1:CONT
uint32_t ADC_ExternalTrigConvEdge; //外部触发使能方式:ADC_CR2的位29:28,EXTEN
uint32_t ADC_ExternalTrigConv; //触发方式:ADC_CR2的位[19:17] :EXTSEL[2:0]
uint32_t ADC_DataAlign; //对齐方式:左对齐还是右对齐:ADC_CR2的位11:ALIGN
uint8_t ADC_NbrOfChannel; //规则通道序列长度:ADC_SQR1的位[23:20]: L[3:0]
}ADC_InitTypeDef;
例如:
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
///
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC1的软件转换启动
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx,uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
///
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_480Cycles);//把规则通道中的通道5,设置为第一个转换
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
ADC_GetConversionValue(ADC1);//获取ADC1转换结果
请参考野火,正点原子的以及ST官方或者其他优秀的代码例程。