1.ADC简介
ADC(Analog-Digital Converter)模拟-数字转换器
ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
12位逐次逼近型ADC,1us转换时间
输入电压范围:0~3.3V,转换结果范围:0~4095
18个输入通道,可测量16个外部(GPIO口,在引脚直接接模拟信号就行)和2个内部信号源(内部温度传感器和内部参考电压,温度传感器可以测量CPU的温度,比如你电脑可以显示CPU的温度,就可以用ADC读取这个温度传感器来测量,内部参考电压是1.2V左右的基准电压,这个基准电压不随外部电压变化而变化的,所以如果你芯片的供电不是标准的3.3V,那测量外部引脚的电压可能就不对,这是就可以读取这个基准电压进行校准,这样就可以得到正确的电压值)
规则组和注入组两个转换单元
模拟看门狗自动监测输入电压范围
STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道
2.ADC基本结构
左边是输入通道,16个GPIO口,外加两个内部通道,然后进入AD转换器,AD转换器里有两个组,一个是规则组,一个是注入组,规则组最多可以选中16个通道,注入组最多可以选择4个通道,然后转换的结果可以存放在AD数据寄存器里,其中规则组只有1个数据寄存器,注入组4个,然后下面有触发控制源,提供了开始转换这个START信号,触发控制可以选择软件触发和硬件触发,硬件触发主要来自定时器,当然页可以选择外部中断的引脚,右边这里是来自于RCC的ADC时钟CLOCK,ADC逐次比较的过程就是由这个时钟推动的,然后上面,可以布置一个模拟看门狗用于检测转换结果的范围,如果超出设定的阈值。就通过中断输出控制,向NVIC申请中断,另外,规则组和注入组转换完成后会有个EOC信号,它会置一个标志位,当然也会通向NVIC,最后右下角这里还有个开关控制,在库函数中,就是ADC_Cmd函数,用于给ADC上电的。
3.ADC知识点
3.1 输入通道
通道 | ADC1 | ADC2 | ADC3 |
通道0 | PA0 | PA0 | PA0 |
通道1 | PA1 | PA1 | PA1 |
通道2 | PA2 | PA2 | PA2 |
通道3 | PA3 | PA3 | PA3 |
通道4 | PA4 | PA4 | PF6 |
通道5 | PA5 | PA5 | PF7 |
通道6 | PA6 | PA6 | PF8 |
通道7 | PA7 | PA7 | PF9 |
通道8 | PB0 | PB0 | PF10 |
通道9 | PB1 | PB1 | |
通道10 | PC0 | PC0 | PC0 |
通道11 | PC1 | PC1 | PC1 |
通道12 | PC2 | PC2 | PC2 |
通道13 | PC3 | PC3 | PC3 |
通道14 | PC4 | PC4 | |
通道15 | PC5 | PC5 | |
通道16 | 温度传感器 | ||
通道17 | 内部参考电压 |
3.2 转换模式
1.单次转换,非扫描模式
在非扫描模式下,只有序列1的通道有效,这时,菜单同时选中一组的方式就退化为简单地选中一个的方式,在这里可以在序列1的位置,指定我们向选择的通道,然后我们就可以触发转换,ADC就会对这个通道2金星模数转换,过一小段时间后,转换完成,转换结果放在数据寄存器里,同时给EOC标志位置1,转换过程结束,我们判断这个EOC标志位,如果转换完了,那我们就可以在数据寄存器读取结果了。如果我们想在启动一次转换就需要在触发一次。
2.连续转换,非扫描模式
它与单次转换不同的时在一次转换结束后不会停止,而是立刻开始下一轮的转换,然后一直持续下去,这样就只需要开始触发一次,之后就可以一直转换了,这个模式的好处就是,开始转换之后不需要等待一段时间的,因为它一直都在转换,所以你就不需要手动开始转换,也不用判断是否结束,想要读AD值的时候,直接从数据寄存器取就是。
3.单次转换,扫描模式
这是单词转换,所以转换一次后就会停下来,下次转换就得再触发才能开始,然后时扫描模式,会用到这个菜单列表,可以选择每个序列位的通道,通道可以任意指定页可以重复,然后初始化结构体里还会有个参数,就是通道数目,每次触发后,就会一次对指定通道进行AD转换,转换结果都会放到数据寄存器里,这里为了防止数据被覆盖,就需要用DMA及时将数据挪走,通道都转换完成后,残生EOC信号,转换结束。然后触发下一次,进行新一轮的转换。
4.连续转换,扫描模式
3.3 触发控制
触发信号的选择,可以通过配置右边的寄存器来完成,使用库函数,直接给个参数就行。
3.4 数据对齐
ADC是12位的,它的转换结果就是12位的数据,但数据寄存器是16位的,所以就存在一个数据对齐的问题。
数据右对齐
12位的数据向右靠,高位多出来的几位就补0,一般使用右对齐,这样读取16位寄存器,直接就是转换结果
12位的数据向左靠,低位多出来的几位就补0,选择左对齐直接读的话,得到的数据会比实际值大,因为数据左对齐就是把数据左移4次,二进制特点数据左移一次,就等效于把这个数据乘2,这里左移4次就成16了。左对齐的用途,如果你不想要这么高的分辨率,觉得0~4095这个数太大,就需要简单的判断,不需要这么高的分辨率,选择左对齐,然后把数据高八位取出来,舍去后4位,这个12位的ADC退化为8位的ADC。
3.5 转换时间
AD转换的步骤:采样,保持,量化,编码
STM32 ADC的总转换时间为:
TCONV = 采样时间 + 12.5个ADC周期
例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期
TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs
4.ADC配置
1.开启RCC时钟,包括ADC和GPIO的时钟,ADCCLK的分频器也需要配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
2.配置GPIO,把需要用的GPIO配置成模拟输入的模式
3.配置多路开关,把通道接入到右边的规则列表里
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
4.配置ADC转换器(如果向配置看门狗,有几个函数来配置阈值和检测通道的;如果向开启中那就再中断输出控制里用ITConfig函数开启对应的中断输出,然后再NVIC配置优先级即可)
ADC_InitTypeDef ADC_InitStructure; //定义结构体变量
ADC_InitStructure.ADC_Mode //模式
ADC_InitStructure.ADC_DataAlign /数据对齐
ADC_InitStructure.ADC_ExternalTrigConv //外部触发
ADC_InitStructure.ADC_ContinuousConvMode //连续转换
ADC_InitStructure.ADC_ScanConvMode //扫描模式
ADC_InitStructure.ADC_NbrOfChannel //通道数,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
ADC_Init(ADC1, &ADC_InitStructure);
5.开关控制(开器ADC之后,根据手册的建议,我们还可以对ADC校准,这样可以减小误差)
ADC_Cmd(ADC1, ENABLE);//使能ADC1,ADC开始运行
ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);