07:STM32----ADC模数转化器

目录

1:简历

2:逐次逼近型ADC

3:ADC基本结构

 4:输入通道

5:规则组的4种转换模式 

1:单次转化,非扫描模式

2:连续转化,非扫描模式

3:单次转化,扫描模式

4:单次转化,扫描模式

6:触发控制

7:数据对齐

 8:转化时间

9:校准

10:ADC的硬件电路

A: AD单通道

1:连接图 

2:函数介绍

3:步骤

4:代码

 B:AD多通道

 1:连接图  

2:代码


1:简历

        ADC(Analog-Digital Converter)模拟-数字转换器

        ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁

        12位逐次逼近型ADC,1us转换时间

        输入电压范围:0~3.3V,转换结果范围:0~4095

        18个输入通道,可测量16个外部(GPIO)和2个内部信号源(内部温度传感器和内部参考电压)

        规则组和注入组两个转换单元

        模拟看门狗自动监测

        输入电压范围 STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道

        12位逐次逼近型ADC,1us转换时间 : 

        分辨率 : 一般用多少位来表示,12位AD值,它的表示范围就是0~2^12-1,量化结果的范围是0~4095 , 位数越高,量化结果就越精细,对应分辨率就越高

        转换时间: 就是转化频率AD转换是需要花一小段时间的,这里1us就表示从AD转换开始到产生结果,需要花1us的时间。对应AD转换的频率就是1MHZ ,  这个就是STM32 ADC的最快转换频率

 规则组和注入组两个转换单元:

        普通的AD转换流程是,启动一次转换、读一次值 , 然后再启动、再读值,这样的流程 ; 

STM32的ADC就比较高级: 可以列一个组,一次性启动一个组,连续转换多个值 , 并且有两个组,一个是用于常规使用的规则组 ,一个是用于突发事件的注入组

2:逐次逼近型ADC

         ADC0809 : 独立的8位逐次逼近型ADC芯片
        EOC是End of Convert : 转换结束信号

        START : 是开始转换,给一个输入脉冲,开始转换

        CLOCK : 是ADC时钟,因为ADC内部是一步一步进行判断的
        REF+和VREF- : DAC的参考电压

3:ADC基本结构

 4:输入通道

5:规则组的4种转换模式 

在初始化ADC时配置的参数

单次转化 : ADC 执行一次转换,然后,ADC 停止

连续转化: 与单次转换不同的是,它在一次转换结束后不会停止 ,  而是立刻开始下一轮的转换,然后一直持续下去  ,  这样就只需要最开始触发一次,之后就可以一直转换了

扫描模式 : 在组中填几个通道几个通道就有效 , 填入多个的时候应避免覆盖的问题,  使用使用DMA

非扫描模式 : 这个组就只有第一个序列1的位置有效 , 这时选中一组的方式就退化为简单地选中一个的方式了

 X.ADC_ContinuousConvMode=DISABLE;//选择是连续转换还是单次转换---单X.ADC_ScanConvMode=DISABLE;//可以选择是扫描模式还是非扫描模式---非扫描模式

1:单次转化,非扫描模式

 

        在非扫描的模式下,这个组就只有第一个序列1的位置有效 , 这时选中一组的方式就退化为简单地选中一个的方式了

        我们可以在序列1的位置指定我们想转换的通道 , 比如通道2 , 然后,我们就可以触发转换,ADC就会对这个通道2进行模数转换 , 过一段时间转化完成  , 转换结果放在数据寄存器里,同时给EOC标志位置1----转换过程就结束了 .   我们判断这个EOC标志位,如果转换完了 ,  可以在数据寄存器里读取结果了 ,  如果我们想再启动一次转换,那就需要再触发一次 ,  转换结束,置EOC标志位,读结果

