STM32--ADC

一、简介

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

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

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

*输入电压范围:0~3.3V,转换结果范围:0~4095(12位转换分辨率)

*18个输入通道,可测量16个外部和2个内部信号源(在任意多个通道上以任意顺序进行的一系列转换构成成组转换(规则通道)。例如,可以如下顺序完成转换:通道3、通道8、通道2、通道0、通道2、通道2、通道15

*规则组和注入组两个转换单元(规则通道:我们平时用的一般通道,按顺序进行转换),(注入通道:可以理解为插入。它是一种在规则通道转换的时候强行插入要转换的一种。注入通道只有在规则通道存在的时候才会出现

*模拟看门狗自动监测输入电压范围

*转换时间:最短的转化时间--Tconv = 采样时间 + 12.5个周期

                    PCLK2 = 72M,ADC_CLK = 72/6 = 12M

                    Tconv = 1.5+12.4 = 14周期 = 14/12us = 1.17us

*AD转换的步骤:采样,保持,量化,编码

*STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道(F4有三个ADC)

1、电压输入范围

*输入电压: VREF- <= VIN  <=  VREF+

*决定输入电压的引脚:VREF-,VREF+,VDDA,VSSA

*VSSA和VREF- 接地,VREF+ 和VDDA 接3.3V

*得到ADC的电压输入范围为: 0-3.3V

电压怎么测?

电压输入范围:ADC可以测量-10V ~  +10V

  根据基尔霍夫定理:(Vin - Vout)/R2 + (3v3-Vout)/R1=Vout/R3

                                    Vout=(Vint + 10)/6

二、ADC的基本结构

ps:STM32f103c8t6有ADC1和ADC2,有两个转换单元(规则组、注入组),规则组有16个通道,注入组有4个通道。

规则通道有数据覆盖的问题(用DMA来解决 只能用于ADC1,只有一个数据寄存器),注入通道没有数据覆盖的问题(四个通道有四个存放寄存器)

三、转换模式

1、单次转换,非扫描模式

*单次转换模式下, ADC 只执行一次转换(如果需要再进行转换需要软件来执行)
*如果一个规则通道被转换:转换数据被储存在 16 ADC_DR寄存器中,EOC( 转换结束 )标志被设置为1,如果设置了 EOCIE ,则产生中断。
*非扫描模式,只能用于只有一个转换通道,有多个转换通道时要设置扫描模式

2、连续转换,非扫描模式

*在连续转换模式中,当前面 ADC 转换一结束马上就启动另一次转换。此模式可通过外部触发启
动或通过设置 ADC_CR2 寄存器上的 ADON 位启动,此时 CONT 位是 1
*如果一个规则通道被转换:转换数据被储存在 16 ADC_DR寄存器中,EOC( 转换结束 )标志被设置为1,如果设置了 EOCIE ,则产生中断。
*非扫描模式,只能用于只有一个转换通道,有多个转换通道时要设置扫描模式

3、单次转换,扫描模式

*ADC规则通道的转换次序是由由序列1到序列16依次转换(有通道就转换没通道就跳过),如果转换次序需要较高优先级,那就要把该通道放在靠前序列
*连续转换模式是当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。
*扫描模式只用于一个规则组中有多个通道需要转换的情况

4、连续转换,扫描模式

*在连续转换模式中,当前面 ADC 转换一结束马上就启动另一次转换。此模式可通过外部触发启
动或通过设置 ADC_CR2 寄存器上的 ADON 位启动,此时 CONT 位是 1
*如果一个规则通道被转换:转换数据被储存在 16 ADC_DR寄存器中,EOC( 转换结束 )标志被设置为1,如果设置了 EOCIE ,则产生中断。
*扫描模式只用于一个规则组中有多个通道需要转换的情况
PS:转换序列里可以可以出现多个相同的转换通道

四、转换顺序

通过设置寄存器里面不同的值,来配置不同通道的转换顺序以及转换的总通道数量

规则通道:

注入通道:

五、代码

1、ADC单通道DMA读取

#include "adc.h"
uint16_t ADC_conversionValue;//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode 	= GPIO_Mode_AIN;   //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin	= ADCx_PIN;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;DMA_InitTypeDef DMA_StructInit;/*--------------------------DMA-----------------------------------------*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);						//打开时钟DMA_DeInit(DMA1_Channel1);												//将DMA寄存器复位成刚上电的样子DMA_StructInit.DMA_MemoryBaseAddr     =	(uint32_t)&ADC_conversionValue;	//存储器地址DMA_StructInit.DMA_PeripheralBaseAddr =	(uint32_t)(&(ADC_x->DR));		//外设地址 DMA_StructInit.DMA_DIR				  = DMA_DIR_PeripheralSRC;			//传输方向DMA_StructInit.DMA_BufferSize         =	1;								//传输数目DMA_StructInit.DMA_PeripheralDataSize =	DMA_PeripheralDataSize_HalfWord;//外设数据宽度,数据寄存器只用到低16位DMA_StructInit.DMA_MemoryDataSize	  = DMA_MemoryDataSize_HalfWord;	//存储器数据宽度,数据寄存器只用到低16位DMA_StructInit.DMA_PeripheralInc 	  =	DMA_PeripheralInc_Disable;		//外设地址是否递增DMA_StructInit.DMA_MemoryInc		  = DMA_MemoryInc_Disable;			//存储器地址是否递增DMA_StructInit.DMA_Mode				  =	DMA_Mode_Circular;				//模式选择(现在时循环模式)DMA_StructInit.DMA_Priority			  =	DMA_Priority_High;				//通道优先级DMA_StructInit.DMA_M2M  			  = DMA_M2M_Disable;				//存储器到存储器模式DMA_Init( DMA1_Channel1, &DMA_StructInit);DMA_Cmd(DMA1_Channel1, ENABLE);/*---------------------ADC------------------------------------*/ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode					= ADC_Mode_Independent; 	//设置独立模式(因为只有一个ADC通道)ADC_StructInit.ADC_ScanConvMode			= DISABLE;					//配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode	= ENABLE;					//配置是否要连续转换ADC_StructInit.ADC_DataAlign			= ADC_DataAlign_Right;		//配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel			= 1;						//配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者GPIO才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8);											//时钟配置72/8=9MADC_RegularChannelConfig(ADC_x, ADCx_Channel, 1, ADC_SampleTime_55Cycles5);	//规则通道的配置,第三个参数是配置第几次转换,第四个参数是配置采样周期ADC_Cmd(ADC_x, ENABLE);														//使能ADC中断ADC_StartCalibration(ADC_x);												//开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x));										//等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE);									//软件触发使能(开始工作)//使能DMA ADCADC_DMACmd(ADC_x, ENABLE);}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();
}extern uint16_t ADC_conversionValue;
int  main()
{float conversionValue = 0;initSysTick();usart_init();ADCx_Init();while(1){conversionValue = (float)ADC_conversionValue/4096*3.3;printf("hex %04x\r\n",ADC_conversionValue);printf("conversionValue %f\r\n",conversionValue);ms_delay(2000);}}

2、ADC单通道中断读取

#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
static void ACDx_GPIO_Config(void);
static void Config_ADC_Init(void);
static void ADCx_NVIC_Config(void);
void ADCx_Init(void);//ADC引脚配置的宏
#define ADCx_PIN 					GPIO_Pin_1
#define ADCx_PIN_PORT  				GPIOA
#define ADCx_PIN_Periph 			RCC_APB2Periph_GPIOA
#define ADCx_PIN_RCC_Clock_Cmd 		RCC_APB2PeriphClockCmd//ADC配置的宏
#define ADCx_Periph 				RCC_APB2Periph_ADC2
#define ADCx_RCC_Clock_Cmd 			RCC_APB2PeriphClockCmd
#define ADC_x        				ADC2
#define ADCx_Channel				ADC_Channel_1#define ADCx_IRQHandler				ADC1_2_IRQHandler
#endif#include "adc.h"static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode 	= GPIO_Mode_AIN;   //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin	= ADCx_PIN;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode					= ADC_Mode_Independent; 	//设置独立模式(因为只有一个ADC通道)ADC_StructInit.ADC_ScanConvMode			= DISABLE;					//配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode	= ENABLE;					//配置是否要连续转换ADC_StructInit.ADC_DataAlign			= ADC_DataAlign_Right;		//配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel			= 1;						//配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者输入引脚触发才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8);											//时钟配置72/8=9MADC_RegularChannelConfig(ADC_x, ADCx_Channel, 1, ADC_SampleTime_55Cycles5);	//规则通道的配置,第三个参数是配置第几个转换换通道,第四个参数是配置采样周期,第二个参数是第几个通道(例:A0是通道1)ADC_ITConfig(ADC_x, ADC_IT_EOC, ENABLE);									//配置成规则通道中断ADC_Cmd(ADC_x, ENABLE);														//使能ADC中断ADC_StartCalibration(ADC_x);												//开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x));										//等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE);									//软件触发使能(开始工作)}static void ADCx_NVIC_Config(void)
{NVIC_InitTypeDef ADCx_NVIC_StructInit;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);ADCx_NVIC_StructInit.NVIC_IRQChannel					= ADC1_2_IRQn;ADCx_NVIC_StructInit.NVIC_IRQChannelCmd					= ENABLE;ADCx_NVIC_StructInit.NVIC_IRQChannelPreemptionPriority  = 1;ADCx_NVIC_StructInit.NVIC_IRQChannelSubPriority			= 1;NVIC_Init(&ADCx_NVIC_StructInit);
}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();ADCx_NVIC_Config();
}extern uint32_t ADC_Conversion_value;
int  main()
{float  ADC_Value = 0;initSysTick();usart_init();ADCx_Init();while(1){ADC_Value = (float)ADC_Conversion_value/4096*3.3;printf("adc_float=%fv\r\n",ADC_Value);printf("adc_Hex=%04x\r\n",ADC_Conversion_value);ms_delay(2000);}}void ADCx_IRQHandler(void)
{if(ADC_GetITStatus(ADC_x, ADC_IT_EOC) == SET){ADC_Conversion_value = ADC_GetConversionValue(ADC_x);//读取转换的数值}ADC_ClearITPendingBit(ADC_x, ADC_IT_EOC);
}

3、ADC多通道DMA读取

#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
static void ACDx_GPIO_Config(void);
static void Config_ADC_Init(void);
void ADCx_Init(void);//ADC引脚配置的宏
#define ADCx_PIN 					GPIO_Pin_1
#define ADCx_PIN_PORT  				GPIOA
#define ADCx_PIN_Periph 			RCC_APB2Periph_GPIOA
#define ADCx_PIN_RCC_Clock_Cmd 		RCC_APB2PeriphClockCmd//ADC配置的宏
#define ADCx_Periph 				RCC_APB2Periph_ADC1
#define ADCx_RCC_Clock_Cmd 			RCC_APB2PeriphClockCmd
#define ADC_x        				ADC1
#define ADCx_Channel				ADC_Channel_1#define len							3#endif#include "adc.h"
uint16_t ADC_conversionValue[len];//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode 	= GPIO_Mode_AIN;   //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin	= GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;DMA_InitTypeDef DMA_StructInit;/*--------------------------DMA-----------------------------------------*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);						//打开时钟DMA_DeInit(DMA1_Channel1);												//将DMA寄存器复位成刚上电的样子DMA_StructInit.DMA_MemoryBaseAddr     =	(uint32_t)ADC_conversionValue;	//存储器地址DMA_StructInit.DMA_PeripheralBaseAddr =	(uint32_t)(&(ADC_x->DR));		//外设地址 DMA_StructInit.DMA_DIR				  = DMA_DIR_PeripheralSRC;			//传输方向DMA_StructInit.DMA_BufferSize         =	len;							//传输数目(缓冲区大小,应该等于数据目的地的大小)// 外设数据大小为半字,即两个字节DMA_StructInit.DMA_PeripheralDataSize =	DMA_PeripheralDataSize_HalfWord;//外设数据宽度,数据寄存器只用到低16位// 内存数据大小也为半字,跟外设数据大小相同DMA_StructInit.DMA_MemoryDataSize	  = DMA_MemoryDataSize_HalfWord;	//存储器数据宽度,数据寄存器只用到低16位DMA_StructInit.DMA_PeripheralInc 	  =	DMA_PeripheralInc_Disable;		//外设地址是否递增DMA_StructInit.DMA_MemoryInc		  = DMA_MemoryInc_Enable;			//存储器地址是否递增DMA_StructInit.DMA_Mode				  =	DMA_Mode_Circular;				//模式选择(现在时循环模式)DMA_StructInit.DMA_Priority			  =	DMA_Priority_High;				//通道优先级DMA_StructInit.DMA_M2M  			  = DMA_M2M_Disable;				//存储器到存储器模式DMA_Init( DMA1_Channel1, &DMA_StructInit);DMA_Cmd(DMA1_Channel1, ENABLE);/*---------------------ADC------------------------------------*/ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode					= ADC_Mode_Independent; 	//设置独立模式(因为只有一个ADC)ADC_StructInit.ADC_ScanConvMode			= ENABLE;					//配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode	= ENABLE;					//配置是否要连续转换ADC_StructInit.ADC_DataAlign			= ADC_DataAlign_Right;		//配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel			= len;						//配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者输入引脚触发才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8);												//时钟配置72/8=9MADC_RegularChannelConfig(ADC_x, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);	//规则通道的配置,第三个参数是配置第几次转换,第四个参数是配置采样周期ADC_RegularChannelConfig(ADC_x, ADC_Channel_2, 2, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC_x, ADC_Channel_3, 3, ADC_SampleTime_55Cycles5);ADC_Cmd(ADC_x, ENABLE);														//使能ADC中断// 初始化ADC 校准寄存器  ADC_ResetCalibration(ADC_x);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC_x));ADC_StartCalibration(ADC_x);												//开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x));										//等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE);									//软件触发使能(开始工作)//使能DMA ADC请求ADC_DMACmd(ADC_x, ENABLE);}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();
}// 局部变量,用于保存转换计算后的电压值 	 
float ADC_ConvertedValueLocal[len];        
int  main()
{float conversionValue = 0;initSysTick();usart_init();ADCx_Init();printf("\r\n ----这是一个ADC多通道采集实验----\r\n");while(1){ADC_ConvertedValueLocal[0] =(float) ADC_conversionValue[0]/4096*3.3;ADC_ConvertedValueLocal[1] =(float) ADC_conversionValue[1]/4096*3.3;ADC_ConvertedValueLocal[2] =(float) ADC_conversionValue[2]/4096*3.3;printf("\r\n CH0 value = %f V \r\n",ADC_ConvertedValueLocal[0]);printf("\r\n CH1 value = %f V \r\n",ADC_ConvertedValueLocal[1]);printf("\r\n CH2 value = %f V \r\n",ADC_ConvertedValueLocal[2]);ms_delay(2000);}}

