STM32 ADC的使用

本例程测量的是PB0口的电压
1、配置ADC使用的GPIO口
STM32 ADC的使用_第1张图片

void ADC_GPIO_Config()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输出PB0
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

2、配置ADC1

void ADC1_Config()
{
	//使用ADC1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	
	//ADC1模式配置
	ADC1_InitStructure.ADC_ContinuousConvMode = ENABLE;
	ADC1_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC1_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//配置TIM2_CC2为触发源
	ADC1_InitStructure.ADC_Mode = ADC_Mode_Independent;
	ADC1_InitStructure.ADC_NbrOfChannel = 1;
	ADC1_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_Init(ADC1,&ADC1_InitStructure);
	
	//配置ADC转换时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div2);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_55Cycles5);
	
	//使能ADC的DMA模块
	ADC_DMACmd(ADC1,ENABLE);
	ADC_Cmd(ADC1,ENABLE);
	
	/* 复位校准寄存器 */
	ADC_ResetCalibration(ADC1);
	/* 等待校准寄存器复位完成 */
	while(ADC_GetResetCalibrationStatus(ADC1));
	//开始ADC1的校准
	ADC_StartCalibration(ADC1);
	//等待ADC1校准完成
	while(ADC_GetCalibrationStatus(ADC1));
	//使用外部触发模式使能
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}

ADC模式配置说明:
1)ADC_Mode :STM32 具有多个ADC,而不同的ADC又是共同通道的,当两个ADC采集同一个通道的先后顺序、时间间隔不同时,就演变出各种各样的模式,如同步注入模式、通不规则模式等10种模式,应选择适当的模式应适应数据采集的要求。
2)ADC_ScanConvMode :当有多个通道需要采集信号时,可以把ADC配置为按照一定顺序对各个通道进行扫描转换,即轮流采集各个通道的值。若采集多个通道,必须开启此模式。
3)ADC_ContinuousConvMode :连续转换模式。此模式与单次转换模式相反,单次转换模式只采集以此ADC数据就停止转换了,而连续采集模式则是在上一次ADC转换完成之后,立即开启下一次的转换。
4)ADC_ExternalTrigConv :ADC需要在收到外部触发信号之后才能开始转换,如外部中断信号、定时器触发,这两个信号为外部触发信号。,如果不能使用外部触发信号,可以使用外部软件触发(ADC_ExternalTrigConv_None)。
5)ADC_DataAlign :ADC数据对齐方式,ADC转换之后的数值被保存在数据寄存器之中(ADC_DR的015或者1632位当中)
左对齐 —> ADC转换数值的最高位与存储区的最高位相对齐,即D12对Bit15
右对齐 —> ADC转换数值的最低位与存储区的最低位相对其,即D0对Bit0
6)ADC_NbrOfChannel :保存进行ADC数据转换的通道数。可以为1~16个

ADC时钟配置说明:
1)ADC时钟有上限,即不能超过14MHz;
使用RCC_ADCCLKConfig(分频值)进行配置
分频值为:

分频值 数值
RCC_PCLK2_Div2 ADC_clock = PCLK2/2
RCC_PCLK2_Div4 ADC_clock = PCLK2/4
RCC_PCLK2_Div6 ADC_clock = PCLK2/6
RCC_PCLK2_Div8 ADC_clock = PCLK2/8

当PCLK2为72MHz时,考虑到ADC_Clk需要低于14MHz,所以分频值应该为RCC_PCLK2_Div6
2)ADC_RegularChannelConfig()。ADC转换速率不只与时钟有关系,还与采样周期相关。每个ADC通道都可以使用不同的采样周期
STM32 ADC的使用_第2张图片
函数参数说明:

  • Rank:针对多通道采集而言的,比如对于1、4、7通道而言,如果他们的Rank值被分别配置为3、2、1,那么扫描顺序就是先7,后4,最后是1
  • ADC-SampleTime:用于配置本通道的采样周期,最短可配置为1.5个采样周期。这里的周期指的是ADC_CLK的时钟周期。

STM32ADC采样时间计算公式:TCONV = 采样周期 + 12.5个ADC时钟周期
其中采样周期就是指ADC_RegularChannelConfig()所配置的周期。
所以,本案例的ADC转换时间为TCONV = (55.5+12.5)*1/12 ~= 5.67us

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

3、电压数值量化
case1:对于64PIN以下的STM32系列,其VREF与VDDA内部相连接,所以参考电压为3.3V。
此时,电压量化计算公式应该是:
SendBuff1 = SendBuff*3.3/4096;//参考电压

case2:对于100PIN以及以上的STM32系列而言,其单独引出VREF,可以使用外部基准IC作为参考电压,例如使用2.5V的基准IC,
此时,电压应该为:
SendBuff1 = SendBuff2.5/4096;//参考电压
STM32 ADC的使用_第3张图片
case3:使用STM32内部参考电压,先读取该值,在比较计算
adc电压计算 Vread =(Adc(readx)/4096(根据ADC位数不同,此处值不同))
Vref。读取通道17,因为是个定值,所以可以计算出Vref = 1.24096/Adc(read17)); 任意通道的电压值 Vread = (Adc(readx)/4096)(1.24096/adc(read17))) = 1.2Adc(readx)/Adc(read17)
STM32 ADC的使用_第4张图片

参考文献:
【1】STM32 ADC的基本原理、寄存器(超基础、详细版)
【2】STM32 ADC转换时间

你可能感兴趣的:(STM32单片机开发)