ADC 1. ADC结构图
1.1电压输入引脚 一般将VREF+和VSSA接3.3V,将VREF-和VDDA接GND 。
1.2输入通道 ADC通道多达19个,ADC1有三个内部通道温度传感器、内部参考电压VREF、备用电源VBAT 。
1.3通道转换顺序 外部16个通道在转换时可分为两组通道,规则通道可分为16路,注入通道可分为4路 。
规则通道,为正常通道 。一般都使用这个 。
注入通道,为特殊通道,类似于中断,优先级比规则通道高 。
1.4触发源 选择好输入通道,设置好转换顺序 。通过设置ADC控制器的ADC_CR2的ADON位为1,使能ADC 。
ADC支持外部触发,选择触发源的方式由控制器寄存器ADC_CR2的EXTSEL[2:0]和JEXTSEL[2:0]来控制 。EXTSEL[2:0]用于选择规则通道触发源,JEXTSEL[2:0]用于选择注入通道触发源 。触发源的使能位为:ADC_CR2的EXTTRIG和JEXTTRIG 。
使能外部触发时,还可选择触发极性 。一共有四种:禁止触发检测、上升沿检测、下降沿检测、上升沿和下降沿均检测 。控制位为控制寄存器ADC_CR2的EXTEN[1:0]和JEXTEN[1:0] 。
1.5ADC时钟 ADC时钟ADC_CLK由APB2经过分频产生,最大值为36Mhz 。分频因子通过控制寄存器ADC_CR2的ADCPER[1:0]设置,可设置的分频系数为2 、 4 、 6 、 8 。一般APB2的时钟为84Mhz,故一般将分频系数设置为2 。
ADC完成采样需要若干个ADC_CLK周期,采样周期最小为3个ADC_CLK 。配置采样周期数量通过ADC采样时间寄存器ADC_SMPR1和ADC_SMPR2中的SMP[2:0]设置 。ADC_SMPR2控制通道0-9,ADC_SMPR1控制通道10-17 。故采样最快需设置采样周期数量为3 。
ADC总采样时间为:Tconv = 采样时间 + 12个周期
一个周期为1/ADC_CLK
1.6数据寄存器 数据根据转换组不同存放位置也不同,规则组数据放在ADC_CR寄存器内,注入组数据放在JDRx内 。使用双重或三重模式那规则组数据存在放通用规矩寄存器ADC_CR内 。
因ADC精度为12位,数据寄存器是16位,故可选择左对齐或右对齐 。通过ADC_CR2的11位ALIGN设置 。
规则组有16个通道,数据寄存器只有一个 。存放数据要么马上被取走,要么开启DMA模式 。可通过ADC状态寄存器ADC_SR获取当前ADC转换进度,进而进行程序控制 。
注入组有4个通道,数据寄存器也有4个,不会像规则组产生一样的数据覆盖问题 。
1.7中断 1.DMA溢出
如果发生DMA传输数据丢失,并且打开中断标志位时,在转换结束后会产生一个溢出中断 。
2.转换结束与注入转换结束
数据转换结束后,如果使能中断转换结束标志位,转换一结束就会产生转换结束中断 。
3.模拟看门狗事件
当模拟看门狗状态位和溢出状态位分别置1时,规则组和注入组在转换结束时可能产生中断 。
ADC转换分单次转换和连续转换
**单次转换:**通过ADC_CR2寄存器的SWSTART位启动(只适用于规则通道),也可通过外部触发启动(适用于规则通道和注入通道),这时CONT位为0 。
一旦所选择的通道转换完成,转换结果被存放在ADC_DR数据寄存器中,EOC(转换结束)标志将被置位 。如果设置了EOCIE,则会产生中断 。然后ADC停止,等待下一次转换 。
**连续转换:**CONT位为1时,通过外部触发将ADC_CR2寄存器中的SWSTRT位置1启动连续转换(仅适用于规则通道) 。
2.相关寄存器 2.1GPIO结构体 typedef struct{uint32_t GPIO_Pin;//GPIO配置引脚GPIOMode_TypeDef GPIO_Mode;//GPIO模式,输入输出GPIOSpeed_TypeDef GPIO_Speed;//GPIO速率GPIOOType_TypeDef GPIO_OType;//GPIO输出方式,推挽、开漏GPIOPuPd_TypeDef GPIO_PuPd;//GPIO触发方式,上下拉}GPIO_InitTypeDef; 2.2ADC配置结构体 typedef struct {uint32_t ADC_Mode; //ADC模式选择,有独立模式、双重模式以及三重模式uint32_t ADC_Prescaler;//ADC分频系数,ADC时钟是由APB2分频而来,分频系数决定ADC时钟频率,可选的分频系数为2、4、6、8 。通常我们使用4分频,保证ADC最大时钟不能高于36MHz 。uint32_t ADC_DMAAccessMode;//ADCDMA模式设置,禁止或使能相应的DMA模式,只有在双重或者三重模式才需要设置,可以设置三种模式,具体可参考参考手册说明 。uint32_t ADC_TwoSamplingDelay;//ADC采样延迟,用来设置两个采样阶段之间的延迟周期数 。取值范围为://ADC_TwoSamplingDelay_5Cycles~ADC_TwoSamplingDelay_20Cycles 。}ADC_CommonInitTypeDef; //ADC模式选择#define ADC_Mode_Independent((uint32_t)0x00000000)//独立模式#define ADC_DualMode_RegSimult_InjecSimult((uint32_t)0x00000001)#define ADC_DualMode_RegSimult_AlterTrig((uint32_t)0x00000002)#define ADC_DualMode_InjecSimult((uint32_t)0x00000005)#define ADC_DualMode_RegSimult((uint32_t)0x00000006)#define ADC_DualMode_Interl((uint32_t)0x00000007)#define ADC_DualMode_AlterTrig((uint32_t)0x00000009)#define ADC_TripleMode_RegSimult_InjecSimult((uint32_t)0x00000011)#define ADC_TripleMode_RegSimult_AlterTrig((uint32_t)0x00000012)#define ADC_TripleMode_InjecSimult((uint32_t)0x00000015)#define ADC_TripleMode_RegSimult((uint32_t)0x00000016)#define ADC_TripleMode_Interl((uint32_t)0x00000017)#define ADC_TripleMode_AlterTrig((uint32_t)0x00000019) //ADC分频系数#define ADC_Prescaler_Div2((uint32_t)0x00000000)//分频系数2#define ADC_Prescaler_Div4((uint32_t)0x00010000)//分频系数4#define ADC_Prescaler_Div6((uint32_t)0x00020000)//分频系数6#define ADC_Prescaler_Div8((uint32_t)0x00030000)//分频系数8 //ADCDMA模式设置#define ADC_DMAAccessMode_Disabled((uint32_t)0x00000000)//DMA模式失能#define ADC_DMAAccessMode_1((uint32_t)0x00004000)#define ADC_DMAAccessMode_2((uint32_t)0x00008000)#define ADC_DMAAccessMode_3((uint32_t)0x0000C000) 【STM32-ADC】//ADC采样延迟周期数#define ADC_TwoSamplingDelay_5Cycles((uint32_t)0x00000000)#define ADC_TwoSamplingDelay_6Cycles((uint32_t)0x00000100)#define ADC_TwoSamplingDelay_7Cycles((uint32_t)0x00000200)#define ADC_TwoSamplingDelay_8Cycles((uint32_t)0x00000300)#define ADC_TwoSamplingDelay_9Cycles((uint32_t)0x00000400)#define ADC_TwoSamplingDelay_10Cycles((uint32_t)0x00000500)#define ADC_TwoSamplingDelay_11Cycles((uint32_t)0x00000600)#define ADC_TwoSamplingDelay_12Cycles((uint32_t)0x00000700)#define ADC_TwoSamplingDelay_13Cycles((uint32_t)0x00000800)#define ADC_TwoSamplingDelay_14Cycles((uint32_t)0x00000900)#define ADC_TwoSamplingDelay_15Cycles((uint32_t)0x00000A00)#define ADC_TwoSamplingDelay_16Cycles((uint32_t)0x00000B00)#define ADC_TwoSamplingDelay_17Cycles((uint32_t)0x00000C00)#define ADC_TwoSamplingDelay_18Cycles((uint32_t)0x00000D00)#define ADC_TwoSamplingDelay_19Cycles((uint32_t)0x00000E00)#define ADC_TwoSamplingDelay_20Cycles((uint32_t)0x00000F00) 2.3 ADC结构体 typedef struct{uint32_t ADC_Resolution;//ADC分辨率选择FunctionalState ADC_ScanConvMode;//ADC扫描模式选择FunctionalState ADC_ContinuousConvMode;//ADC连续转换模式选择uint32_t ADC_ExternalTrigConvEdge;//ADC外部触发极性uint32_t ADC_ExternalTrigConv;//ADC外部触发选择uint32_t ADC_DataAlign;//ADC数据对齐方式uint8_tADC_NbrOfConversion;//ADC规则序列长度}ADC_InitTypeDef; //ADC分辨率选择//分辨率越高,AD转换数据精度越高,转换时间也越长 。相反分辨率越低,AD转换数据精度越低,转换时间也越短 。#define ADC_Resolution_12b((uint32_t)0x00000000)#define ADC_Resolution_10b((uint32_t)0x01000000)#define ADC_Resolution_8b((uint32_t)0x02000000)#define ADC_Resolution_6b((uint32_t)0x03000000)//ADC扫描模式//可选参数为ENABLE或DISABLE,用来设置是否打开ADC扫描模式 。如果是单通道AD转换,选择DISABLE;如果是多通道AD转换,选择ENABLE 。//ADC连续转换模式选择 。//可选参数为ENABLE或DISABLE,用来设置是连续转换还是单次转换模式 。如果为ENABLE,则选择连续转换模式;如果为DISABLE,则选择单次转换模式,转换一次后停止,需要手动控制才能重新启动转换 。 //外部触发极性选择#define ADC_ExternalTrigConvEdge_None((uint32_t)0x00000000)//禁止触发检测#define ADC_ExternalTrigConvEdge_Rising((uint32_t)0x10000000)//上升沿触发检测#define ADC_ExternalTrigConvEdge_Falling((uint32_t)0x20000000)//下降沿触发检测#define ADC_ExternalTrigConvEdge_RisingFalling ((uint32_t)0x30000000)//上升沿下降沿都检测 //ADC数据对齐方式#define ADC_DataAlign_Right((uint32_t)0x00000000)//右对齐#define ADC_DataAlign_Left((uint32_t)0x00000800)//左对齐//ADC规则序列长度//如果是单通道转换,参数为1 。 3.配置方法 3.1ADC初始化分步介绍 (1)定义结构体
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体变量ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDefADC_InitStructure;//定义ADC结构体 (2)初始化相关时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//初始化GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//初始化ADC时钟 (3)初始化GPIO结构体(设置为模拟输入)
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模拟输入模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//管脚设置 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//浮空 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化结构体 (4)初始化ADC配置结构体(通用控制寄存器CCR)
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频 。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36MhzADC_CommonInit(&ADC_CommonInitStructure);//初始化 (5)初始化ADC结构体
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化 (6)ADC使能
ADC_Cmd(ADC1, ENABLE);//开启AD转换器 3.2ADC初始化函数整体 /******************************************************************************** 函 数 名: ADCx_Init* 函数功能: ADC初始化 * 输入: 无* 输出: 无*******************************************************************************/void ADCx_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDefADC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模拟输入模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//管脚设置 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//浮空 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化结构体//RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);//ADC1复位 //RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE); //复位结束ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频 。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36MhzADC_CommonInit(&ADC_CommonInitStructure);//初始化ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化ADC_Cmd(ADC1, ENABLE);//开启AD转换器} 3.3设置指定ADC的规则组通道 void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime){uint32_t tmpreg1 = 0, tmpreg2 = 0;/* Check the parameters */assert_param(IS_ADC_ALL_PERIPH(ADCx));assert_param(IS_ADC_CHANNEL(ADC_Channel));assert_param(IS_ADC_REGULAR_RANK(Rank));assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime));/* if ADC_Channel_10 ... ADC_Channel_18 is selected */if (ADC_Channel > ADC_Channel_9){/* Get the old register value */tmpreg1 = ADCx->SMPR1;/* Calculate the mask to clear */tmpreg2 = SMPR1_SMP_SET << (3 * (ADC_Channel - 10));/* Clear the old sample time */tmpreg1 &= ~tmpreg2;/* Calculate the mask to set */tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10));/* Set the new sample time */tmpreg1 |= tmpreg2;/* Store the new register value */ADCx->SMPR1 = tmpreg1;}else /* ADC_Channel include in ADC_Channel_[0..9] */{/* Get the old register value */tmpreg1 = ADCx->SMPR2;/* Calculate the mask to clear */tmpreg2 = SMPR2_SMP_SET << (3 * ADC_Channel);/* Clear the old sample time */tmpreg1 &= ~tmpreg2;/* Calculate the mask to set */tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel);/* Set the new sample time */tmpreg1 |= tmpreg2;/* Store the new register value */ADCx->SMPR2 = tmpreg1;}/* For Rank 1 to 6 */if (Rank < 7){/* Get the old register value */tmpreg1 = ADCx->SQR3;/* Calculate the mask to clear */tmpreg2 = SQR3_SQ_SET << (5 * (Rank - 1));/* Clear the old SQx bits for the selected rank */tmpreg1 &= ~tmpreg2;/* Calculate the mask to set */tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1));/* Set the SQx bits for the selected rank */tmpreg1 |= tmpreg2;/* Store the new register value */ADCx->SQR3 = tmpreg1;}/* For Rank 7 to 12 */else if (Rank < 13){/* Get the old register value */tmpreg1 = ADCx->SQR2;/* Calculate the mask to clear */tmpreg2 = SQR2_SQ_SET << (5 * (Rank - 7));/* Clear the old SQx bits for the selected rank */tmpreg1 &= ~tmpreg2;/* Calculate the mask to set */tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7));/* Set the SQx bits for the selected rank */tmpreg1 |= tmpreg2;/* Store the new register value */ADCx->SQR2 = tmpreg1;}/* For Rank 13 to 16 */else{/* Get the old register value */tmpreg1 = ADCx->SQR1;/* Calculate the mask to clear */tmpreg2 = SQR1_SQ_SET << (5 * (Rank - 13));/* Clear the old SQx bits for the selected rank */tmpreg1 &= ~tmpreg2;/* Calculate the mask to set */tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13));/* Set the SQx bits for the selected rank */tmpreg1 |= tmpreg2;/* Store the new register value */ADCx->SQR1 = tmpreg1;}} 3.4获取转换数值 /******************************************************************************** 函 数 名: Get_ADC_Value* 函数功能: 获取通道ch的转换值,取times次,然后平均* 输入: ch:通道编号times:获取次数* 输出: 通道ch的times次转换结果平均值*******************************************************************************/u16 Get_ADC_Value(u8 ch,u8 times){ u32 temp_val=0; u8 t; //设置指定ADC的规则组通道,一个序列,采样时间 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles); //ADC1,ADC通道,480个周期,提高采样时间可以提高精确度for(t=0;t 讲解不到位的希望大家指出,有需要我讲解的部分,希望大家提出,我会出文档讲解 。
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