2:连续转化,非扫描模式

 

        首先,它还是非扫描模式,所以组列表就只用第一个  ,  与单次转换不同的是,它在一次转换结束后不会停止 ,  而是立刻开始下一轮的转换,然后一直持续下去  ,  这样就只需要最开始触发一次,之后就可以一直转换了

        优点  :  开始转换之后不需要等待一段时间的 ,  它一直都在转换,所以你就不需要手动开始转换了 , 也不用判断是否结束的 ,  想要读AD值的时候,直接从数据寄存器取就是了

3:单次转化,扫描模式

 

        这个模式也是单次转换,所以每触发一次 , 转换结束后,就会停下来  ,  下次转换就得再触发能开始

        扫描模式 : 会用到这个组了 , 在序列中填入通道 , 这里每个位置是通道几可以任意指定,并且也是可以重复的 ,  初始化结构体里还会有个参数,就是通道数目 (x.ADC_NbrOfChannel=)  比如这里指定通道数目为7,那它就只看前7个位置,那么x.ADC_NbrOfChannel=7, 它就会只对前7个AD通道进行转化,   转换结果都放在数据寄存器里  ,   这里为了防止数据被覆盖,就需要用DMA及时将数据挪走  ,  那7个通道转换完成之后,产生EOC信号(EOC置1),转换结束 ,  然后再触发下一次,就又开始新一轮的转换

使用DMA---避免通道数据覆盖

        因为这里只有一个规则组的数据寄存器 , 如果使用了 扫描模式在一个组中开启了7个通道,  只会有最后一个通道被保留下来,  前面的6个通道会被覆盖掉. 最后只会得到一个通道.

        使用这里使用MDA在下一个通道来之前,  把现在的数据放到了MDA中, 避免出现通道的覆盖问题

4:单次转化,扫描模式

         次转换完成后,立刻开始下一次的转换 , 也开启组

6:触发控制

配置ADC时使用的参数-----X.ADC_ExternalTrigConv

7:数据对齐

ADC初始化中的配置---X.ADC_DataAlign

 

        我们这个ADC是12位的,它的转换结果就是一个12位的数据 ,  但是这个数据寄存器是16位的,所以就存在一个数据对齐的问题

右对齐 : 就是12位的数据向右靠 , 就是12位的数据向有靠 , 高位多出来的几位就补0 ,一般

使用右对齐,  这样读取这个16位寄存器,直接就是转换结果

左对齐 : 是12位的数据向左靠 ,  低位多出来的几位补0 ,  得到的数据会比实际的大 ,  数据左对齐实际上就是把数据左移了4次  ,数据左移一次,就等效于把这个数据乘2 , 直接读取的话相当于把数据扩大了16倍 . 

 8:转化时间

 

 

9:校准

        ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差

        建议在每次上电后执行一次校准

        启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期

10:ADC的硬件电路

 

A: AD单通道

1:连接图

 

2:函数介绍

在stm32f10x rcc.h文件中-----配置ADCCLK

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2)

RCC_ADCCLKConfig :  APB2时钟72MHz时钟信号然后通过ADC预分频器进行分频,得到ADCCLK钟信号 ; ADCCLK最大是14MHz , 所以这里只能是6分频或者是8分频

        6分频:72Mhz/6=12Mhz,             8分频:72Mhz/8=9Mhz

在stm32f10x adc.h文件中----选择组----我们选择规则组的输入通道

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);

 ADC_RegularChannelConfig : 参数2--选择通道 , 参数3--选择序列范围1~16       参数3: 指定通道的采样时间

在stm32f10x adc.h文件中----初始化ADC

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);

ADC_InitTypeDef ADC_initstruct;


    ADC_initstruct.ADC_ContinuousConvMode=DISABLE;//选择是连续转换还是单次转换---单次
    ADC_initstruct.ADC_DataAlign=ADC_DataAlign_Right; //数据对齐---右对齐
    ADC_initstruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//触发控制的触发源---不使用外部触发,使用内部软件触发
    ADC_initstruct.ADC_Mode=ADC_Mode_Independent;//ADC的工作模式---独立模式
    ADC_initstruct.ADC_NbrOfChannel=1;  //通道数目--指定在扫描模式下,总共会用到几个通道
    ADC_initstruct.ADC_ScanConvMode=DISABLE;//可以选择是扫描模式还是非扫描模式---非扫描模式
    ADC_Init(ADC1,&ADC_initstruct);

