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//配置GPIOGPIO_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--通道o1----1~16的范围规则组第几个序列ADC_SampleTime_55Cycles5-----指定通道的采样时间*///初始化ADCADC_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);//开启ADCADC_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//配置GPIOGPIO_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  --通道o1----1~16的范围规则组第几个序列ADC_SampleTime_55Cycles5-----指定通道的采样时间*///初始化ADCADC_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);//开启ADCADC_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//配置GPIOGPIO_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  --通道o1----1~16的范围规则组第几个序列ADC_SampleTime_55Cycles5-----指定通道的采样时间*///初始化ADCADC_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);//开启ADCADC_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);}
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git小白入门——了解分布式版本管理和安装

Git是什么? Git是目前世界上最先进的分布式版本控制系统(没有之一) 什么是版本控制系统? 程序员开发过程中,对于每次开发对各种文件的修改、增加、删除,达到预期阶段的一个快照就叫做一个版本。 如果有一…

【OpenCV入门】第一部分——图像处理基础

本文结构 图像处理的基本操作读取图像imread() 显示图像imshow()waitKey()destroyAllWindows() 保存图像imwrite() 复制图像copy() 获取图像属性 像素确定像素的位置获取像素的BGR值修改像素的BGR值 色彩空间GRAY色彩空间cvtColor()——从BGR色彩空间转换到GRAY色彩空间 HSV色彩…

Lua学习(一)

lua基础学习 LUA 语言1. 什么是lua?1.1 准备工作 2. 基本语法2.1 注释2.2 标识符2.3 关键字2.4 全局变量 3. 数据类型4. 变量4.1 赋值语句 5. 循环5.1 while循环5.2 for循环5.3泛型for循环5.4 repeat until 循环5.5 break 语句 6. 流程控制6.1 if语句6.2 if else 语…

GNU make系列之介绍Makefile(0)

一.欢迎来到我的酒馆 在本章节介绍Makefile。 目录 一.欢迎来到我的酒馆二.GNU make 预览三.一个简单的Makefile四.make程序如何处理Makefile文件五.在Makefile中使用变量 二.GNU make 预览 2.1 GNU make工具会自动决定哪些程序需要被重新编译,并且执行相应的命令来…

reactantd(12)动态表单的默认值问题

最近遇到一个需求是有一个表单可以输入各种信息,然后还需要有一个编辑功能,点击编辑的时候需要把当前数据填入到表单里面。在网上查了很多种方法,然后我的思路是使用initialValues搭配setState()使用。默认值都为空,然后点击单条数…

从零开始学习 Java:简单易懂的入门指南之查找算法及排序算法(二十)

查找算法及排序算法 常见的七种查找算法:1. 基本查找2. 二分查找3. 插值查找4. 斐波那契查找5. 分块查找6. 哈希查找7. 树表查找 四种排序算法:1. 冒泡排序1.1 算法步骤1.2 动图演示1.3 代码示例 2. 选择排序2.1 算法步骤2.2 动图演示 3. 插入排序3.1 算…

knife4j 整合 springboot

官方文档:https://doc.xiaominfo.com/knife4j 版本兼容说明:https://doc.xiaominfo.com/docs/quick-start/start-knife4j-version 升级说明:https://doc.xiaominfo.com/docs/upgrading/upgrading-to-v4版本兼容惯关系: springboot…

MySQL一行记录是如何存储的?

目录 MySQL的数据存放在哪个文件? 表空间文件的结构是怎么样的? 1、行(row) 2、页(page) 3、区(extent) 4、段(segment) InnoDB 行格式有哪些&#xf…

解读亚马逊云科技语义搜图检索方案

图像检索(包括文搜图和图搜图)是各个行业中常见的一个应用场景。比如在电商场景中,基于以图搜图做相似商品查找;在云相册场景中,基于文搜图来找寻所需的图像素材。 传统基于标签的图像检索方式,即先使用目标…

博流RISC-V芯片Eclipse环境搭建

文章目录 1、下载 Eclipse2、导入 bouffalo_sdk3、编译4、烧录5、使用ninja编译 之前编译是通过 VSCode 编译,通过手工输入 make 命令编译,我们也可以通过 Eclipse 可视化 IDE 来编译、烧录。 1、下载 Eclipse 至 Eclipse 官网 https://www.eclipse.org…

【微服务部署】02-配置管理

文章目录 1.ConfigMap1.1 创建ConfigMap方式1.2 使用ConfigMap的方式1.3 ConfigMap使用要点建议 2 分布式配置中心解决方案2.1 什么时候选择配置中心2.2 Apollo配置中心系统的能力2.2.1 Apollo创建配置项目2.2.2 项目使用2.2.3 K8s中使用Apollo 1.ConfigMap ConfigMap是K8s提供…

【第1章 数据结构概述】

目录 一. 基本概念 1. 数据、数据元素、数据对象 2. 数据结构 二. 数据结构的分类 1. 数据的逻辑结构可分为两大类:a. 线性结构;b. 非线性结构 2. 数据的存储结构取决于四种基本的存储方法:顺序存储、链接存储、索引存储、散列存储 3. …

iMX6ULL 库移植 | Libgpiod 库的交叉编译及使用指南(linux)

GPIO口的操作,是很常见的功能。传统的GPIO sysfs接口已被弃用。自Linux 4.8起,内核提供了全新的操作gpio的方式libgpiod(C library and tools for interacting with the linux GPIO character device),当然也更高效&am…

大数据Flink简介与架构剖析并搭建基础运行环境

文章目录 前言Flink 简介Flink 集群剖析Flink应用场景Flink基础运行环境搭建Docker安装docker-compose文件编写创建并运行容器访问Flink web界面 前言 前面我们分别介绍了大数据计算框架Hadoop与Spark,虽然他们有的有着良好的分布式文件系统和分布式计算引擎,有的有…

电脑识别不了固态硬盘怎么办?

在使用固态硬盘时,可能会出现电脑无法识别的情况,这时我们就无法使用固态硬盘中的数据。那么,电脑识别不了固态硬盘怎么办? 为什么电脑识别不了固态硬盘? 一般来说,电脑识别不了固态硬盘是因为以下3个原因…

软件工程(八) UML之类图与对象图

1、类图与对象图 1.1、类图与对象图的概念 类图(class diagram)描述一组类、接口、协作和它们之间的关系 对象图(object diagram)描述一组对象及它们之间的关系、对象图描述了在类图中所建立的事物实例的静态快照。 1.2、类图与对象图的区别 类图和对象图基本上是一样…

Python Opencv实践 - Canny边缘检测

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_GRAYSCALE) print(img.shape)#图像Canny边缘检测 #cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradien…

python web 开发与 Node.js + Express 创建web服务器入门

目录 1. Node.js Express 框架简介 2 Node.js Express 和 Python 创建web服务器的对比 3 使用 Node.js Express 创建web服务器示例 3.1 Node.js Express 下载安装 3.2 使用Node.js Express 创建 web服务器流程 1. Node.js Express 框架简介 Node.js Express 是一种…

Spring boot中调用C/C++(dll)

添加JNA依赖 <dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>5.5.0</version> </dependency>准备C代码/C代码 如下是C代码&#xff0c;文件名&#xff1a;xizi.c #include <std…

电子电路原理题目整理(1)

电子电路原理题目整理&#xff08;1&#xff09; 最近在学习《电子电路原理》&#xff0c;记录一下书后面试题目&#xff0c;答案为个人总结&#xff0c;欢迎讨论。 1.电压源和电流源的区别&#xff1f; 电压源在不同的负载电阻下可提供恒定的负载电压&#xff0c;而电流源对于…