一、STM32中ADC(模拟-数字转换器)简介:
ADC可以将引脚上连续变化的模拟电压转换位数字变量,而STM32F10xx中使用的是12位的逐次逼近型模拟数字转换器,所以它转换的数字变量变化范围为:0~4095。
它有多达18个通道,可测量16个外部和2个内部信号源(温度传感器/ V REFINT 内部通道)STM32F103C8T6中ADC资源:ADC1、ADC2、10个外部输入通道
当使用对应引脚获取AD值时,需要选择对应通道,否则数据无效
ADC的输入时钟不得超过14MHz,它是由PCLK2(72MHZ)经分频产生
相应代码为RCC_ADCCLKConfig(RCC_PCLK2_Div6);(此处为6分频,还可进行8分频)
STM32F103C8T6中ADC转换时间为1.17us
ADC供电要求:2.4V~3.6V
它有两个转换单元:1、注入组 2、规则组
二、ADC框图介绍:
1、逐次逼近型ADC(非STM32):
寄存器SAR中的数字为0~255,使用二分法不断细分,将细分的数字给到DAC,然后DAC会生成对应的电压,再与输入通道的电压通过比较器进行比较,如果DAC电压比较大,SAR就将原来输出给DAC的数字再除以2,并将最后值给DAC,最后在于待测电压进行比较,直到找到相似电压为止。
2、ADC框图:
对应输入的通道(16个外部信号源和2个内部信号源)
模拟多路开关:指定选择的通道,注入组最多选择4个通道,二规则组可以选择16个通道
模拟至数字转换器:就是逐次逼近型ADC(图二)
上面两个是ADC的参考电压,也就是0~4095对应的电压值,下面两个是ADC的供电电压。
ADC的触发方式有两种:1、软件触发:ADC_SoftwareStartConvCmd(ADC1, ENABLE);
2、硬件触发:硬件触发又可分为:
1、外部中断触发(不太建议使用,中断触发会导致程序不断进入中断处理简单的程序(并且中断的优先级不一样也会导致ADC转换不及时),可能会造成ADC转换频率造成影响)
2、定时器触发(TRGO):如给TIM3设置一个时间,并且把他的更新事件选择为TRGO输出
(TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );产生更新事件,TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update)选择输出触发源为TRGO)(事件与中断的不同:中断他是有对应的函数的,当你触发的时候必须要CPU的干预,但是事件它没有对应函数,他却可以触发相关联的操作,可以不需要CPU的干预)然后ADC中选择,开始触发信号为TIM3的TRGO,当触发更新事件时,就会进行ADC采样了。
用于存放采样后的数据,注意:
1、规则组他只有一个,而他的通道却有16个,所以它再存放的过程中会出现数据被覆盖的现象(解决办法,使用DMA转运)而注入组却不用担心,因为他的通道数和寄存器个数一样。
2、因为他的寄存器是16为,而ADC转运结构却只有12位,所以会多出来几位。所以它的数据对其位有两种对其方式(可以再配置ADC结构体时选择):
一般常用右对其,当你只是需要大概值时可以选择左对齐,将低8位舍弃。
设置两个阈值,当结果超过阈值时,看门狗会触发中断。
中断触发:当规则组转换完成时会置EOC标志位1,查看标志位可判断转换是否完成。
同理JEOC位注入组的标志位,AWD位看门狗的标志位。
三、ADC基本结构和配置:
第一步:开启RCC时钟(ADC和GPIO)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
第二步:配置ADCCLK的分配器(最大不超过14)
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
第三步:配置GPIO(GPIO配置为模拟输入)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
第四步:配置多路开关
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);//规则组
ADC_InjectedChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);//规则组
第五步:配置ADC转换器(配置结构体)
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐,选择右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发,使用软件触发,不需要外部触发
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //连续转换,失能,每转换一次规则组序列后停止
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式,失能,只转换规则组的序列1这一个位置
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
第六步:开启ADC(CMD)
注意:最后进行ADC校准,这样可以减少误差
//固定流程,内部有电路会自动执行校准
ADC_ResetCalibration(ADC1); //复位校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);//复位校准完成
ADC_StartCalibration(ADC1);//启动校准
while (ADC_GetCalibrationStatus(ADC1) == SET);//启动校准完成
(选配)
第7步:配置看门狗阈值
第8步:开启中断输出控制(ITconfig)
第9步:配置NVIC
四、转换模式(以规则组为例):
共四种转换模式:
单次转换,非扫描模式
转换一次后需要重新触发,且再触发前可以更改通道,并且需要判断EOC标志位来确定他是否转运完成
连续转换,非扫描模式
只需触发一次就可以连续准换,也不用判断EOC标志位
单次转换,扫描模式:
可以选择多个序列,序列中的通道可以重复,只有当7个转换完成后才会置EOC标志位
连续转换,扫描模式:
间断模式:
你可以选择当外部触发时经过n次转换,直到此序列所有转换完成为止。
举例:
n=3,被转换的通道 = 0、1、2、3、6、7、9、10
第一次触发:转换的序列为 0、1、2
第二次触发:转换的序列为 3、6、7
第三次触发:转换的序列为 9、10,并产生EOC事件
第四次触发:转换的序列 0、1、2
五、转换时间:
TCONV = 采样时间 + 12.5个ADC周期
例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期
TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs