STM32——ADC模数转换器

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一,ADC简介

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

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

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

  • 输入电压范围:03.3V,转换结果范围:04095

  • 18个输入通道,可测量16个外部(最大16个)和2个内部信号源

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

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

    STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道。
    在这里插入图片描述
    依次介绍
    左侧是ADC的输入通道,包括16个GPIO口,两个内部通道。通过模拟多路开关,选择我们需要的通道。
    规则组一次可最多选16个通道,但数据寄存器只有16位,故每个通道的更新数据会覆盖前一个通道的更新数据数据(需使用DMA及时搬运数据,防止数据被覆盖)。
    注入组一次最多可选4个通道,数据寄存器有4*16位,可同时读取四个通道的数据。

触发转换信号:分为两种
一种为软件触发(使用库函数实现)
一种为硬件触发,主要来自定时器的各个通道和外部中断触发引脚,还有TRGO定时器主模式的输出。
优点:每隔一段时间,实现ADC更新一次时,不用频繁进入中断,使用硬件自动触发。

VREF+,VREF- ADC参考电压
VDDA,VSSA ADC供电电压
通常互接,使参考电压与供电电压相等。
在这里插入图片描述
ADCCLK:ADC时钟,推动ADC进行逐次比较获得数字信号,最大为14MHZ,由APB2时钟72MHZ经过ADC预分频器获得。

模拟看门狗:存有阈值高限和阈值低限。启功后,一旦数据寄存器的值在阈值范围之外,看门狗就会申请中断,执行中断函数

EOC:规则组完成信号,规则组完成转换完成后,置标志位。
JEOC:注入组完成信号,注入组完成转换完成后,置标志位。
AWD:模拟看门狗事件,转换结果高于阈值时,置标志位。
上述信号都可触发中断。

转换模式(规则组)

单次转换,非扫描模式。
非扫描模式下,规则组16个可选通道中只有第一个通道有效。
我们可在序列一的位置转换我们想要选择的通道,触发信号发生后,ADC就会对这个通道的数据进行模数转换,完成之后EOC置一,我们可判断EOC标志位,如果转换完成我们可在数据寄存器中读取结果。
再次转换需要再次触发。
如果想换一个通道转换,可把原来序列一的通道换成另一个通道(可实现多通道转换)。

连续转换,非扫描模式。
与上一个模式相比,该模式会立刻进行下一次转换,不需每次转换前都发生一次触发信号,只在第一次发生触发信号即可,也不用判断是否结束,直接读取即可。

单次转换,扫描模式
与第一个相比,我们一次可选择多个通道(需指定一共的通道数),扫描各个通道,进行模数转换,但下一个数据会覆盖上一个数据。

连续转换,扫描模式
与上一个模式相比,该模式会立刻进行下一次转换,不需每次转换前都发生一次触发信号,只在第一次发生触发信号即可,也不用判断是否结束,直接读取即可。

数据对齐

在这里插入图片描述
数据寄存器是16位的,但ADC数模转换器的12位的,这会造成左右对齐不同时,数据不同。
右对齐:高四位为0,为真实值。(常用)
左对齐:第四位为0,可降低分辨率(使用时,只取出高八位)。

转换时间

在这里插入图片描述
量化,编码:ADC逐次比较的过程.
采样,保持:ADC转换数据的过程中是需要一段时间的,如果在这段时间内,输入的电压还在不断变化,那就可能造成数据的遗失(对于一串连续的波形,遗失了一部分,无法准确定位读取位置)。
故我们在转换过程中,使用电容和开关,存储这段电压,当转换完成时,再输出这段电压(这段过程产生了采样时间)。
采样时间越大,越能避免一些毛刺信号的干扰。

校准

在这里插入图片描述
无需了解太多,初始化后执行几段代码即可。

二,程序配置

第一步:开启RCC时钟,GPIO,ADC;ADCCLK分频器配置。
第二部:配置GPIO为模拟输入。
第三步:配置多路开关,选择通道进入ADC中。
第四步:配置ADC转化器,结构体配置。
第五步:开关控制,开始ADC;进行校准。

ADC相关库函数介绍

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);//配置ADCLK预分频器,可以对APB2时钟进行2,4,6,8分频,输入到ADCCLK中。(RCC库函数中)

void ADC_DeInit(ADC_TypeDef* ADCx);//恢复初始配置
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);//初始化配置ADC
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);//配置结构体参数为默认值

void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);//开启ADC
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);//开启DMA输出信号,可用来使用DMA转运数据。
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);//中断控制

/*校准函数*/
void ADC_ResetCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);
void ADC_StartCalibration(ADC_TypeDef* ADCx);
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);
//ADC初始化后依次调用即可

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//ADC软件开始转换配置

/*间断模式*/
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);//每隔几个通道间断一次
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//是否开启间断


void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);//ADC规则组通道配置
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//ADC外部触发转换配置
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);//ADC获取转换值
uint32_t ADC_GetDualModeConversionValue(void);//ADC获取双模式转换值
/*模拟看门狗*/
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);//是否启动模拟看门狗
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);//配置高低阈值
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);//配置看门的通道


void ADC_TempSensorVrefintCmd(FunctionalState NewState);//开启内部通道(两个内部通道使用时,必须调用此函数)


FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);//获取标志位状态
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);//清除标志位
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);//获取中断标志位
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);//清除中断标志位



配置流程

第一步:开启时钟;配置ADCCLK预分频器系数

/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/*配置ADCCLK预分频系数*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);

第二步:配置GPIO

/*配置GPIO*/
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;//配置位模拟输入模式
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0; 
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);

第三步:配置多路开关,选择通道进入ADC中。

ADC_RegularChannelConfig(ADC1,ADC_Channel_1, 0, ADC_SampleTime_55Cycles5);//规则组序列1的位置,配置为通道0
//多通道配置时,此函数可在ADC_Init()中省略,在取值函数中每次重新配置序列数,以读取不同通道的值。(我们仍然使用的是单次,非扫描模式来实现的ADC多通道读取模拟值。)

第四步:配置ADC转化器,结构体配置。

/*配置ADC转化器*/
	ADC_InitTypeDef ADC_InitStruct;
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//独立模式
	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right ;//右对齐模式
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//软件触发
	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;//非连续模式
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;//非扫描模式
	ADC_InitStruct.ADC_NbrOfChannel=1;
	
	ADC_Init(ADC1,&ADC_InitStruct);

第五步:开关控制,开始ADC;进行校准。

	/*开启ADC*/
	ADC_Cmd(ADC1, ENABLE);
	
	/*ADC校准*/
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1)==SET);//等待是否校准完成
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1)==SET);

取值函数

/*单通道取值*/
uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//软件触发AD转换一次(对应上文的单词,非连续模式,每次取值前软件重新触发)
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//等待EOC标志位,即等待AD转换结束
	return ADC_GetConversionValue(ADC1);					//读数据寄存器,得到AD转换的结果
}

/*多通道取值*/
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);	//在每次转换前,根据函数形参灵活更改规则组的通道1
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//软件触发AD转换一次
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//等待EOC标志位,即等待AD转换结束
	return ADC_GetConversionValue(ADC1);					//读数据寄存器,得到AD转换的结果
}
//上文ADC初始化,是单通道的初始化;多通道配置多通道取值函数,再使能几个引脚即可。
  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值