??在STM32微控制器系列中,ADC(Analog-to-Digital Converter)是一个重要的外设模块,它允许微控制器将模拟信号转换成数字信号以进行处理。模拟信号–>数字信号。
?? MCU只能处理数字量(10011001),如果需要MCU区分模拟输入信号时,MCU直接做不了,需要将模拟信号通过模数转换器,转成数字量供MCU处理。模数转换器一般用在各类传感器〈光敏电阻)上,还有部分用在音视频处理上。
?
??转换开始前先将所有寄存器清零。开始转换以后,时钟脉冲首先将寄存器最高位置成1,使输出数字为100···0。这个数码被D/A转换器转换成相应的模拟电压Uo,送到比较器中与Ui进行比较。
??若Ui<Uo,说明数字过大了,故将最高位的1清除为0。将下一位置1,继续进行比较。(减/换砝码)
??若Ui>Uo,说明数字还不够大,应将这一位保留。然后,再按同样的方式将下一次高位置成1 ,再继续进行比较。(加砝码)
??并且经过比较以后确定这个1是否应该保留。这样逐位比较下去,一直到最低位为止。比较完毕后,寄存器中的状态就是所要求的数字量输出。
?
?? 分辨率:它表明A/D对模拟信号的分辨能力,由它确定能被A/D辨别的最小模拟量变化。通常为8,10,12,16位等。如电压为0~3.3v,分辨率为4096,则可识别最小A/D模拟量变化为 3.3/ 4096 v。
?? 转换时间:转换时间是A/D完成一次转换所需要的时间。一般转换速度。越快越好。
?
??分辨率12位(最高)ADC是逐次趋近型模数转换器。它具有多达19个复用通道,可测量来自16众外部源、两个内部源和VBAT通道的信号。这些通道的A/D转换可在单次、连续、扫描或不连续采样模式下进行。ADC的结果存储在一个左对齐或右对齐的16位数据寄存器中。
??ADC具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或下限。
? ?●12位分辨率
? ?● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断
? ?● 单次和连续转换模式
?? ● 从通道0到通道n的自动扫描模式
? ?● 自校准
? ?● 带内嵌数据一致性的数据对齐
? ?● 采样间隔可以按通道分别编程
? ?● 规则转换和注入转换均有外部触发选项
? ?● 间断模式
?? ● 双重模式(带2个或以上ADC的器件)
??可通过将 ADC_CR2寄存器中的 ADON位置1来为ADC供电。首次将ADON位置1时,会将ADC 从掉电(低功耗)模式中唤醒。SWSTART或JSWSTART位置1时,启动AD 转换。
??可通过将 ADON位清零来停止转换,并使ADC进入掉电(低功耗)模式。在此模式下ADC 几乎不耗电(只有几A)。
ADC具有两个时钟方案:
??用于数字接口的时钟:(用于寄存器读/写访问)此时钟等效于APB2时钟。可以通过 RCC APB2外设时钟使能寄存器(RCC_APB2ENR)分别为每个ADC使能/禁止数字接口时钟。
??用于模拟电路的时钟:ADCCLK,所有ADC共用此时钟来自于经可编程预分频器分频的APB2时钟,该预分频器允许ADC在fpclk2/2、/4、/6或/8下工作。有关ADCCLK的最大值,请参见数据手册。
??有16条复用通道。可以将转换分为两组:规则转换(规则组)和注入转换(注入组)。每个组包含一个转换序列,该序列可按任意顺序在任意通道上完成。例如,可按以下顺序对序列进行转换: ADC_IN3、ADC_IN8、ADC_IN2、ADC_IN2、ADC_INO、ADC_IN2、ADC_IN2、ADC_IN15。
??一个规则转换组最多由16个转换构成。必须在ADC_SQRx寄存器中选择转换序列的规则通道及其顺序。规则转换组中的转换总数必须写入ADC_SQR1寄存器中的 L[3:0]位。
??一个注入转换组最多由4个转换构成。必须在 ADC_JSQR寄存器中选择转换序列的注入通道及其顺序。注入转换组中的转换总数必须写入ADC_JSQR寄存器中的L[1:0]位。
??如果在转换期间修改 ADC_SQRx或 ADC_JSQR寄存器,将复位当前转换并向ADC发送一个新的启动脉冲,以转换新选择的组。
在单次转换模式下,ADC执行一次转换。CONT位为0时,可通过以下方式启动此模式:
适用规则通道:将 ADC_CR2寄存器中的 SWSTART位置1。
适用注入通道:将JSWSTART位置1。
适用规则通道或注入通道:外部触发,完成所选通道的转换之后。
如果转换了规则通道:
?? 转换数据存储在16位 ADC_DR寄存器中—EOC(转换结束)标志置1。
?? EOCIE位置1时将产生中断。
如果转换了注入通道:
??转换数据存储在16位 ADC_JDR1寄存器中一JEOC(注入转换结束)标志置1。
??JEOCIE位置1时将产生中断。
然后,ADC停止。
?
??在连续转换模式下, ADC 结束一个转换后立即启动一个新的转换。 CONT 位为 1 时,可通过外部触发或将 ADC_CR2 寄存器中的 SWSTRT 位置 1 来启动此模式。
每次转换之后:
??上次转换的数据存储在16 位 ADC_DR 寄存器中。
??EOC(转换结束)标志置 1。
??EOCIE 位置1时将产生中断。
??注意: 无法连续转换注入通道。连续模式下唯一的例外情况是,注入通道配置为在规则通道之后自动转换(使用 JAUTO 位),请参见自动注入一节。
?
??通过将 ADC_CR1寄存器中的 SCAN位置1来选择扫描模式。将此位置1后,ADC会扫描在ADC_SQRx寄存器(对于规则通道)或ADC_JSQR寄存器(对于注入通道)中选择的所有通道。为组中的每个通道都执行一次转换。每次转换结束后,会自动转换该组中的下一个通道。如果将CONT位置1,规则通道转换不会在组中最后一个所选通道处停止,而是再次从第一个所选通道继续转换。
??如果将 DMA位置1,则在每次规则通道转换之后,均使用直接存储器访问(DMA)控制器将转换自规则通道组的数据(存储在ADC_DR寄存器中)传输到SRAM。
在以下情况下,ADC_SR寄存器中的EOC位置1:
??如果EOCS位清零,在每个规则组序列转换结束时
??如果 EOCS位置1,在每个规则通道转换结束时
??从注入通道转换的数据始终存储在 ADC_IDRx寄存器中。
●触发注入(类似于中断,优先级:注入组 >规则组)
??要使用触发注入,必须将 ADC_CR1寄存器中的 JAUTO位清零。
??1.通过外部触发或将ADC_CR2寄存器中的 SWSTART位置1来启动规则通道组转换。
??2.如果在规则通道组转换期间出现外部注入触发或者JSWSTART位置1,则当前的转换会复位,并且注入通道序列会切换为单次扫描模式。
??3.然后,规则通道组的规则转换会从上次中断的规则转换处恢复。
??如果在注入转换期间出现规则事件,注入转换不会中断,但在注入序列结束时会执行规则序列。图37 显示了相应的时序图。
??注意:使用触发注入时,必须确保触发事件之间的间隔长于注入序列。例如,如果序列长度为30个ADC时钟周期(即,采样时间为3个时钟周期的两次转换),则触发事件的最小间隔不能小于31个ADC时钟周期。
●自动注入(相当于注入组的连续转换,但必须跟在规则组的连续转换之后转换)
??如果将JAUTO位置1,则注入组中的通道会在规则组通道之后自动转换。
??这可用于转换最多由20个转换构成的序列,这些转换在ADC_SQRx和 ADC_JSQR寄存器中编程。
??在此模式下,必须禁止注入通道上的外部触发。如果CONT位和 JAUTO位均已置1,则在转换规则通道之后会继续转换注入通道。
;注意:不能同时使用自动注入和不连续采样模式。
??ADC_CR2寄存器中的ALIGN位用于选择转换后存储的数据的对齐方式。可选择左对齐或右对齐两种方式,如图38和图39所示。
??注入通道组的转换数据将减去 ADC_JOFRx寄存器中写入的用户自定义偏移量,因此结果可以是一个负值。SEXT位表示扩展的符号值。
??对于规则组中的通道,不会减去任何偏移量,因此只有十二个位有效。
??ADC会在数个ADC_CLK周期内对输入电压进行采样,可使用ADC_SMPR1 和 ADC_SMPR2寄存器中的SMP[2:0]位修改周期数。每个通道均可以使用不同的采样时间进行采样。
总转换时间的计算公式如下:
Tconv =采样时间+12个周期
示例:若ADC_CLK = 30 MHz 且采样时间=3个周期时:
Tconv= 3 + 12= 15 个周期 =15/30 us =0.5 us
??可通过降低ADC分辨率来执行快速转换。RES位用于选择数据寄存器中可用的位数。每种分辨率的最小转换时间如下:
12位:3+12= 15 ADCCLK周期
10位:3+ 10= 13 ADCCLK周期
8位:3+8= 11 ADCCLK周期
6位:3+6= 9 ADCCLK周期
?
通过ADC采集STM32内部温度传感器。
??温度传感器可用于测量器件的环境温度。对于STM32F40x和 STM32F41x器件,温度传感器内部连接到ADC1_IN16 通道,使用ADC1 将传感器输出电压转换为数字值。
??不使用时可将传感器置于掉电模式。
??注意:必须将TSVREFE位置1才能同时对两个通道进行转换。ADC1_IN16或ADC1_IN18(温度传感器)和ADC1_IN17 (VREFINT)。
?
假设现有采集到的AD值为adVal。按照公式:
0- 3.3V按照12bitADC进行采样==区间为0-4095 ,相当于将3.3V分为4096份,每一个份的电压值为3.3V /4096 =0.0008056640625 V。
VSENSE= adVal*3.3V/4096。
?
void ADC1_IN16_Init (void)
{
RCC->APB2ENR |=(0x1 <<8);//1.打开ADC1时钟
ADC->CCR |=(0x1 <<23); //2.使能温度传感器通道
ADC->CCR &=~(0x3 <<16); //3.配置ADC分频
ADC->CCR |= (0x1 <<16); //4分频84Mhz /4=21Mhz
//4.配置好CR1、CR2
ADC1->CR1 =0;//整体清零
/*
*12bit分辨率
*禁止规则通道不连续采样*禁止扫描模式
*/
ADC1->CR2 =0;//整体清零
ADC1->CR2l=(0xl<<10);//每个规则通道转换,将Eoc置一
/*
*禁止规则通道外部触发
*数据右对齐
*单次转换*/
//5.构造规则组-转换序列长度1,序列顺序16
ADC1->SQR1 &=~ (0xF <<20);//规则序列长度=1
ADC1->SQR3 &=~ (0x1F <<0);
ADC1->SQR3 |=(16<<0);//第一次转换通道16
ADC1->SMPR1 |=(0x7<<18);//6.设置ADc IN16通道采样时间 480 + 12=23.4us
}
ul6 ADC1_ReadDate (void)
{
ul6 adval;
ADC1->CR2 |=(0x1 <<0);//7.使能ADC
ADC1->CR2 |=(0x1<< 30); //8.将CR2中的SWSTAET位置1--开始转换
while( !(ADC1->SR &(0x1<<1)) );//9.等待EOC置1
ADC1->SR &=~(0x1 <<1);//清除EOC标志
ad = ADC1->DR; //10.读取转换结果
ADC1->CR2 &= ~(0x1 <<0);//11.失能ADC
return adval;
}
//-------------------------主函数main.c内容
void main(void)
{
u16 r_adval;
float tempture;
ADC1_IN16_Init();
while(1)
{
r_adval =ADC1_ReadDate();
tempture=(r_adval * 3.3 / 4096-0.76) /2.5 +25;
printf("tempture=%f\n",tempture);
delay_ms(500);
}
}