STM32速成笔记—ADC

一、什么是ADC
ADC(Analogto-Digital Converter)模拟数字转换器,是将模拟信号转换成数字信号的一种外设。比如某一个电阻两端的是一个模拟信号,单片机无法直接采集,此时需要ADC先将短租两端的电压这个模拟信号转化成数字信号,单片机才能够进行处理。

二、ADC的用途
ADC具有将模拟信号转换成数字信号的能力,比如将模拟的电压转换成数字信号,单片机进行处理。可以用作温度监测或者电流监测等方面,用途极广。

三、STM32F103ZET6的ADC

根据中文参考手册介绍,STM32F103ZET6单片机有3个12位ADC,共有18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。

3.1 ADC通道对应引脚

STM32F103ZET6的ADC各通道对应IO如下

通道    ADC1    ADC2    ADC3
通道0    PA0    PA0    PA0
通道1    PA1    PA1    PA1
通道2    PA2    PA2    PA2
通道3    PA3    PA3    PA3
通道4    PA4    PA4    PA4
通道5    PA5    PA5    PA5
通道6    PA6    PA6    PA6
通道7    PA7    PA7    PA7
通道8    PB0    PB0    PB0
通道9    PB1    PB1    PB1
通道10    PC0    PC0    PC0
通道11    PC1    PC1    PC1
通道12    PC2    PC2    PC2
通道13    PC3    PC3    PC3
通道14    PC4    PC4    PC4
通道15    PC5    PC5    PC5
通道10    内部温度传感器        
通道10    内部参考电压VREF        

3.2ADC时钟

ADC输入时钟ADC_CLK由APB2分频产生,最大值是14MHz。库函数提供了设置分频因子的函数

void RCC_ADCCLKConfig(uint32_t RCC_PCLK2)

 可选的分频因子有

#define RCC_PCLK2_Div2                   ((uint32_t)0x00000000)
#define RCC_PCLK2_Div4                   ((uint32_t)0x00004000)
#define RCC_PCLK2_Div6                   ((uint32_t)0x00008000)
#define RCC_PCLK2_Div8                   ((uint32_t)0x0000C000)

APB2总线时钟为72MHz,而ADC的最大工作频率为14MHz,所以,分频因子一般设置为6,这样ADC的输入时钟频率为12MHz。

3.3 ADC工作模式

根据中文参考手册介绍,STM32F1的ADC有三种工作模式

单次转换模式
单次转换模式下,ADC只执行一次转换。该模式既可通过设置ADC_CR2寄存器的ADON位(只适用于规则通道)启动也可通过外部触发启动(适用于规则通道或注入通道),这时CONT位为0。
连续转换模式
在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。
扫描模式

3.4 ADC转换时间

ADC的总转换时间与时钟频率有关,总转换时间 = 采样时间 + 12.5个周期。其中,采样时间最短为1.5个周期,也就是最短转换时间为14个时钟周期。使用软件触发时,可选择的采样时间如下

#define ADC_SampleTime_1Cycles5                    ((uint8_t)0x00)
#define ADC_SampleTime_7Cycles5                    ((uint8_t)0x01)
#define ADC_SampleTime_13Cycles5                   ((uint8_t)0x02)
#define ADC_SampleTime_28Cycles5                   ((uint8_t)0x03)
#define ADC_SampleTime_41Cycles5                   ((uint8_t)0x04)
#define ADC_SampleTime_55Cycles5                   ((uint8_t)0x05)
#define ADC_SampleTime_71Cycles5                   ((uint8_t)0x06)
#define ADC_SampleTime_239Cycles5                  ((uint8_t)0x07)

 

3.5 ADC校准

使能ADC后,需要对ADC进行校准。使用库函数开发时,提供了ADC校准的函数

	ADC_ResetCalibration(ADC1);//重置指定的ADC的校准寄存器
	while(ADC_GetResetCalibrationStatus(ADC1));//获取ADC重置校准寄存器的状态
	
	ADC_StartCalibration(ADC1);//开始指定ADC的校准状态
	while(ADC_GetCalibrationStatus(ADC1));//获取指定ADC的校准程序

3.6 ADC转换结果与实际电压的换算

获取到的AD转换结果并不是实际电压,如果想要得到实际电压,需要经过换算。上面介绍了,STM32的ADC为12位,也就是AD值取值范围为0~4095。采集电压范围为0到3.3V。AD值与实际电压之间存在比例关系。

实际电压 = (AD值 / 4095) * 3.3。单位为伏特(V)

四、ADC配置步骤

  • 使能GPIO时钟和ADC时钟,设置引脚为模拟输入
  • 设置ADC的分频因子
  • 初始化ADC参数,包括ADC工作模式,规则序列等
  • 使能ADC并校准
  • 触发AD转换,读取AD转换值

五、ADC配置程序

5.1 ADC初始化程序

这里以配置ADC1的通道1为例,给出ADC的配置例程,分频因子设置为6,单次转换模式,软件触发。

 

/*
 *==============================================================================
 *函数名称:ADC1_Init
 *函数功能:初始化ADCx
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void ADC1_Init(void)
{
	// 结构体定义
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1,ENABLE);
	
	// 设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	// GPIO配置
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;   //ADC1通道1
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;   // 模拟输入
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	// ADC参数配置
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;   // 独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;   // 非扫描模式	
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;   // 关闭连续转换
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;   // 禁止触发检测,使用软件触发
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;   // 右对齐	
	ADC_InitStructure.ADC_NbrOfChannel = 1;   // 1个转换在规则序列中 也就是只转换规则序列1 
	ADC_Init(ADC1, &ADC_InitStructure);   // ADC初始化
	
	ADC_Cmd(ADC1, ENABLE);   // 开启AD转换器
	
	// ADC校准
	ADC_ResetCalibration(ADC1);   // 重置指定的ADC的校准寄存器
	while(ADC_GetResetCalibrationStatus(ADC1));   // 获取ADC重置校准寄存器的状态
	
	ADC_StartCalibration(ADC1);   // 开始指定ADC的校准状态
	while(ADC_GetCalibrationStatus(ADC1));   // 获取指定ADC的校准程序

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);   // 使能或者失能指定的ADC的软件转换启动功能
}

5.2 软件触发AD转换

库函数开发,配置为软件触发时,可以通过下面的函数触发AD转换

void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)

5.3 读取AD转换结果

库函数提供了用于读取AD转换结果的函数

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)

这里给出另一个函数,用于软件触发AD转换并读取转换结果

/*
 *==============================================================================
 *函数名称:Get_ADC_Value
 *函数功能:读取某一规则通道AD值
 *输入参数:ch:规则通道ADC_Channel_x;times:读取次数
 *返回值:无
 *备  注:该函数配置好后,返回的结果是N次后的平均值
 *==============================================================================
 */
u16 Get_ADC_Value(u8 ch,u8 times)
{
	u32 temp_val = 0;
	u8 t;
	// 设置指定ADC的规则组通道,一个序列,采样时间
	// ADC1,ADC通道,239.5个周期,提高采样时间可以提高精确度
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5);			    
	
	for(t=0;t<times;t++)
	{
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);   // 使能指定的ADC1的软件转换启动功能	
		while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));   // 等待转换结束
		temp_val+=ADC_GetConversionValue(ADC1);
		delay_ms(5);
	}
	return temp_val/times;
} 

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值