4、双ADC_DMA读取_同步规则

*此模式在 规则通道组 上执行。外部触发来自 ADC1 的规则组多路开关 ( ADC1_CR2 寄存器的
EXTSEL[2:0] 选择 ) 它同时给 ADC2 提供同步触发。
*不要在2个ADC上转换相同的通道((两个ADC在同一个通道上的采样时间不能重善)。
* ADC1 ADC2 的转换结束时:产生一个32位DMA传输请求(如果设置了DMA位),32位的ADC1_DR寄存器内容传输到SRAM中,它 上半个字包含ADC2的转换数据, 低半个字包含ADC1的转换数据。
* 当所有 ADC1/ADC2 规则通道都被转换完时,产生 EOC 中断 ( 若任一 ADC 接口开放了中断 )
#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
static void ACDx_GPIO_Config(void);
static void Config_ADC_Init(void);
void ADCx_Init(void);//ADC引脚配置的宏
#define ADCx_PIN 					GPIO_Pin_1
#define ADCx_PIN_PORT  				GPIOA
#define ADCx_PIN_Periph 			RCC_APB2Periph_GPIOA
#define ADCx_PIN_RCC_Clock_Cmd 		RCC_APB2PeriphClockCmd//ADC配置的宏
#define ADCx_Periph 				RCC_APB2Periph_ADC1
#define ADCx_RCC_Clock_Cmd 			RCC_APB2PeriphClockCmd
#define ADC_x        				ADC1
#define ADCx_Channel				ADC_Channel_1#define len							1#endif#include "adc.h"
uint32_t ADC_conversionValue[len];//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
static void ACDx_GPIO_Config(void)
{GPIO_InitTypeDef ADC_GPIO_StructInit;ADCx_PIN_RCC_Clock_Cmd(ADCx_PIN_Periph,ENABLE);ADC_GPIO_StructInit.GPIO_Mode 	= GPIO_Mode_AIN;   //必须是模拟输入ADC_GPIO_StructInit.GPIO_Pin	= GPIO_Pin_1 | GPIO_Pin_2 ;GPIO_Init(ADCx_PIN_PORT, &ADC_GPIO_StructInit);
}static void Config_ADC_Init(void)
{ADC_InitTypeDef ADC_StructInit;DMA_InitTypeDef DMA_StructInit;/*--------------------------DMA-----------------------------------------*/RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);						//打开时钟DMA_DeInit(DMA1_Channel1);												//将DMA寄存器复位成刚上电的样子DMA_StructInit.DMA_MemoryBaseAddr     =	(uint32_t)ADC_conversionValue;	//存储器地址DMA_StructInit.DMA_PeripheralBaseAddr =	(uint32_t)(&(ADC_x->DR));		//外设地址 DMA_StructInit.DMA_DIR				  = DMA_DIR_PeripheralSRC;			//传输方向DMA_StructInit.DMA_BufferSize         =	len;							//传输数目(缓冲区大小,应该等于数据目的地的大小)// 外设数据大小为半字,即两个字节DMA_StructInit.DMA_PeripheralDataSize =	DMA_PeripheralDataSize_Word;	//外设数据宽度(32位)// 内存数据大小也为半字,跟外设数据大小相同DMA_StructInit.DMA_MemoryDataSize	  = DMA_MemoryDataSize_Word;		//存储器数据宽度(32位)DMA_StructInit.DMA_PeripheralInc 	  =	DMA_PeripheralInc_Disable;		//外设地址是否递增DMA_StructInit.DMA_MemoryInc		  = DMA_MemoryInc_Enable;			//存储器地址是否递增DMA_StructInit.DMA_Mode				  =	DMA_Mode_Circular;				//模式选择(现在时循环模式)DMA_StructInit.DMA_Priority			  =	DMA_Priority_High;				//通道优先级DMA_StructInit.DMA_M2M  			  = DMA_M2M_Disable;				//存储器到存储器模式DMA_Init( DMA1_Channel1, &DMA_StructInit);DMA_Cmd(DMA1_Channel1, ENABLE);/*---------------------ADC1------------------------------------*/ADCx_RCC_Clock_Cmd(ADCx_Periph, ENABLE);ADC_StructInit.ADC_Mode					= ADC_Mode_RegSimult; 		//设置成规则同步模式(因为有两个ADC)ADC_StructInit.ADC_ScanConvMode			= ENABLE;					//配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode	= ENABLE;					//配置是否要连续转换ADC_StructInit.ADC_DataAlign			= ADC_DataAlign_Right;		//配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel			= len;						//配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者输入引脚触发才会使用)ADC_Init(ADC_x, &ADC_StructInit);RCC_ADCCLKConfig(RCC_PCLK2_Div8);											//时钟配置72/8=9MADC_Cmd(ADC_x, ENABLE);														//使能ADC中断ADC_RegularChannelConfig(ADC_x, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);//设置通道1(PA1)//使能DMA ADC请求ADC_DMACmd(ADC_x, ENABLE);/*--------------------ADC2-------------------------------------*/ADCx_RCC_Clock_Cmd(RCC_APB2Periph_ADC2, ENABLE);ADC_StructInit.ADC_Mode					= ADC_Mode_RegSimult; 		//设置成规则同步模式(因为有两个ADC)ADC_StructInit.ADC_ScanConvMode			= ENABLE;					//配置是否扫描(用在多通道)ADC_StructInit.ADC_ContinuousConvMode	= ENABLE;					//配置是否要连续转换ADC_StructInit.ADC_DataAlign			= ADC_DataAlign_Right;		//配置数据的对齐模式ADC_StructInit.ADC_NbrOfChannel			= len;						//配置要转换通道的数目ADC_StructInit.ADC_ExternalTrigConv     = ADC_ExternalTrigConv_None;//配置触发模式(这里是软件触发,外部触发是有定时器或者GPIO才会使用)
//	RCC_ADCCLKConfig(RCC_PCLK2_Div8);											//时钟配置72/8=9MADC_Init(ADC2, &ADC_StructInit);ADC_Cmd(ADC2, ENABLE);														//使能ADC中断ADC_RegularChannelConfig(ADC2, ADC_Channel_2, 1, ADC_SampleTime_55Cycles5);//设置通道2(PA2)/* 使能ADCx_2的外部触发转换 */ADC_ExternalTrigConvCmd(ADC2, ENABLE);// 初始化ADC1 校准寄存器  ADC_ResetCalibration(ADC_x);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC_x));ADC_StartCalibration(ADC_x);												//开始校准ADCwhile(ADC_GetCalibrationStatus(ADC_x));										//等待校准完成// 初始化ADC2 校准寄存器  ADC_ResetCalibration(ADC2);// 等待校准寄存器初始化完成while(ADC_GetResetCalibrationStatus(ADC2));ADC_StartCalibration(ADC2);												//开始校准ADCwhile(ADC_GetCalibrationStatus(ADC2));										//等待校准完成ADC_SoftwareStartConvCmd(ADC_x, ENABLE);									//软件触发使能(开始工作)}void ADCx_Init(void)
{ACDx_GPIO_Config();Config_ADC_Init();
}extern uint32_t ADC_conversionValue[len];//单ADC模式时,数据寄存器只用到低16位(用来存放 ADC发过来的数据)
// 局部变量,用于保存转换计算后的电压值 	 
float ADC_ConvertedValueLocal[len*2];        
int  main()
{uint16_t temp0=0 ,temp1=0;initSysTick();usart_init();ADCx_Init();printf("\r\n ----这是一个双ADC规则同步采集实验----\r\n");while(1){// 取出ADC1数据寄存器的高16位,这个是ADC2的转换数据temp0 = (ADC_conversionValue[0]&0XFFFF0000) >> 16;//取高16位(ADC2的数据)// 取出ADC1数据寄存器的低16位,这个是ADC1的转换数据temp1 = (ADC_conversionValue[0]&0XFFFF);		  //取低16位(ADC1的数据)ADC_ConvertedValueLocal[0] =(float) temp0/4096*3.3;ADC_ConvertedValueLocal[1] =(float) temp1/4096*3.3;printf("\r\n ADC1 value = %f V \r\n",ADC_ConvertedValueLocal[1]);printf("\r\n ADC2 value = %f V \r\n",ADC_ConvertedValueLocal[0]);ms_delay(2000);}}

PS:

*多路ADC模式的时候 ,要配置外部触发转换,单路ADC只需要配置软件触发转换

*多路ADC模式的时候,ADC1,ADC2一起使用,例如设置规则同步的时候,通道的数目要一致,ADC1有两个通道,ADC2也需要有两个通道

*

五、触发源

 *ADC 的触发转换有两种方法:分别是通过软件或外部事件(也就是硬件)触发转换。

 *软件触发转换的方法。方法是:通过写 ADC_CR2 寄存器的 ADON 这个位来控制,写 1 就开始转换,写 0 就停止转换,这个控制 ADC 转换的方式非常简单。

*外部事件触发转换的方法,有定时器和输入引脚触发等等

六、校准

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

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

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

七、DMA请求

*因为规则通道转换的值储存在一个仅有的数据寄存器中,所以当转换多个规则通道时需要使用 DMA,这可以避免丢失已经存储在ADC_DR寄存器中的数据。

*只有在规则通道的转换结束时才产生DMA请求,并将转换的数据从ADC_DR寄存器传输到用户 指定的目的地址。

*只有ADC1和ADC3拥有DMA功能。由ADC2转化的数据可以通过双ADC模式,利用ADC1的DMA功能传输。(ADC2转换的数据要用DMA传输的时候,就可以用双ADC模式)。

八、中断

*规则和注入组转换结束时能产生中断,当模拟看门狗状态位被设置时也能产生中断。它们都有
独立的中断使能位。

*ADC1和ADC2的中断映射在同一个中断向量上,而ADC3的中断有自己的中断向量。

* ADC_SR 寄存器中有 2 个其他标志,但是它们没有相关联的中断:

九、数据对齐

*ADC_CR2 寄存器中的 ALIGN 位选择转换后数据储存的对齐方式。数据可以左对齐或右对齐
*
注入组通道转换的数据值已经减去了在 ADC_JOFRx 寄存器中定义的偏移量,因此结果可以是一
个负值。 SEXT 位是扩展的符号值。
*对于规则组通道,不需减去偏移值,因此只有 12 个位有效。

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

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

相关文章

鸿蒙ArkTS声明式开发:跨平台支持列表【背景设置】 通用属性

背景设置 设置组件的背景样式。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版…

备份数据怎么恢复?从入门到精通,2个技巧读懂!

在数字时代&#xff0c;数据的重要性不言而喻。无论是个人还是企业&#xff0c;数据都是我们生活和工作的核心&#xff0c;但由于各种原因&#xff0c;数据丢失的情况时有发生。为了应对这种情况&#xff0c;备份数据成为了一个必要的措施。可当数据真的丢失时&#xff0c;备份…

3D工业视觉

前言 本文主要介绍3D视觉技术、工业领域的应用、市场格局等&#xff0c;主要技术包括激光三角测量、结构光、ToF、立体视觉。 一、核心内容 3D视觉技术满足工业领域更高精度、更高速度、更柔性化的需求&#xff0c;扩大工业自动化的场景。 2D视觉技术基于物体平面轮廓&#…

CentOS 7基础操作01_安装CentOS 7操作系统

1、实验环境 因为 Windows图形界面占用系统资源较高,所以公司准备将面向互联网的网站,数据库等重要应用基于Linux平台部署&#xff0c;并计划于近期将服务器安装开源免费的 CentOS 系统。进行前期准备工作时,需要公司的系统管理员尽快掌握 CentOS 系统的安装过程 2、需要描述 …

《QT实用小工具·六十九》基于QT开发的五子棋AI游戏

1、概述 源码放在文章末尾 该项目实现了五子棋对战AI&#xff0c;可以享受和AI下棋的快乐&#xff0c;项目实现思路如下&#xff1a; 博弈树 ●Alpha-Beta剪枝(性能提高较大) ●启发式搜索(性能提高较大) ●落子区域限制(性能提高较大) ●Zobrist哈希(性能小幅提升) ●Qt…

能拖拽生成几个图表,就叫BI,就叫低代码,顶多算个报表工具

一、什么是BI BI&#xff08;Business Intelligence&#xff09;是指通过数据分析和可视化工具来帮助企业做出决策的过程和技术。它远远不止于简单的拖拽生成图表&#xff0c;而是通过对数据的深入分析和挖掘&#xff0c;提供更全面、准确的信息支持。 BI&#xff08;Business…

RxSwift - 实现一个MVVM架构的TableView

文章目录 RxSwift - 实现一个MVVM架构的TableView前沿MVVM架构的Tableview目录结构1、模型&#xff08;Model&#xff09;2、视图模型&#xff08;ViewModel&#xff09;3、视图&#xff08;View&#xff09; 界面效果 RxSwift - 实现一个MVVM架构的TableView 前沿 MVVM架构在…

算法(七)插入排序

文章目录 插入排序简介代码实现 插入排序简介 插入排序&#xff08;insertion sort)是从第一个元素开始&#xff0c;该元素就认为已经被排序过了。然后取出下一个元素&#xff0c;从该元素的前一个索引下标开始往前扫描&#xff0c;比该值大的元素往后移动。直到遇到比它小的元…

案例|开发一个美业小程序,都有什么功能

随着移动互联网的迅猛发展&#xff0c;美业连锁机构纷纷寻求数字化转型&#xff0c;以小程序为载体&#xff0c;提升服务效率&#xff0c;增强客户体验。 线下店现在面临的困境&#xff1a; 客户到店排队时间过长&#xff0c;体验感受差 新客引流难&#xff0c;老用户回头客…

链动3+1模式:数字化转型中的创新商业发展路径

在数字化时代&#xff0c;企业为了保持竞争力&#xff0c;不断探索和尝试新的商业模式。链动31模式作为一种创新的商业模式&#xff0c;以其独特的运作机制&#xff0c;为企业和个人带来了全新的发展机遇。本文将对链动31模式进行深入解析&#xff0c;并通过与传统链动模式的对…

【如何用爬虫玩转石墨文档?】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

多维时序 | Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预测

多维时序 | Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预测 目录 多维时序 | Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现SA-BP模拟退火算法优化BP神经网络多变量时间序列预…

SpringSecurity6从入门到实战之Filter过滤器回顾

SpringSecurity6从入门到实战之Filter过滤器回顾 如果没有SpringSecurity这个框架,我们应该通过什么去实现客户端向服务端发送请求时,先检查用户是否登录,登录了才能访问.否则重定向到登录页面 流程图如下 官方文档&#xff1a;https://docs.spring.io/spring-security/referen…

【C#】类和对象的区别

1.区别概述 结构体和类的最大区别是在存储空间上&#xff0c;前者是值类型&#xff0c;后者是引用类型&#xff0c;它们在赋值上有很大的区别&#xff0c;在类中指向同一块空间的两个类的值会随一个类的改变而改变另一个&#xff0c;请看如下代码所示&#xff1a; namespace …

CV Method:经典CNN Backbone总结

文章目录 前言一、ResNet二、ResNeXt三、Res2Net四、SeNet五、ResNeSt六、DenseNet七、CSPNetPytorch Model Code总结 前言 Backbone作为一切深度学习任务的基础&#xff0c;不论是理论还是实际应用都有重要的意义&#xff0c;本文针对经典Backbone进行总结&#xff0c;这些Ba…

前端vue搭建

1.找一个合适的模板&#xff0c;可以用vue-element-admin的模板&#xff0c;但是个人认为这个模板太大了&#xff0c;做小项目修改起来比较复杂&#xff0c;可以找一个比较小的项目 2.我找的项目git clone https://github.com/tuture-dev/vue-admin-template.git&#xff0c;这…

【iOS】UI学习(一)

目录 前言前情内容&#xff1a;如何在xcode里创建UI项目UILabelUIButtonUIButton基础UIButton事件处理 UIviewUIView基础概念UIView的层级关系 UIWindow对象总结 前言 本篇博客主要介绍了iOS中UI学习的部分知识&#xff0c;即UILabel、UIButton、UiView、UIWindow的相关内容&am…

大坝安全监测自动化技术的规范化设计准则

大坝安全监测自动化技术的规范化设计准则 一、施工阶段自动化系统设计要点 在施工阶段&#xff0c;大坝安全监测自动化系统的设计应当涵盖以下几个核心内容&#xff1a; 监测仪器的布局规划及详细的施工图纸设计。 配套土建项目以及防雷设施的施工设计规划。 明确施工过程中的技…

7 步解决Android Studio模拟器切换中文输入

详细步骤传送地址&#xff1a;Android Studio 模拟器切换中文输入 目录 01 问题概述 02 模拟器的调试 01 问题概述 大家在使用Android Studio 软件进行项目演示时总会遇到一些输入框需要输入中文汉字的情况&#xff0c;由于AS自带的模拟器基本都是英文&#xff0c;这时就有同…

香橙派OriengePi AiPro 华为昇腾芯片开发板开箱测评

香橙派OriengePi AiPro 华为昇腾芯片开发板开箱测评 文章目录 前言OrangePi AIpro硬件相关及配置外观接口配置虚拟桌面网络配置拓展swap内存 软件相关及配置docker基础镜像搭建pytorch安装及匹配 软件测试使用yolo v8测试使用模型转换 总结 前言 博主有幸受邀CSDN测评香橙派与…