在stm32f10x adc.h文件中----开启ADC

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState)

在stm32f10x adc.h文件中----校准ADC

第一步,调用第一个函数,复位校准

第二步,调用第二个函数,等待复位校准完成

第三步,调用第三个函数,开始校准

第四步,调用第四个函数,等待校准完成

1 : void ADC_ResetCalibration(ADC_TypeDef* ADCx);
2 : FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
3 : void ADC_StartCalibration(ADC_TypeDef* ADCx);
4 : FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);

ADC_ResetCalibration : 复位校准

ADC_GetResetCalibrationStatus : 等待复位校准完成

ADC_StartCalibration : 开始校准

ADC_GetCalibrationStatus : 获取校准状态

在stm32f10x adc.h文件中----启动转换,获取结果

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)

ADC_SoftwareStartConvCmd : 软件触发转换

ADC_GetFlagStatus : 获取标志位状态的函数

ADC_GetConversionValue : ADC 获取转换值

3:步骤

1:RCC开启时钟-----ADC和GPIO的时钟

2: 配置ADCCLK----RCC_ADCCLKConfig

3: 配置GPIO-----GPIO_Init

4:选择组----我们选择规则组的输入通道--------ADC_RegularChannelConfig

5: 初始化ADC-----ADC_Init

6:开启ADC----ADC_Cmd

7:校准ADC:

A: 复位校准-----ADC_ResetCalibration

B:等待复位校准完成----ADC_GetResetCalibrationStatus

C: 开始校准-----ADC_StartCalibration

D:获取校准状态-----ADC_GetCalibrationStatus 

4:代码

        使用的是单次转化,非扫描模式

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

#include "AD.h"
void AD_init(void){
	//RCC开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//配置ADCCLK
	//APB2时钟72MHz时钟信号然后通过ADC预分频器进行分频,得到ADCCLK钟信号
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72Mhz/6=12Mhz
	
	//配置GPIO
	GPIO_InitTypeDef GPIO_initstruct;
	GPIO_initstruct.GPIO_Mode=GPIO_Mode_AIN;  //模拟输入,可以理解为ADC的专属模式
	GPIO_initstruct.GPIO_Pin=GPIO_Pin_0;
	GPIO_initstruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_initstruct);
	
	//选择AD转化器----我们选择规则组的输入通道
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);  
	/*ADC_Channel_0--通道o
	1----1~16的范围规则组第几个序列
	ADC_SampleTime_55Cycles5-----指定通道的采样时间
	*/
	
	//初始化ADC
	ADC_InitTypeDef ADC_initstruct;
	ADC_initstruct.ADC_ContinuousConvMode=DISABLE;//选择是连续转换还是单次转换---单次
	ADC_initstruct.ADC_DataAlign=ADC_DataAlign_Right; //数据对齐---右对齐
	ADC_initstruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//触发控制的触发源---不使用外部触发,使用内部软件触发
	ADC_initstruct.ADC_Mode=ADC_Mode_Independent;//ADC的工作模式---独立模式
	ADC_initstruct.ADC_NbrOfChannel=1;  //通道数目--指定在扫描模式下,总共会用到几个通道
	ADC_initstruct.ADC_ScanConvMode=DISABLE;//可以选择是扫描模式还是非扫描模式---非扫描模式
	ADC_Init(ADC1,&ADC_initstruct);

	//开启ADC
	ADC_Cmd(ADC1,ENABLE);
	
	//校准ADC
	
	//复位校准
	ADC_ResetCalibration(ADC1);//---把CR2_RSTCAL_Set这一位置一
	//等待复位校准完成--ADC_GetResetCalibrationStatus作用:返回复位校准的状态
	while (ADC_GetResetCalibrationStatus(ADC1)==SET);   //SET=1
	/*获取的是这个CR2_RSTCAL_Set的标志位 ,该位由软件设置并由硬件清除
	在校准寄存器被初始化后该位将被清除,所以该位的用法就是:
	你软件置该位为1,那硬件就会开始复位校准 , 当复位校准完成后,该位就会由硬件自动清0
	*/
	//开始校准
	ADC_StartCalibration(ADC1);
	//获取校准状态
	while(ADC_GetCalibrationStatus(ADC1)==SET);

}

