需要用到的ADC配置函数
RCC_ADCCLKConfig();//配置ADCCLK分频器(对APB2的72MHz时钟进行2、4、6、8分频输入到ADCCLK)
ADC_Init();//ADC初始化
ADC_StructInit();//ADC结构体赋默认值
ADC_Cmd();//使能/失能ADC
ADC_DMACmd();//
使能/失能
DMA输出信号,需要DMA转运数据就用
ADC_RegularChannelConfig();//ADC规则组通道配置
ADC_ResetCalibration();//复位校准
ADC_GetResetCalibrationStatus();//获取复位校准状态
ADC_StartCalibration();//开始校准
ADC_GetCalibrationStatus();//获取开始校准状态
ADC_SoftwareStartConvCmd();//ADC软件触发转换开始
ADC_ExternalTrigConvCmd();//是否允许外部触发转换
ADC_GetFlagStatus();//获取【EOC】标志位状态,可以判断转换是否结束
//转换结束【EOC】置1,转换未结束【EOC】置0
ADC_GetConversionValue();//获取ADC转换值(读取ADC数据寄存器中的转换结果)
ADC_AnalogWatchdogCmd();//使能/失能模拟看门狗
ADC_AnalogWatchdogThresholdsConfig();//配置高低阈值
ADC_AnalogWatchdogSingleChannelConfig();//配置看门的通道
ADC_TempSensorVrefintCmd();//
使能/失能
ADC温度传感器、内部参考电压控制
AD多通道采集
配置AD时参考该图流程
1、完成驱动文件导入操作和编写驱动程序基本代码(参考之前文章)
//将【AD】驱动文件放在【Hardware】文件夹中
2、在AD.c中初始化函数AD_Init
void AD_Init(void)//初始化AD{//第一步:RCC开启ADC和GPIO的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//ADC都是APB2上的设备RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//需要配置ADCCLK分频器RCC_ADCCLKConfig(RCC_PCLK2_Div6);//第二步:配置需要用到的GPIOGPIO_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);//第三步:配置多路开关,选择规则组通道【查引脚定义表】ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//目前配置为:在规则组菜单列表的第一个位置(序列1)写入通道0//第四步:结构体配置ADCADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//转换模式选择(连续[ENABLE]/单次[DISABLE]转换)ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//用于外部触发规则组转换的触发源//此处选择不使用外部触发,也就是选择使用软件触发ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作模式(单/双AD转换)ADC_InitStructure.ADC_NbrOfChannel = 1;//在扫描模式时总共用到几个通道ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描转换选择(扫描[多通道][ENABLE]/非扫描[单通道][DISABLE]模式)ADC_Init(ADC1,&ADC_InitStructure);//目前配置ADC模式为【单次转换】、【非扫描】//这里还可以配置中断模拟看门狗,本例不用,这里不配置//第五步:开关控制,开启ADCADC_Cmd(ADC1,ENABLE);//ADC配置完成,可以正常工作//还要对ADC进行校准以减小误差ADC_ResetCalibration(ADC1);//复位校准while( ADC_GetResetCalibrationStatus(ADC1) == SET);//获取复位校准状态,等待复位校准完成//如果没校准完成(复位校准状态为SET),就在while空循环里一直等待,完成后跳出whileADC_StartCalibration(ADC1);//开始校准while( ADC_GetCalibrationStatus(ADC1) == SET);//获取开始校准状态,等待校准完成//如果没校准完成(校准状态为SET),就在while空循环里一直等待,完成后跳出while}
3、在
AD.c中编写启动AD转换获取结果函数AD_GetValue
编写启动AD转换获取结果函数时参考本图(单次转换、非扫描)
//启动转换,获取结果uint16_t AD_GetValue(void){//首先由软件触发转换ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发,ADC开始转换//等待转换完成(完成时EOC标志位置1)while( ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//如果转换未完成(EOC标志位为RESET),就在while空循环里一直等待,完成后跳出while//读取结果(ADC数据寄存器)return ADC_GetConversionValue(ADC1);//此处直接给AD_GetValue函数返回结果}
4、在AD.h中声明初始化函数AD_Init和启动AD转换获取结果函数AD_GetValue
void AD_Init(void);uint16_t AD_GetValue(void);
5、在主程序main.c中#include "AD.h"
#include "AD.h"
6、在主循环之前先初始化AD
7、在主循环中编写程序主体
uint16_t ADValue;float Voltage;int main(void){AD_Init();OLED_Init();OLED_ShowString(1,1,"ADValue:");OLED_ShowString(2,1,"Voltage:0.00V");while(1){ADValue = AD_GetValue();Voltage = ( (float) ADValue / 4095 ) * 3.3;//将AD值换算成电压OLED_ShowNum(1,9,ADValue,4);OLED_ShowNum(2,9,Voltage,1);//显示电压整数部分OLED_ShowNum(2,11,(uint16_t)(Voltage *100) % 100,2);//显示电压小数部分(先把电压放大100倍再取余)//浮点数不能取余,需要在这里强转为整数Delay_ms(100);//刷新的慢一些}}
实现功能:上电后不断进行AD采集并通过OLED显示ADValue:和Voltage:,通过旋转电位器(滑动变阻器)改变电压值
上面的程序是【单次转换】、【非扫描】
如果是【连续转换】、【非扫描】则只需要更改部分AD.c
//第四步:结构体配置ADCADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//转换模式选择(连续[ENABLE]/单次[DISABLE]转换)ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//用于外部触发规则组转换的触发源//此处选择不使用外部触发,也就是选择使用软件触发ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC工作模式(单/双AD转换)ADC_InitStructure.ADC_NbrOfChannel = 1;//在扫描模式时总共用到几个通道ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描转换选择(扫描[多通道][ENABLE]/非扫描[单通道][DISABLE]模式)ADC_Init(ADC1,&ADC_InitStructure);//目前配置ADC模式为【连续转换】、【非扫描】//这里还可以配置中断模拟看门狗,本例不用,这里不配置//第五步:开关控制,开启ADCADC_Cmd(ADC1,ENABLE);//ADC配置完成,可以正常工作//还要对ADC进行校准以减小误差ADC_ResetCalibration(ADC1);//复位校准while( ADC_GetResetCalibrationStatus(ADC1) == SET);//获取复位校准状态,等待复位校准完成//如果复位校准未完成(复位校准状态为SET),就在while空循环里一直等待,完成后跳出whileADC_StartCalibration(ADC1);//开始校准while( ADC_GetCalibrationStatus(ADC1) == SET);//获取开始校准状态,等待校准完成//如果校准未完成(校准状态为SET),就在while空循环里一直等待,完成后跳出while//【连续转换】只需要在最开始触发一次就行ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发,ADC开始转换//之后内部的ADC就会连续不断地对指定通道进行转换,将结果放在数据寄存器里,数据寄存器会不断刷新最新的转换结果-------------------------------------------------------------------------------------------------------------------------//不需要在AD_GetValue中不断触发,也不需要用while等待转换完成//获取结果uint16_t AD_GetValue(void){//读取结果(ADC数据寄存器)return ADC_GetConversionValue(ADC1);//此处直接给AD_GetValue函数返回结果}
实现功能:上电后不断进行AD采集并通过OLED显示ADValue:和Voltage:,通过旋转电位器(滑动变阻器)改变电压值
【基于AD单通道采集】AD多通道采集
-
使用【单次转换】、【非扫描】来实现多通道采集(只需要在每次触发转换之前,手动更改列表第一个位置的通道就行)
//EX:第一次转换,先写入【通道0】,之后触发,等待,读值
第二次转换,先把【通道0】改为【通道1】,之后触发,等待,读值
第三次转换…………
//使用【连续转换】模式需要配合【DMA】缓存数据,确保数据不被覆盖
-
修改部分前面的【AD单通道采集】代码即可
一、将初始化函数AD_Init中的部分代码
剪切到启动AD转换获取结果函数AD_GetValue
//第三步:配置多路开关,选择规则组通道【查引脚定义表】ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);//目前配置为:在规则组菜单列表的第一个位置(序列1)写入通道0|||||V//启动转换,获取结果uint16_t AD_GetValue(uint8_t ADC_Channel){//首先由软件触发转换ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件触发,ADC开始转换//配置多路开关,选择规则组通道【查引脚定义表】ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);//目前配置为:在规则组菜单列表的第一个位置(序列1)写入需要的通道//等待转换完成(完成时EOC标志位置1)while( ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);//如果转换未完成(EOC标志位为RESET),就在while空循环里一直等待,完成后跳出while//读取结果(ADC数据寄存器)return ADC_GetConversionValue(ADC1);//此处直接给AD_GetValue函数返回结果}
2、在AD.h中重新声明初始化函数AD_Init和启动AD转换获取结果函数AD_GetValue
void AD_Init(void);uint16_t AD_GetValue(void);
3、在主循环中编写程序主体
uint16_t AD0,AD1,AD2,AD3;//AD0:电位器//AD1:光敏传感器//AD2:热敏传感器//AD3:反射传感器int main(void){AD_Init();OLED_Init();OLED_ShowString(1,1,"AD0:");OLED_ShowString(2,1,"AD1:");OLED_ShowString(3,1,"AD2:");OLED_ShowString(4,1,"AD3:");while(1){AD0 = AD_GetValue(ADC_Channel_0);AD1 = AD_GetValue(ADC_Channel_1);AD2 = AD_GetValue(ADC_Channel_2);AD3 = AD_GetValue(ADC_Channel_3);//依次启动4次转换,并且在转换之前指定了转换的通道//每次转换完成之后,把结果分别存在4个数据里OLED_ShowNum(1,5,AD0,4);OLED_ShowNum(2,5,AD1,4);OLED_ShowNum(3,5,AD2,4);OLED_ShowNum(4,5,AD3,4);Delay_ms(100);//刷新的慢一些}}
实现功能:上电后不断进行四路AD采集并通过OLED显示AD值