一、ADC是什么
ADC(Analog-Digital Converter)模拟-数字转换器,可以将引脚上连续变换的模拟电压转换为数字变量储存,建立了模拟量与数字量之间的桥梁。
在我所使用的STM32中,是一个12位逐次逼近型ADC,转换时间最快为1us。
12位逐次逼近型ADC是什么意思?12位,就是ADC转换的精度,范围,也就是2^12。主次逼近型,这是他的工作原理,ADC是将输入值与一个标准值比较,标准值比输入值大,就减小标准值,比输入值小,就增大标准值。这个过程采用的是二分法,即下一个标准值取当次两者的中间值,而二分法在二进制数中的表现就是移位,所以在用二分法比较大小的时候,就是在二进制数中不断移位的过程,一直进行到两者相等,此时标准值就是输入值,将标准值移入寄存器,以用于后续读取,这就是逐次逼近。ADC转换需要一定时间,这个时间具体参考手册。
二、ADC的结构
ADC最多有18个输入(型号不同数量也会有所不同),其中16个GPIO口的输入是外部的,在32内部有两个输入,一个是温度,一个是标准值,这两个是内部自带的,只需要用过代码调用即可。选好输入通道后,要通过一个多路选择器,选中你所使用的那一路。随后数据进入ADC.
在ADC内部,有两个组,规则组和注入组。
2.1、规则组
规则组一次性最多可以输入16个数据,但是转换的结果寄存器中只有一个位置,也就是说,如果单单使用ADC的规则组,一次输入16个数据,那么前15个数据转化的结果都会被第16个数据转化的结果覆盖,最终得到的只有第16个数据转化的结果。所以要使用规则组一次性转化多个数据,需要配合DMA使用,这个暂时没学到。
2.2、注入组
注入组一次性最多可以输入4个数据,并且注入组的输出寄存器也有四个位置,所以采用注入组比较简单,适合入门。
2.3、工作模式
1.ADC有单ADC工作和双ADC工作模式。暂时不了解
2.单次转换和连续转换:
单次转换,完成一组数据转换后就停止了,想要继续转换需要再次触发。
连续转换,完成一组数据转换后不会停止,而是继续从头到尾转换数据。
3.扫描模式和非扫描模式:
扫描模式:对于一组数据中有不止一个数据的,扫描模式会按设置的扫描数量,转换对应数量的数据
非扫描模式:无论一组数据中有多少数据,都只转换第一个数据,然后就结束此次转换。
2.4、其他
START:触发控制,用来开始转换。
RCC:时钟信号
开关控制:给ADC上电,用函数控制。
EOC:标志位,0为未转换完成,1为转换完成。
模拟看门狗:用来检测数据,如果数据不在事先设置好的范围内,则触发对应的操作。
三、Keil5代码
3.1、常用函数
RCC_ADCCLKConfig 配置ADCCLK分频器,可以对APB2的72MHZ进行2/4/6/8分频输入到ADCCLK
ADC_DeInit 反初始化
ADC_Init ADC初始化
ADC_StructInit 结构体初始化
ADC_Cmd ADC上电允许(开关控制)
ADC_DMACmd 开启DMA输出信号
ADC_ITConfig 终端输出控制
ADC_ResetCalibration 复位校准
ADC_GetResetCalibrationStatus 获取复位校准状态
ADC_StartCalibration 开始校准
ADC_GetCalibrationStatus 获取开始校准状态
ADC_SoftwareStartConvCmd 软件触发ADC
ADC_GetSoftwareStartConvStatus 获取软件触发状态(注意,标志位在软件触发开始后就被清零0了)
ADC_GetFlagStatus 获取标志位状态
ADC_DiscModeChannelCountConfig 每隔几个通道间断一次
ADC_DiscModeCmd 是不是启用间断模式
ADC_RegularChannelConfig ADC规则组通道配置
ADC_ExternalTrigConvCmd ADC外部触发转换控制
ADC_GetConversionValue ADC获取转换值
ADC_GetDualModeConversionValue 双ADC模式读取转换结果
ADC_TempSensorVrefintCmd ADC温度传感器,内部参考电压控制(开启内部两个通道)
ADC_GetFlagStatus 获取标志位状态
ADC_ClearFlag 清除标志位
ADC_GetITStatus 获取中断状态
ADC_ClearITPendingBit 清除中断状态挂起位
3.2初始化函数
void AD_Init(void)
{
//第一步,初始化时钟RCC--ADC的时钟和GPIO的时钟以及ADCCLK
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
//第二步,初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//第三步,选择通道
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
//第四步,初始化ADC
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_Init(ADC1,&ADC_InitStructure);
//第五步,给ADC上电
ADC_Cmd(ADC1,ENABLE);
//第六步,使用前校准一下
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) == SET);
}