uint16_t ad_getvalue(){
	//启动转换,获取结果
	
	//软件触发转换
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	//获取标志位状态的函数
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
	/*
	EOC是规则组或注入组完成时都会置1 , 0(RESET):转换未完成:
	1(SET):转换完成
	*/
	//ADC 获取转换值
	return ADC_GetConversionValue(ADC1);
	/*ADC_GetConversionValue---那这里,因为读取DR寄存器会自动清除EOC标志位
	所以这之后我们就不需要再手动清除标志位了
	
	*/
	

}



uint16_t advalue;
float volatge;
int main(void)
{
	OLED_Init();
	AD_init();
	
	OLED_ShowString(1, 1, "ADValue:");
	OLED_ShowString(2, 1, "volatge:0.00V");
	
	
	while (1)
	{
		advalue=ad_getvalue();
		volatge=(float)advalue /4095 *3.3;
		OLED_ShowNum(1, 9, advalue, 4);
		OLED_ShowNum(2, 9, volatge, 1);
//浮点数不能取余
		OLED_ShowNum(2, 11, (uint16_t)(volatge * 100) % 100, 2);
		Delay_ms(100);
//OLED_ShowNum函数是写整数的,所以使用这中方法表示小数

	}
}

校准ADC     SET=1   RESET=0

       //复位校准
    ADC_ResetCalibration(ADC1);
   //等待复位校准完成
    while (ADC_GetResetCalibrationStatus(ADC1)==SET);   
    //开始校准
    ADC_StartCalibration(ADC1);
    //获取校准状态
    while(ADC_GetCalibrationStatus(ADC1)==SET);

        复位校准(ADC_ResetCalibration)函数的作用是把CR2_RSTCAL_Set这一位置一 ; 

         等待复位校准完成(while (ADC_GetResetCalibrationStatus(ADC1)==SET) :  获取的是这个CR2_RSTCAL_Set的标志位 ,该位由软件设置并由硬件清除在校准寄存器被初始化后该位将被清除,所以该位的用法就是:你软件置该位为1,那硬件就会开始复位校准 , 当复位校准完成后,该位就会由硬件自动清0

        开始校准(ADC_StartCalibration) : 这样子就可以启动校准

        获取校准状态(while(ADC_GetCalibrationStatus(ADC1)==SET);) : 看校准是否完成

启动转换,获取结果    SET=1   RESET=0

        ​​​​​//软件触发转换
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);
    //获取标志位状态的函数
    while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
     //ADC 获取转换值
    return ADC_GetConversionValue(ADC1);
          软件触发转换(ADC_SoftwareStartConvCmd) : ADC开始转化

        获取标志位状态的函(while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);)

: EOC是规则组或注入组完成时都会置1 , 0(RESET):转换未完成:1(SET):转换完成

        ADC 获取转换值(ADC_GetConversionValue(ADC1);) : ADC_GetConversionValue---那这里,因为读取DR寄存器会自动清除EOC标志位 所以这之后我们就不需要再手动清除标志位了
    

按照上面的流程来执行就ok了 : 首先,软件触发转换 , 然后等待转换完成,也就是等待EOC标志位置1 , 最后,读取ADC数据寄存器

配置GPIO---模式选择模拟输入 

GPIO_initstruct.GPIO_Mode=GPIO_Mode_AIN;

        在AIN模式下,GPIO口是无效的 ,  断开GPIO”防止你GPIO口的输入输出对我模拟电压造成干扰 ,  所以AIN模式就是ADC的专属模式

引脚分布

       

使用连续转化,非扫描模式

        优点: 不需要不断地触发,也不需要等待转换完成的

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

