ADC简介
·ADC(Analog-Digital Converter)模拟-数字转换器
·ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路 的桥梁
·12位逐次逼近型ADC,1us转换时间
·输入电压范围:0~3.3V,转换结果范围:0~4095
·18个输入通道,可测量16个外部和2个内部信号源
·规则组和注入组两个转换单元
·模拟看门狗自动监测输入电压范围
·STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道
配置ADC的基本结构
本节暂时不会用到看门狗和中断输出控制等部分, 本节演示的是软件触发、规则组,单次转换、非扫描模式的ADC转换。
输入通道
由于该芯片只有10个外部输入通道,所以只有通道0到通道9这10个引脚可用于输入模拟量。
ADC初始化配置模板
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//ADC都是挂载在APB2总线上
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//配置ADC时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//选择6分频 ADC时钟最大频率为14MHz
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//选择模拟输入模式 ADC专属
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//选择规则组的输入通道
/*
在规则组菜单列表的第一个位置,写入通道0
*/
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
//ADC_RegularChannelConfig(ADC1,ADC_Channel_3,2,ADC_SampleTime_55Cycles5);//填充列表的方式
//初始化ADC
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//选择独立模式还是双ADC模式
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//选择数据对齐方式
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//外部触发转换选择(触发控制的触发源选择)
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//选择单次转换
ADC_InitStructure.ADC_ScanConvMode=DISABLE;//选择非扫描模式
ADC_InitStructure.ADC_NbrOfChannel=1;//选择通道数目(1~16)
ADC_Init(ADC1,&ADC_InitStructure);
//上电ADC
ADC_Cmd(ADC1,ENABLE);
//对ADC进行校准
ADC_ResetCalibration(ADC1);//这里会将复位校准状态标志位置1
while(ADC_GetResetCalibrationStatus(ADC1));//获取复位校准状态,复位校准完后状态位标志为0,跳出循环
ADC_StartCalibration(ADC1);//开始校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
RCC_ADCCLKConfig是用来配置ADCCLK分频器的,
由上图可知,ADCCLK最大频率为14MHz,所以这里选择6分频,即72MHz/6=12MHz。
接着初始化GPIO口时要配置成模拟输入模式。
然后选择规则组的输入通道,因为初始化了PA0口,对应通道0,其中第三个参数是指定序列号
接着就是老朋友Init函数,都按照模板里配置就是单次转换非扫描模式,注意ADC_ExternalTrigConv参数,我们选择外部触发None,就是使用软件触发。
接着上电ADC。
最后根据手册的建议,我们可以对ADC进行校准,以减小误差。
我们想要获取转换的值,可以用下面这个函数
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//触发转换,选择软件触发
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);//获取规则组转换完成标志位EOC
return ADC_GetConversionValue(ADC1);//获取转换值
}
将该函数放在while循环里,就会不断进行软件触发,进而进行ADC转换,当转换完成时,EOC为1
由手册可知,我们调用 ADC_GetConversionValue函数时,就是读取ADC_DR的值,所以不用再手动对EOC清零。
若想要选择连续转换,非扫描模式
只需要将模板里的ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//选择单次转换
改为ENABLE就是选择连续转换模式了
可见只需要软件触发一次,就会不停的进行转换
所以我们只需要在初始化函数最后触发一次就可以了,不需要一直在while里触发,读取转换值时也不用判断标志位,因为此时数据寄存器会不断刷新最新的转换结果,我们只需要读出来就行了。
常用函数
RCC_ADCCLKConfig;配置ADCCLK分频器
ADC_SoftwareStartConvCmd;软件触发
ADC_GetFlagStatus;获取标志位状态,判断EOC
ADC_RegularChannelConfig;规则组通道配置
ADC_ExternalTrigConvCmd;外部触发转换控制,就是是否允许外部触发转换
ADC_GetConversionValue;ADC获取转换值