adc采集_adc采集电压 - CSDN
精华内容
参与话题
  • ADC数据采集

    2020-03-21 18:29:41
    MCU的采集精度是12位,有多种参考源,分别是:AVCC电压,ExRef引脚,内置1.5V电压,内置2.5V参考电压, 加入设置成第一种AVCC电压,那么传感器所放大的电压值就不能超过AVCC电压,按照12精度换算则是4096 / AVCC *...

    MCU的采集精度是12位,有多种参考源,分别是:AVCC电压,ExRef引脚,内置1.5V电压,内置2.5V参考电压,

    加入设置成第一种AVCC电压,那么传感器所放大的电压值就不能超过AVCC电压,按照12精度换算则是4096 / AVCC * 转换的量程最大电压值 = AD值(软件读到的寄存器值)

    如果是参考的内部电压,同样传感器的输出电压值放大后电压不能超过内部电压值,否则要做分压检测处理,

    未完,待续。。。

    展开全文
  • ADC采集方法

    千次阅读 2019-08-09 18:29:15
    /*************************************************************************** *File: ADC.c Description: Interface driver for the 500 Series Z-Wave Single Chip built-in ADC sample data Aut...

    /***************************************************************************
    *File: ADC.c

    • Description: Interface driver for the 500 Series Z-Wave Single Chip
    •          built-in ADC sample data
      
    • Author: pandy
    • Revision: V1.0
    • Date: 2018-5-22

    ****************************************************************************/
    #include <ZW_typedefs.h>
    #include “zw050X.h”
    #include <INTRINS.H>
    #include “ZW_appltimer_api.h”
    /IO control/
    #include <ZW_pindefs.h>
    #include <ZW_evaldefs.h>
    #include “zw_uart_api.h”
    #include “ISD51.h”
    #include “zw_timer_api.h”
    #include “zw_adcdriv_api.h”
    #include “eeprom.h”

    #define Vbg 1230
    #define batterLowWarningValue 2750
    #define ZW_DEBUG_ADC_MON 0xff
    /-------------------------private data-----------------------/
    #ifdef ZW_DEBUG_ADC_MON
    #define ZW_DEBUG_BATT_ADC_SEND_BYTE(data) ZW_DEBUG_SEND_BYTE(data)
    #define ZW_DEBUG_BATT_ADC_SEND_STR(STR) ZW_DEBUG_SEND_STR(STR)
    #define ZW_DEBUG_BATT_ADC_SEND_NUM(data) ZW_DEBUG_SEND_NUM(data)
    #define ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(data) ZW_DEBUG_SEND_WORD_NUM(data)
    #define ZW_DEBUG_BATT_ADC_SEND_NL() ZW_DEBUG_SEND_NL()
    #else
    #define ZW_DEBUG_BATT_ADC_SEND_BYTE(data)
    #define ZW_DEBUG_BATT_ADC_SEND_STR(STR)
    #define ZW_DEBUG_BATT_ADC_SEND_NUM(data)
    #define ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(data)
    #define ZW_DEBUG_BATT_ADC_SEND_NL()
    #endif

    WORD adc_value=0;
    static WORD battLevel;
    WORD SumBatt;
    static WORD battVol;
    static BYTE battState;
    BOOL startBatteryVoltageMeasurement=TRUE;
    BOOL awatingBatteryVoltageMeasurement=TRUE;
    BYTE getBattPercent; //µç³Ø°Ù·Ö±È
    WORD tempVal,getAdcValue=0xffff;
    extern XBYTE battValve;
    void ADC_Init()
    {
    // Set ADC to battery monitoring mode, other parameters are ignored ADC_BATT_MULTI_MODE ADC_BATT_SINGLE_MODE
    ZW_ADC_init(ADC_BATT_MULTI_MODE, ADC_REF_U_VDD, ADC_REF_L_VSS, 0);
    // Set auto zero period
    ZW_ADC_auto_zero_set(ADC_AZPL_128);
    // Set ADC resolution
    ZW_ADC_resolution_set(ADC_12_BIT);

    }
    /*================================================================*/
    /16ת»»10½øÖÆ/
    WORD decChangeOc(WORD inputDigit)
    {
    WORD re=0;//
    WORD n=1;//
    while(inputDigit!=0)
    {
    re += (inputDigit%10)*n;
    inputDigit /= 10;
    n *= 16;
    }
    return re;
    }

    /*=ADC_actor===============/
    /adc start sample/
    void ADC_actor(BOOL bState,BOOL pSample)
    {
    WORD tempVal;
    if (bStatestartBatteryVoltageMeasurement)
    {
    // Power up ADC
    ZW_ADC_power_enable(TRUE);
    // Start ADC
    ZW_ADC_enable(TRUE);
    // battState=awatingBatteryVoltageMeasurement;
    }
    if(pSample
    awatingBatteryVoltageMeasurement)
    {
    do{battLevel=ZW_ADC_result_get();}
    while ( battLevel == ADC_NOT_FINISHED );
    // battLevel=ZW_ADC_result_get();
    ZW_DEBUG_BATT_ADC_SEND_STR("\r\n----battLevel= ");
    ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(battLevel);
    // if((battLevel!= ADC_NOT_FINISHED))
    {
    // Calc battery level in mV (Vbg is the band gab voltage)
    battVol=(DWORD)Vbg
    4096/(DWORD)battLevel; // Return battery voltage in mV
    ZW_DEBUG_BATT_ADC_SEND_STR("\r\n----adc volage= ");
    ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(decChangeOc(battVol));
    if(battVol>=3000)
    {
    getBattPercent=100;
    }
    if((battVol>batterLowWarningValue)&&(battVol<2998))
    {

    			tempVal=((battVol-batterLowWarningValue));//3000-2750=250
    			getBattPercent=(BYTE)(tempVal*0.4);//100/250=0.25
    		}
    		 if(battVol<=batterLowWarningValue)
    		{
    		
    		  getBattPercent=0xff;
    		}
    		MemoryPutByte((WORD)&EEOFFSET_BATTER_far,getBattPercent);//batterlevel saves eeprom
    		ZW_DEBUG_BATT_ADC_SEND_STR("\r\n----getBattPercent= ");
    		ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(getBattPercent);
    		ZW_DEBUG_BATT_ADC_SEND_STR("\r\n");
    		// Power down ADC
    		ZW_ADC_power_enable(FALSE); 
    	}
    }
    

    }
    /*=ADC_Get===============*/
    /adc sample/
    void ADC_Get()
    {
    BYTE i,j,z;
    BYTE Max = 1,Min = 1;
    WORD Adc_Buf[11];

    	// Power up ADC
    	ZW_ADC_power_enable(TRUE);
    	// Start ADC
    	ZW_ADC_enable(TRUE);
      for(z=0;z<200;z++);
    	for(i=0;i<11;i++)//»ñÈ¡5 ADCÖµ
    	{
    	getAdcValue=ZW_ADC_result_get();
    	if((getAdcValue!= ADC_NOT_FINISHED))
    	{
    

    // ZW_DEBUG_BATT_ADC_SEND_STR("\r\n—ii= ");
    // ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(i);

    	 Adc_Buf[i] = getAdcValue;
    	 ZW_DEBUG_BATT_ADC_SEND_STR("\r\n---getAdcValue= ");
    	 ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(getAdcValue);	
    	// Power down ADC
    

    // ZW_ADC_power_enable(FALSE);
    }

    	}
    	for(j=1;j<11;j++)
    	{
    		if(Adc_Buf[Max] < Adc_Buf[j])
    		{
    		  Max = j;
    		}
    		if(Adc_Buf[Min] > Adc_Buf[j])
    		{
    		  Min = j;
    		}
    		SumBatt +=Adc_Buf[j];
    	ZW_DEBUG_BATT_ADC_SEND_STR("\r\n----SumBatt= ");
    	ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(SumBatt);
    	}
    

    // battLevel=(SumBatt-Adc_Buf[Max]-Adc_Buf[Min]);
    battLevel=SumBatt/10;

    	ZW_DEBUG_BATT_ADC_SEND_STR("\r\n----battLevel= ");
    	ZW_DEBUG_BATT_ADC_SEND_WORD_NUM(battLevel);
    
    	// Calc battery level in mV (Vbg is the band gab voltage)
    	battVol=(DWORD)Vbg*4096/(DWORD)battLevel;	// Return battery voltage in mV		
    	ZW_DEBUG_SEND_STR("\r\n-adc volage=");
    	ZW_DEBUG_SEND_WORD_NUM(decChangeOc(battVol));
    	if(battVol>=3000)
    	{
    	 getBattPercent=100;
    	}
    	 if((battVol>batterLowWarningValue)&&(battVol<2998))
    	{ 
    		
    		tempVal=((battVol-batterLowWarningValue));//3000-2750=250
    		getBattPercent=(BYTE)(tempVal*0.4);//100/250=0.25
    	}
    	 if(battVol<=batterLowWarningValue)
    	{
    	
    		getBattPercent=0xff;
    	}
    	battValve=getBattPercent;
    

    // MemoryPutByte((WORD)&EEOFFSET_BATTER_far,getBattPercent);//batterlevel saves eeprom
    ZW_DEBUG_SEND_STR("\r\n-getBattPercent=");
    ZW_DEBUG_SEND_WORD_NUM(getBattPercent);
    ZW_DEBUG_SEND_STR("\r\n");
    // Power down ADC
    // ZW_ADC_power_enable(FALSE);
    // ZW_ADC_enable(FALSE);

    }
    

    //--------------------------------------------------------------------------
    //È¥µô×î´óÖµ×îСֵÔÙƽ¾ù
    WORD AdcSmpAvg(WORD getADC)
    {
    DWORD ADCData;
    BYTE i;
    BYTE Max = 0,Min = 0;
    WORD Adc_Buf[10];
    ADCData = getADC;
    for(i=0;i<10;i++)
    {
    Adc_Buf[i] = 0;
    }
    for(i=0;i<10;i++)
    {
    if(Adc_Buf[Max] < Adc_Buf[i])
    {
    Max = i;
    }

            if(Adc_Buf[Min] > Adc_Buf[i])
            {
                Min = i;
            }
            ADCData +=Adc_Buf[i];
        }
    ADCData=(ADCData-Adc_Buf[Max]-Adc_Buf[Min])/8;
    return (WORD)ADCData;
    

    }
    //----------------------------------------------------------------------------
    /------------------------------------------------------
    **parameter: Null
    ** return£º µçÁ¿°Ù·Ö±È
    ------------------------------------------------------
    /

    BYTE getBatteryValue()
    {
    // battValve=MemoryGetByte((WORD)&EEOFFSET_BATTER_far);//getBattPercent;
    // battValve=getBattPercent;
    return (battValve);

    }

    /------------------------------------------------------
    **parameter: benble------TRUE STOP
    ** FALSE …
    ------------------------------------------------------
    /
    void ADC_Stop()
    {

    ZW_ADC_enable(FALSE);
    }

    /****************************************************************
    **File: adc.h
    **auther:pandy
    **date: 2018-3-14
    **chagne:
    ******************************************************************/
    #ifndef _ADC__H
    #define _ADC__H

    void ADC_Init();
    void ADC_actor(BOOL bState,BOOL pSample);
    BYTE getBatteryValue();
    void ADC_Get();

    #endif

    展开全文
  • 此STM32单片机为STM32F103系列的 ...1、使用定时器中断每隔一定时间进行ADC转换,这样每次都必须读ADC的数据寄存器,非常浪费时间! 2、把ADC设置成连续转换模式,同时对应的DMA通道开启循环模式,这样A...

    此STM32单片机为STM32F103系列的

    STM32的ADC有DMA功能这都毋庸置疑,也是我们用的最多的!然而,如果我们要对一个信号(比如脉搏信号)进行定时采样(也就是隔一段时间,比如说2ms),有三种方法:

     

    一文带你看懂Stm32定时器+ADC+DMA进行AD采样的实现

    1、使用定时器中断每隔一定时间进行ADC转换,这样每次都必须读ADC的数据寄存器,非常浪费时间!

    2、把ADC设置成连续转换模式,同时对应的DMA通道开启循环模式,这样ADC就一直在进行数据采集然后通过DMA把数据搬运至内存。但是这样做的话还得加一个定时中断,用来定时读取内存中的数据!

    3、使用ADC的定时器触发ADC转换的功能,然后使用DMA进行数据的搬运!这样只要设置好定时器的触发间隔,就能实现ADC定时采样转换的功能,然后可以在程序的死循环中一直检测DMA转换完成标志,然后进行数据的读取,或者使能DMA转换完成中断,这样每次转换完成就会产生中断,我是采用第二种方法。下面上代码:我这里使用的单通道

    //定时器初始化

    voidTIM2_ConfiguraTIon(void)

    {

    TIM_TImeBaseInitTypeDefTIM_TimeBaseStructure;

    TIM_OCInitTypeDefTIM_OCInitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

    TIM_TimeBaseStructure.TIM_Period=1999;//设置2ms一次TIM2比较的周期

    TIM_TimeBaseStructure.TIM_Prescaler=71;//系统主频72M,这里分频71,相当于1000K的定时器2时钟

    TIM_TimeBaseStructure.TIM_ClockDivision=0x0;

    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

    TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//下面详细说明

    TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//TIM_OutputState_Disable;

    TIM_OCInitStructure.TIM_Pulse=1000;

    TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//如果是PWM1要为Low,PWM2则为High

    TIM_OC2Init(TIM2,&TIM_OCInitStructure);

    //TIM_InternalClockConfig(TIM2);

    //TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);

    //TIM_UpdateDisableConfig(TIM2,DISABLE);

    }

    //ADC_DMA初始化配置

    voidADC_DMA_Config(void)

    {

    DMA_InitTypeDefDMA_InitStructure;//注:ADC为12位模数转换器,只有ADCConvertedValue的低12位有效

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//使能DMA时钟

    DMA_DeInit(DMA1_Channel1);//开启DMA1的第一通道

    DMA_InitStructure.DMA_PeripheralBaseAddr=ADC1_DR_Address;//DMA对应的外设基地址

    DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)&ADCConvertedValue;//内存存储基地址

    DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//DMA的转换模式为SRC模式,由外设搬移到内存

    DMA_InitStructure.DMA_BufferSize=1;//DMA缓存大小,1个

    DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//接收一次数据后,设备地址禁止后移

    DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Disable;//关闭接收一次数据后,目标内存地址后移

    DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度为16位

    DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//DMA搬移数据尺寸,HalfWord就是为16位

    DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//循环转换模式

    DMA_InitStructure.DMA_Priority=DMA_Priority_High;//DMA优先级高

    DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//M2M模式禁用

    DMA_Init(DMA1_Channel1,&DMA_InitStructure);

    DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);//使能传输完成中断

    }

    //ADC初始化

    voidPulseSenosrInit(void)

    {

    //当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换

    ADC_InitTypeDefADC_InitStructure;

    ADC_GPIO_Configuration();//IO口配置

    TIM2_Configuration();//定时器配置

    ADC_DMA_Config();//ADC_DMA配置

    ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立的转换模式ADC_DUALMOD[3:0]=0000;

    ADC_InitStructure.ADC_ScanConvMode=DISABLE;//关闭扫描模式因为只有一个通道

    ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//关闭连续转换模式否则只要触发一次,

    //后续的转换就会永不停歇(除非CONT清0),这样第一次以后的ADC,就不是由TIM2_CC2来触发了

    ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T2_CC2;//软件转换模式

    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//对齐方式,ADC为12位中,右对齐方式ADC_ALIGN=0;

    ADC_InitStructure.ADC_NbrOfChannel=1;//开启通道数,1个ADC_SQR1[23:20]=0000;

    //ADC_SQR1[23:20]设置通道数目的选择

    ADC_Init(ADC1,&ADC_InitStructure);

    //RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置时钟(12MHz),在RCC里面还应配置APB2=AHB时钟72MHz

    ADC_RegularChannelConfig(ADC1,ADC_Channel_2,1,ADC_SampleTime_1Cycles5);

    //ADC_SMPR2ADC_SMPR1设置每个通道的采样时间

    //ADC_SQR1[19:0]DC_SQR1[29:0]DC_SQR3[29:0]设置对应通道的转换顺序适用于多通道采样

    //ADC通道组,第3个通道采样顺序1,转换时间

    ADC_ExternalTrigConvCmd(ADC1,ENABLE);//设置外部触发模式使能(这个“外部“其实仅仅是相//对于ADC模块的外部,

    ADC_DMACmd(ADC1,ENABLE);

    ADC_Cmd(ADC1,ENABLE);//ADC命令,使能ADC_ADON=1

    ADC_ResetCalibration(ADC1);//重新校准

    while(ADC_GetResetCalibrationStatus(ADC1));//等待重新校准完成

    ADC_StartCalibration(ADC1);//开始校准ADC_RSTCAL=1;初始化校准寄存器

    while(ADC_GetCalibrationStatus(ADC1));//等待校准完成ADC_CAL=0;

    //ADC_SoftwareStartConvCmd(ADC1,ENABLE);//连续转换开始,ADC通过DMA方式不断的更新RAM区。

    //ADC_SWSTART=1开始规则转换切记软件触发也属于外部事件要设置ADC_EXTTRIG=1

    //实际上还是在STM32内部)

    TIM_Cmd(TIM2,ENABLE);//最后面打开定时器使能

    DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA

    }

    //中断处理函数

    voidDMA1_Channel1_IRQHandler(void)

    {

    if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET){

    //自己的中断处理代码但是记住程序不要太复杂最好不要超过中断时间

    DMA_ClearITPendingBit(DMA1_IT_TC1);

    }

    }

    //中断配置

    NVIC_InitTypeDefNVIC_InitStructure;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel1_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;

    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    voidADC_GPIO_Configuration(void)//ADC配置函数

    {

    GPIO_InitTypeDefGPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA,ENABLE);//使能ADC和GPIOA时钟

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;//管脚2

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入模式

    GPIO_Init(GPIOA,&GPIO_InitStructure);//GPIO组

    }

    展开全文
  • stm32学习笔记---ADC电压采集

    万次阅读 多人点赞 2018-09-12 22:09:58
    ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由 VREF-、VREF+ 、VDDA 、VSSA、这四个外部 引脚决定。 我们在设计原理图的时候一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,得到 ADC 的输入电压范围为:0~3.3V。 ...

     1.  ①电压输入范围
    ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由 VREF-、VREF+ 、VDDA 、VSSA、这四个外部
    引脚决定。
    我们在设计原理图的时候一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,得到
    ADC 的输入电压范围为:0~3.3V。
    如果我们想让输入的电压范围变宽,去到可以测试负电压或者更高的正电压,我们可
    以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到 0~3.3V,这样 ADC 就
    可以测量了。
    2.  ②输入通道
    我们确定好 ADC 输入电压之后,那么电压怎么输入到 ADC?这里我们引入通道的概念,
    STM32 的 ADC 多达 18 个通道,其中外部的 16 个通道就是框图中的 ADCx_IN0 、
    ADCx_IN1...ADCx_IN5。这 16 个通道对应着不同的 IO 口,具体是哪一个 IO 口可以从手
    册查询到。其中 ADC1/2/3 还有内部通道:ADC1 的通道 16 连接到了芯片内部的温度传感
    器,Vrefint 连接到了通道 17。ADC2 的模拟通道 16 和 17 连接到了内部的 VSS。
    ADC3 的模拟通道 9、14、15、16 和 17 连接到了内部的 VSS。

    外部的 16 个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有 16
    路,注入通道最多有 4 路。那这两个通道有什么区别?在什么时候使用?
    规则通道
    规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通
    道,或者应该说我们用到的都是这个通道,没有什么特别要注意的可讲。

    注入通道
    注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转
    换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就
    要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断
    程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。
    3.  ③转换顺序
    规则序列
    规则序列寄存器有 3 个,分别为 SQR3、SQR2、SQR1。SQR3 控制着规则序列中的第
    一个到第六个转换,对应的位为:SQ1[4:0]~SQ6[4:0],第一次转换的是位 4:0 SQ1[4:0],如
    果通道 16 想第一次转换,那么在 SQ1[4:0]写 16 即可。SQR2 控制着规则序列中的第 7 到第
    12 个转换,对应的位为:SQ7[4:0]~SQ12[4:0],如果通道 1 想第 8 个转换,则 SQ8[4:0]写 1
    即可。SQR1 控制着规则序列中的第 13 到第 16 个转换,对应位为:SQ13[4:0]~SQ16[4:0],
    如果通道 6 想第 10 个转换,则 SQ10[4:0]写 6 即可。具体使用多少个通道,由 SQR1 的位
    L[3:0]决定,最多 16 个通道。

    注入序列
    注入序列寄存器 JSQR 只有一个,最多支持 4 个通道,具体多少个由 JSQR 的 JL[2:0]
    决定。如果 JL 的  值小于 4 的话,则 JSQR 跟 SQR 决定转换顺序的设置不一样,第一次转
    换的不是 JSQR1[4:0],而是 JCQRx[4:0] ,x = (4-JL),跟 SQR 刚好相反。如果 JL=00(1

    个转换),那么转换的顺序是从 JSQR4[4:0]开始,而不是从 JSQR1[4:0]开始,这个要注意,
    编程的时候不要搞错。当 JL 等于 4 时,跟 SQR 一样。

    4.  ④触发源
    通道选好了,转换的顺序也设置好了,那接下来就该开始转换了。ADC 转换可以由
    ADC 控制寄存器 2:  ADC_CR2 的 ADON 这个位来控制,写 1 的时候开始转换,写 0 的时候
    停止转换,这个是最简单也是最好理解的开启 ADC 转换的控制方式,理解起来没啥技术含
    量。
    除了这种庶民式的控制方法,ADC 还支持触发转换,这个触发包括内部定时器触发和
    外部 IO 触发。触发源有很多,具体选择哪一种触发源,由 ADC 控制寄存器 2:ADC_CR2 的
    EXTSEL[2:0] 和 JEXTSEL[2:0] 位 来控制 。 EXTSEL[2:0] 用于 选择 规则 通道 的触发源,
    JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后,触发源是否要激活,则由
    ADC 控制寄存器 2:ADC_CR2 的 EXTTRIG 和 JEXTTRIG 这两位来激活。其中 ADC3 的规则
    转换和注入转换的触发源与 ADC1/2 的有所不同,在框图上已经表示出来。
    5.  ⑤转换时间
    ADC 时钟
    ADC 输入时钟 ADC_CLK 由 PCLK2 经过分频产生,最大是 14M,分频因子由 RCC 时
    钟配置寄存器 RCC_CFGR 的位 15:14   ADCPRE[1:0]设置,可以是 2/4/6/8 分频,注意这里
    没有 1 分频。一般我们设置 PCLK2=HCLK=72M。
    采样时间
    ADC 使用若干个 ADC_CLK 周期对输入的电压进行采样,采样的周期数可通过 ADC 
    采样时间寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位设置,ADC_SMPR2 控制
    的是通道 0~9,ADC_SMPR1 控制的是通道 10~17。每个通道可以分别用不同的时间采样。
    其中采样周期最小是 1.5 个,即如果我们要达到最快的采样,那么应该设置采样周期为 1.5
    个周期,这里说的周期就是 1/ADC_CLK。

    ADC 的转换时间跟 ADC 的输入时钟和采样时间有关,公式为:Tconv  =  采样时间  + 
    12.5 个周期。当 ADCLK  =  14MHZ  (最高),采样时间设置为 1.5 周期(最快),那么总
    的转换时间(最短)Tconv = 1.5 周期 + 12.5 周期 = 14 周期 = 1us。
    一般我们设置 PCLK2=72M,经过 ADC 预分频器能分频到最大的时钟只能是 12M,采
    样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us,这个才是最常用的。
    6.  ⑥数据寄存器
    一切准备就绪后,ADC 转换后的数据根据转换组的不同,规则组的数据放在 ADC_DR
    寄存器,注入组的数据放在 JDRx。
    规则数据寄存器
    ADC 规则组数据寄存器 ADC_DR 只有一个,是一个 32 位的寄存器,低 16 位在单 ADC
    时使用,高 16 位是在 ADC1 中双模式下保存 ADC2 转换的规则数据,双模式就是 ADC1 和
    ADC2 同时使用。在单模式下,ADC1/2/3 都不使用高 16 位。因为 ADC 的精度是 12 位,
    无论 ADC_DR 的高 16 或者低 16 位都放不满,只能左对齐或者右对齐,具体是以哪一种方
    式存放,由 ADC_CR2 的 11 位 ALIGN 设置。
    规则通道可以有 16 个这么多,可规则数据寄存器只有一个,如果使用多通道转换,那
    转换的数据就全部都挤在了 DR 里面,前一个时间点转换的通道数据,就会被下一个时间
    点的另外一个通道转换的数据覆盖掉,所以当通道转换完成后就应该把数据取走,或者开
    启 DMA 模式,把数据传输到内存里面,不然就会造成数据的覆盖。最常用的做法就是开
    启 DMA 传输。
    注入数据寄存器
    ADC 注入组最多有 4 个通道,刚好注入数据寄存器也有 4 个,每个通道对应着自己的
    寄存器,不会跟规则寄存器那样产生数据覆盖的问题。ADC_JDRx 是 32 位的,低 16 位有
    效,高 16 位保留,数据同样分为左对齐和右对齐,具体是以哪一种方式存放,由
    ADC_CR2 的 11 位 ALIGN 设置。
    7.  ⑦中断
    转换结束中断
    数据转换结束后,可以产生中断,中断分为三种:规则通道转换结束中断,注入转换
    通道转换结束中断,模拟看门狗中断。其中转换结束中断很好理解,跟我们平时接触的中
    断一样,有相应的中断标志位和中断使能位,我们还可以根据中断类型写相应配套的中断
    服务程序。
    模拟看门狗中断
    当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是我
    们开启了模拟看门狗中断,其中低阈值和高阈值由 ADC_LTR 和 ADC_HTR 设置。例如我

    们设置高阈值是 2.5V,那么模拟电压超过 2.5V 的时候,就会产生模拟看门狗中断,反之
    低阈值也一样。
    DMA 请求
    规则和注入通道转换结束后,除了产生中断外,还可以产生 DMA 请求,把转换好的
    数据直接存储在内存里面。要注意的是只有 ADC1 和 ADC3 可以产生 DMA 请求。有关
    DMA 请求需要配合《STM32F10X-中文参考手册》DMA 控制器这一章节来学习。一般我
    们在使用 ADC 的时候都会开启 DMA 传输。
    8.  ⑧电压转换
    模拟电压经过 ADC 转换后,是一个 12 位的数字值,如果通过串口以 16 进制打印出来
    的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟实际
    的模拟电压(用万用表测)对比,看看转换是否准确。
    我们一般在设计原理图的时候会把 ADC 的输入电压范围设定在:0~3.3v,因为 ADC
    是 12 位的,那么 12 位满量程对应的就是 3.3V,12 位满量程对应的数字值是:2^12。数值
    0 对应的就是 0V。如果转换后的数值为  X ,X 对应的模拟电压为 Y,那么会有这么一个等
    式成立:  2^12 / 3.3 = X / Y,=> Y = (3.3 * X ) / 2^12。

     

    31.4  独立模式单通道采集实验

    #include "bsp_adc.h"
    
    static void ADCx_GPIO_Config(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	
    	// 打开 ADC IO端口时钟
    	ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE );
    	
    	// 配置 ADC IO 引脚模式
    	// 必须为模拟输入
    	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    	
    	// 初始化 ADC IO
    	GPIO_Init(ADC_PORT, &GPIO_InitStructure);	
    }
    
    static void ADCx_Mode_Config(void)
    {
    	ADC_InitTypeDef ADC_InitStruct;
    	
    	ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
    	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
    	ADC_InitStruct.ADC_ScanConvMode = DISABLE;
    	ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;	
    	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
    	ADC_InitStruct.ADC_NbrOfChannel = 1;
    	
    	ADC_Init(ADC_x, &ADC_InitStruct);
    	
    	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
    	ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
    	
    	ADC_ITConfig(ADC_x, ADC_IT_EOC, ENABLE);
    	ADC_Cmd(ADC_x, ENABLE);
    	
      // ADC开始校准
    	ADC_StartCalibration(ADC_x);
    	// 等待校准完成
    	while(ADC_GetCalibrationStatus(ADC_x));
    	
    	ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
    }
    
    static void ADC_NVIC_Config(void)
    {
      NVIC_InitTypeDef NVIC_InitStructure;
    	// 优先级分组
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    
      // 配置中断优先级
      NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
    }
    
    void ADCx_Init(void)
    {
    	ADC_NVIC_Config();
    	ADCx_GPIO_Config();
    	ADCx_Mode_Config();
    }
    
    /**
      ******************************************************************************
      * @file    main.c
      * @author  fire
      * @version V1.0
      * @date    2013-xx-xx
      * @brief   串口中断接收测试
      ******************************************************************************
      * @attention
      *
      * 实验平台:秉火 F103-霸道 STM32 开发板 
      * 论坛    :http://www.firebbs.cn
      * 淘宝    :http://firestm32.taobao.com
      *
      ******************************************************************************
      */ 
     
     
    #include "stm32f10x.h"
    #include "bsp_usart.h"
    #include "bsp_adc.h"
    
    
    extern __IO uint16_t ADC_ConvertedValue;
    
    // 局部变量,用于保存转换计算后的电压值 	 
    float ADC_ConvertedValueLocal;        
    
    // 软件延时
    void Delay(__IO uint32_t nCount)
    {
      for(; nCount != 0; nCount--);
    } 
    
    /**
      * @brief  主函数
      * @param  无
      * @retval 无
      */
    int main(void)
    {	
      /*初始化USART 配置模式为 115200 8-N-1,中断接收*/
      USART_Config();
    	printf("欢迎使用秉火STM32开发板\n\n\n\n");
    	
    	ADCx_Init();
    	
      while(1)
    	{	
    		ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3; 
    	
    		printf("\r\n The current AD value = 0x%04X \r\n",ADC_ConvertedValue); 
    		printf("\r\n The current AD value = %f V \r\n",ADC_ConvertedValueLocal); 
    		printf("\r\n\r\n");
    
    		Delay(0xffffee); 
    	}	
    }
    
    // 作业
    
    // 1-把程序改成 ADC1/3
    // 2-换成其他的通道试一试
    
    
    
    
    
    
    
    
    
    
    
    /*********************************************END OF FILE**********************/
    
    void ADC_IRQHandler(void)
    {
    	if( ADC_GetITStatus(ADC_x, ADC_IT_EOC) == SET)
      {
    		ADC_ConvertedValue = ADC_GetConversionValue(ADC_x);
    	}
    	ADC_ClearITPendingBit(ADC_x, ADC_IT_EOC);
    }

     

     

     

    展开全文
  • ADC信息采集

    千次阅读 2016-12-23 20:45:07
    前言前面介绍了ADC,今天通过实例来讲解ADC的使用ADC的初始化通过代码讲解void ADCinit() { /*清除ADC数据寄存器*/ ADCH&=0x00; ADCL&=0x00; /*P0_7端口模拟 IO使能*/ APCCFG|=0x80; /*单次转换,参考电压为电源...
  • R9 STM32之ADC—电压采集

    千次阅读 2017-08-03 10:01:40
    STM32之ADC—电压采集简介STM32f103 系列有 3 个 ADC,精度为 12 位,每个 ADC 最多有 16 个外部通道。其中 ADC1 和 ADC2 都有 16个外部通道,ADC3根据 CPU 引脚的不同通道数也不同,一般都有 8 个外部通道。目录...
  • ADC采样工作原理详解

    千次阅读 2019-07-03 16:26:13
    如何利用单片机的ADC模块(或者独立的ADC芯片)得到接入ADC管脚上的实际电压值? 这个问题,是第一次接触ADC时候,大家都会遇到的问题。会读到什么值 单片机会读到什么值?需要看一个特性,就是几位的ADC,在手册上...
  • STM32 多通道ADC采集详解(DMA模式和非DMA模式)

    万次阅读 多人点赞 2019-09-02 09:57:15
    ADC相关问题: 1.采集到的值如何转化计算? STM32系列芯片大都是12位只有少部分是16位的,如:F373芯片。 12位分辨率意味着我们采集电压的精度可以达到:Vref / 4096。 采集电压= Vref * ADC_DR / 4096; VREF...
  • ADC采样原理

    万次阅读 2019-06-02 23:21:57
    尽管国内有华为、紫光、中芯微等一定知名度的芯片企业,但与欧美等企业差距很大,尤其在ADC芯片上表现尤为显著。目前ADC的供应商主要有德州仪器、亚德诺等企业。中国是全球最主要的芯片需求方,但是国内能造出高...
  • 交直流电压电流信号ADC采集

    万次阅读 2018-07-16 16:04:50
    1、电流信号采集需要将电流信号转化为电压信号才能进行采集,如下图所示: 图1单片机ADC采集到的电压模拟数字信号后,需要除以ADC的分辨率再乘以基准电压得到单片机采集的数字电压,根据欧姆定律,U=IRàI=U/R,求得...
  • STM32 CUbeIDE ADC采集单通道和多通道 DMA 1、ADC采集单通道1.1 、创建工程选择ADC1.2、重定向printf 可以输出小数1.3、开启 ADC DMA2、ADC采集2通道   STM32拥有 1~3个 ADC STM32F101/102系列只有 1个 ADC)),...
  • stm32 ADC采集温度

    2020-07-30 23:30:27
    基于STM32嵌入式芯片的ADC采集程序,尤其适合国信长天开发板
  • STM32ADC采集程序

    2020-07-17 17:52:53
    DAC输出一个控制电压值,ADC采集反馈值,再通过串口发送出去
  • 浅谈stm32f1两路adc采集(非DMA)

    千次阅读 2018-07-11 16:57:20
    由于项目的需要写3路ADC采集,发现采集的电压出现很大的误差。(后来换成ADC1和ADC2模式后解决了)仔细看了一下,不会是板子对应的引脚共用,那到底是怎么回事呢?想到了电路上的上拉电阻,测量出现的电压数值跳变不...
  • STM32 ADC采集和DAC输出

    2020-07-29 14:18:37
    STM32 ADC采集通过DAC直接输出,采集频率最大700hz可完全不失真,700到4k,打点不完全,4k以上开始失真
  • STM32F4 的16通道ADC采集例程,注释清晰, /**************************************************************************** PCLK2 = HCLK / 2 下面选择的是2分频 ADCCLK = PCLK2 /8 = HCLK / 8 = 168 / 8 = ...
  • 通过ADC采集MQ2烟雾传感器数据 一、硬件准备 小熊派+E53_SF1扩展模块,如下所示: 二、开启ADC 打开board.h文件,找到ADC的配置处,按照其提示使用: 首先,打开【RT-Thread Settings】,找到ADC设备驱动程序,将...
  • ADC采集实现温度检测

    千次阅读 2020-06-09 11:02:48
    1 使用nordic库实现 nRF52832ADC采集的一个例子 https://www.cnblogs.com/zzu-liulei/p/6519141.html 2 用nRF52840自带的ADC采集camera内部的温度 原理图: 3 思路: 1).camera内部的热敏电阻与上拉电阻分...
  • STM8S_005_ADC采集单通道电压

    千次阅读 2017-05-08 20:40:07
    因此,本文讲述STM8S的一项比较实用的功能:ADC采集电压。 在物联网的产品中,大多数传感器都使用了模数转换(ADC)这一功能。本文提供STM8S两种转换模式:Ø 单次软件触发Ø 连续转换 本文将结合“STM8S参考...
  • ADC 采集电池电量

    千次阅读 2017-05-18 14:09:25
    单片机内部的多路ADC采集之间可能会相互影响,使用的时候需要参考datasheet,在NUC100中,ADC7 比较与ADC6同时使用时,ADC6的采样就会出问题,采集的电量值一直保持不变。       其次,ADC采集电路的设计也要...
1 2 3 4 5 ... 20
收藏数 8,312
精华内容 3,324
关键字:

adc采集