#include "AD.h"
void AD_init(void){
	//RCC开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//配置ADCCLK
	//APB2时钟72MHz时钟信号然后通过ADC预分频器进行分频,得到ADCCLK钟信号
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72Mhz/6=12Mhz
	
	//配置GPIO
	GPIO_InitTypeDef GPIO_initstruct;
	GPIO_initstruct.GPIO_Mode=GPIO_Mode_AIN;  //模拟输入,可以理解为ADC的专属模式
	GPIO_initstruct.GPIO_Pin=GPIO_Pin_0;
	GPIO_initstruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_initstruct);
	
	//选择AD转化器----我们选择规则组的输入通道
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);  
	/*ADC_Channel_0  --通道o
	1----1~16的范围规则组第几个序列
	ADC_SampleTime_55Cycles5-----指定通道的采样时间
	*/
	
	//初始化ADC
	ADC_InitTypeDef ADC_initstruct;
	ADC_initstruct.ADC_ContinuousConvMode=ENABLE;//选择是连续转换还是单次转换---单次
	ADC_initstruct.ADC_DataAlign=ADC_DataAlign_Right; //数据对齐---右对齐
	ADC_initstruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//触发控制的触发源---不使用外部触发,使用内部软件触发
	ADC_initstruct.ADC_Mode=ADC_Mode_Independent;//ADC的工作模式---独立模式
	ADC_initstruct.ADC_NbrOfChannel=1;  //通道数目--指定在扫描模式下,总共会用到几个通道
	ADC_initstruct.ADC_ScanConvMode=DISABLE;//可以选择是扫描模式还是非扫描模式---非扫描模式
	ADC_Init(ADC1,&ADC_initstruct);

	//开启ADC
	ADC_Cmd(ADC1,ENABLE);
	
	//校准ADC
	
	//复位校准
	ADC_ResetCalibration(ADC1);//---把CR2_RSTCAL_Set这一位置一
	//等待复位校准完成--ADC_GetResetCalibrationStatus作用:返回复位校准的状态
	while (ADC_GetResetCalibrationStatus(ADC1)==SET);   //SET=1
	/*获取的是这个CR2_RSTCAL_Set的标志位 ,该位由软件设置并由硬件清除
	在校准寄存器被初始化后该位将被清除,所以该位的用法就是:
	你软件置该位为1,那硬件就会开始复位校准 , 当复位校准完成后,该位就会由硬件自动清0
	*/
	//开始校准
	ADC_StartCalibration(ADC1);
	//获取校准状态
	while(ADC_GetCalibrationStatus(ADC1)==SET);
	
	//软件触发转换
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//连续模式下只需要触发一次

}

uint16_t ad_getvalue(){
	//启动转换,获取结果

	return ADC_GetConversionValue(ADC1);
	/*ADC_GetConversionValue---那这里,因为读取DR寄存器会自动清除EOC标志位
	所以这之后我们就不需要再手动清除标志位了
	*/	

}


uint16_t advalue;
float volatge;
int main(void)
{
	OLED_Init();
	AD_init();
	
	OLED_ShowString(1, 1, "ADValue:");
	OLED_ShowString(2, 1, "volatge:0.00V");
	
	
	while (1)
	{
		advalue=ad_getvalue();
		volatge=(float)advalue /4095 *3.3;
		OLED_ShowNum(1, 9, advalue, 4);
		OLED_ShowNum(2, 9, volatge, 1);
		OLED_ShowNum(2, 11, (uint16_t)(volatge * 100) % 100, 2);
		Delay_ms(100);

	}
}

        因为使用了连续模式 , 使用只有需要触发一次即可,  把//软件触发转换 ADC_SoftwareStartConvCmd(ADC1,ENABLE);移到 void AD_init函数下即可

        //获取标志位状态的while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);

在初始化完成之后,触发一次就行了 , 内部的ADC就会一次接着一次地、连续不断地 ,  对我们指定的通道0进行转换,转换结果放在数据寄存器里  ,  此时数据寄存器会不断地刷新最新的转换结果 ,使用在uint16_t ad_getvalue() 这里就不需要获取标志位状态的函数了

 B:AD多通道

 1:连接图  

 AO----模拟量的输出引脚

3个模块的AO,分别接在PA1、PA2和PA3口

DO-----数字输出

        AO是指传感器输出的模拟电信号:        可以是电压、电流等连续变化的信号,其数值与光照强度(或其他被测量的参数)相关。AO信号可以通过模数转换器(ADC)转换为数字信号,以供后续处理或控制使用。

        DO是指传感器输出的数字信号:        通常以逻辑电平(例如高电平或低电平)表示,表示光照强度(或其他被测量的参数)是否达到或超过设定的阈值。DO信号可以直接用于触发开关、报警或其他数字控制应用。

通过同时使用AO和DO,光敏传感器可以提供更丰富的信息输出,并满足不同应用场景的需求。

以前我们使用的都是DO,  这里我们使用的为A0

2:代码

使用: 单次非扫描的模式

        多通道  :  首先我们应该想到扫描的模式 , 启动一个组在组中填入我们要使用的通道,  但是由于覆盖的问题,要使用DMA(见下一节) ,所以没有使用扫描模式

        //选择AD转化器----我们选择规则组的输入通道
    ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5); 第二个参数就是我们的通道,  我们把通道作为参数, 放在组中的第一给序列中, 只需要在主函数中不断调用ad_getvalue函数即可

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

#include "AD.h"
void AD_init(void){
	//RCC开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//配置ADCCLK
	//APB2时钟72MHz时钟信号然后通过ADC预分频器进行分频,得到ADCCLK钟信号
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72Mhz/6=12Mhz
	
	//配置GPIO
	GPIO_InitTypeDef GPIO_initstruct;
	GPIO_initstruct.GPIO_Mode=GPIO_Mode_AIN;  //模拟输入,可以理解为ADC的专属模式
	GPIO_initstruct.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_initstruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_initstruct);
	
	 
	/*ADC_Channel_0  --通道o
	1----1~16的范围规则组第几个序列
	ADC_SampleTime_55Cycles5-----指定通道的采样时间
	*/
	
	//初始化ADC
	ADC_InitTypeDef ADC_initstruct;
	ADC_initstruct.ADC_ContinuousConvMode=DISABLE;//选择是连续转换还是单次转换---单次
	ADC_initstruct.ADC_DataAlign=ADC_DataAlign_Right; //数据对齐---右对齐
	ADC_initstruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//触发控制的触发源---不使用外部触发,使用内部软件触发
	ADC_initstruct.ADC_Mode=ADC_Mode_Independent;//ADC的工作模式---独立模式
	ADC_initstruct.ADC_NbrOfChannel=1;  //通道数目--指定在扫描模式下,总共会用到几个通道
	ADC_initstruct.ADC_ScanConvMode=DISABLE;//可以选择是扫描模式还是非扫描模式---非扫描模式
	ADC_Init(ADC1,&ADC_initstruct);

	//开启ADC
	ADC_Cmd(ADC1,ENABLE);
	
	//校准ADC
	
	//复位校准
	ADC_ResetCalibration(ADC1);//---把CR2_RSTCAL_Set这一位置一
	//等待复位校准完成--ADC_GetResetCalibrationStatus作用:返回复位校准的状态
	while (ADC_GetResetCalibrationStatus(ADC1)==SET);   //SET=1
	/*获取的是这个CR2_RSTCAL_Set的标志位 ,该位由软件设置并由硬件清除
	在校准寄存器被初始化后该位将被清除,所以该位的用法就是:
	你软件置该位为1,那硬件就会开始复位校准 , 当复位校准完成后,该位就会由硬件自动清0
	*/
	//开始校准
	ADC_StartCalibration(ADC1);
	//获取校准状态
	while(ADC_GetCalibrationStatus(ADC1)==SET);

}

uint16_t ad_getvalue(uint8_t ADC_Channel){
	//启动转换,获取结果
	
	//选择AD转化器----我们选择规则组的输入通道
	ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5); 
	
	//软件触发转换
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	//获取标志位状态的函数
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
	/*
	EOC是规则组或注入组完成时都会置1 , 0(RESET):转换未完成:
	1(SET):转换完成
	*/
	//ADC 获取转换值
	return ADC_GetConversionValue(ADC1);
	/*ADC_GetConversionValue---那这里,因为读取DR寄存器会自动清除EOC标志位
	所以这之后我们就不需要再手动清除标志位了
	
	*/
	


}



uint16_t AD1,AD2,AD3,AD4;
float volatge;
int main(void)
{
	OLED_Init();
	AD_init();
	
	OLED_ShowString(1, 1, "AD0:");
	OLED_ShowString(2, 1, "AD1:");
	OLED_ShowString(3, 1, "AD2:");
	OLED_ShowString(4, 1, "AD3:");	
	
	while (1)
	{
		
		AD1=ad_getvalue(ADC_Channel_0);
		AD2=ad_getvalue(ADC_Channel_1);
		AD3=ad_getvalue(ADC_Channel_2);
		AD4=ad_getvalue(ADC_Channel_3);

		OLED_ShowNum(1, 5, AD1, 4);
		OLED_ShowNum(2, 5, AD2, 4);
		OLED_ShowNum(3, 5, AD3, 4);
		OLED_ShowNum(4, 5, AD4, 4);
		Delay_ms(100);

	}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/100226.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

文章目录 0 简介1 二维码检测2 算法实现流程3 特征提取4 特征分类5 后处理6 代码实现5 最后 0 简介 🔥 优质竞赛项目系列,今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖,适合作为竞赛课…

【多线程案例】单例模式(懒汉模式和饿汉模式)

文章目录 1. 什么是单例模式?2. 立即加载/“饿汉模式”3. 延时加载/“懒汉模式”3.1 第一版3.2 第二版3.3 第三版3.4 第四版 1. 什么是单例模式? 提起单例模式,就必须介绍设计模式,而设计模式就是在软件设计中,针对特殊…

6路液体水位检测芯片VK36W6D SOP16 抗电源干扰及手机干扰特性好

产品品牌:永嘉微电/VINKA 产品型号:VK36W6D 封装形式:SOP16/QFN16L 详细资料:13.5/5.474/4.703 概述 VK36W6D具有6个触摸检测通道,可用来检测6个点的水位。该芯片具有较高的集成度,仅需极少的外部组件便…

一文了解tcp/ip协议的运行原理

接触代理ip的人都了解https/sock5等ip协议,那么TCP/IP 协议又是什么? 一、什么是TCP/IP 协议? TCP/IP 协议实际上是一系列网络通信协议的一个统称,他负责具体的数据传输工作,核心的两个协议包括TCP以及IP&#xff0c…

25.选择排序,归并排序,基数排序

目录 一. 选择排序 (1)简单选择排序 (2)堆排序 二. 归并排序 三. 基数排序 四. 各种排序方法的比较 (1)时间性能 (2)空间性能 (3)排序方法的稳定性能…

美创科技获通信网络安全服务能力评定(应急响应一级)认证!

近日,中国通信企业协会公布通信网络安全服务能力评定2023年第一批获证企业名单。 美创科技获得应急响应一级资质,成为2023年第一批获证企业之一! 通信网络安全服务能力评定是对通信网络安全服务单位从事通信网络安全服务综合能力的评定&#…

Revit SDK 介绍:CreateAirHandler 创建户式风管机

前言 这个例子介绍如何通过 API 创建一个户式风管机族的内容,包含几何和接头。 内容 效果 核心逻辑 必须打开机械设备的族模板创建几何实体来表示风管机创建风机的接头 创建几何实体来表示风管机 例子中创建了多个拉伸,下面仅截取一段代码&#xff…

python爬虫—requests

一、安装 pip install requests 二、基本使用 1、基本使用 类型 : models.Response r.text : 获取网站源码 r.encoding :访问或定制编码方式 r.url :获取请求的 url r.content :响应的字节类型 r.status_code :响应…

山西省文物局与大势智慧签订战略合作协议

8月24日,由山西省文物局、中国文物信息咨询中心(国家文物局数据中心)主办的数字文博发展论坛在太原举行。武汉大势智慧科技有限公司(后简称“大势智慧”)受邀参与,与来自国内文博数字化领域的专家学者齐聚一堂,围绕“数…

什么是同源策略(same-origin policy)?它对AJAX有什么影响?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 同源策略(Same-Origin Policy)与 AJAX 影响⭐ 同源策略的限制⭐ AJAX 请求受同源策略影响⭐ 跨域资源共享(CORS)⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记…

K 次取反后最大化的数组和【贪心算法】

1005 . K 次取反后最大化的数组和 给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组: 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后,返回数组 可能…

02_nodejs开发环境安装

02 【nodejs开发环境安装】 1.版本介绍 在命令窗口中输入 node -v 可以查看版本0.x 完全不技术 ES64.x 部分支持 ES6 特性5.x 部分支持ES6特性(比4.x多些),属于过渡产品,现在来说应该没有什么理由去用这个了6.x 支持98%的 ES6 特…

zabbix安装部署

前期准备:安装mysql数据库和nginx 一、下载zabbix rpm -Uvh https://repo.zabbix.com/zabbix/4.4/rhel/7/x86_64/zabbix-release-4.4-1.el7.noarch.rpm yum-config-manager --enable rhel-7-server-optional-rpms yum install epel-release numactl yum install…

Metasploit“MSF”连接postgresql时因排序规则版本不匹配导致无法连接

一、问题 更新Kali之后使用Metasploit时出现一个问题,连接postgresql时因排序规则版本不匹配导致无法连接 警告: database "msf" has a collation version mismatch DETAIL: The database was created using collation version 2.36, but the operati…

Linux操作系统中的信号剖析,

1、前言 信号是一种信息载体,在现实中,信号就是表示消息的物理量,比如说红绿灯,古时候狼烟等等,就拿红绿灯来说,为什人和车辆都是看到绿灯才会通行,红灯亮了就要停下来,因为这是现实…

Dolphin for Mac(Wii游戏模拟器)配置指南

Wii模拟器Dolphin Mac是款适合Mac电脑中的游戏玩家们使用的模拟器工具。Wii模拟器Dolphin Mac官方版支持直接运行游戏镜像文件,玩家可以将游戏ISO拷贝到某一个文件夹中统一进行管理。Wii模拟器Dolphin Mac除了键盘和鼠标外,还支持配合原版的Wii遥控器操作…

1、[春秋云镜]CVE-2022-32991

文章目录 一、相关信息二、解题思路(手注)三、通关思路(sqlmap) 一、相关信息 靶场提示:该CMS的welcome.php中存在SQL注入攻击。 NVD关于漏洞的描述: 注入点不仅在eid处!!&#xff…

Screaming Frog SEO Spider,为您的网站提供全方位的优化解决方案

Screaming Frog SEO Spider是一款适用于Mac的软件,它可以帮助用户分析网站的优化信息。该软件可以模拟蜘蛛爬行的方式,抓取网站的各种信息,并将这些信息整理成易于理解的报告。这些报告可以帮助用户评估网站的优化情况,发现链接的…

前端将UTC时间格式转化为本地时间格式~~uniapp写法

UTC时间格式是什么 首先我们先简单的了解一下:UTC时间(协调世界时,Coordinated Universal Time)使用24小时制,以小时、分钟、秒和毫秒来表示时间 HH:mm:ss.SSSHH 表示小时,取值范围为00到23。mm 表示分钟…

pip安装第三方库与设置

pip的使用 假如下载numpy pip install numpypypi 镜像源「配置」 常用镜像源列表 官方:https://pypi.org/simple 百度:https://mirror.baidu.com/pypi/simple/ 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里:https://m…