如何使用STM32进行ADC转换

ADC(Analog-Digital Converter)为模拟-数字转换器,可以将引脚上连续变化的电压值等效为数字变量。

12位为其分辨率0~2^12-1,将能够检测到的电压范围通过线性等效为0-4095其中的一个数字变量,分辨率越高越精确。

1us为转换时间

实现原理:

通过通道选择开关选择输入引脚,然后通过编码DAC实现等效电压,然后将引脚输入电压与编码产生的电压相比较。通过2分法查找,直到编码电压与引脚输入电压相等,此时引脚输入电压的编码就和预编码相同。

一般将参考电压与VDDA,VSSA模拟电源相连。需要时钟使能和START开始信号。转换结束会将EOC信号置位。

输入通道可选外部输入和内部输入,并且可以选择进入规则组还是注入组。

规则组可以同时转换16个通道,但是只有一个数据寄存器,也就是只能输出一个数据。可以通过DMA寄存器缓存。

注入组可以同时转换4个通道,且有4个数据寄存器,即可以输出四个数据。

触发源的选择可以选择软件触发和硬件触发,如果为软件触发需要随时进中断,比较影响效率。

 

需要配置GPIO口,ADC转换器,时钟使能,中断。

转换模式的介绍:连续/单次—-扫描/非扫描  排列组合共有四种转换模式

连续转换,非扫描模式,只能选择一个通道,触发一次即可,每次转换之间不需要对EOC进行操作,进行一次转换后接着进行下一次转换,需要读取值的时候直接读就行。

单次转换,扫描模式:扫描即可进行多个通道的转换,单次即在每次的所有通道都转换结束后,EOC置位,本次转换结束,需要再次触发才能开始下一次的转换。

总而言之,单次/连续 对应着是否能够连续不断的进行转换

扫描/非扫描  即每次转换可以转换多少个通道。

 

数据有两种对齐方式,一般选择右对齐,不会改变读取值

如果对应精度要求不太高,可以选择左对齐然后把前8位取出来进行比较,这样就是舍弃了后四位的精度。 

 

代码部分:

首先配置输入GPIO和ADC1的时钟

然后配置ADC1转换器的预分频值。

然后配置GPIO的模式,这里注意选择GPIO_PIN_AIN,该模式为模拟输入的专属模式

然后配置ADC1转换器,使能

校准部分

与ADC相关的取值函数,如果只需要一个通道,那么可以在ADC初始化函数中选择通道和他的规则组模式。如果需要多个通道,则需要给ADC取值函数一个形参用于确定需要转换的通道。然后利用该参数选择当前转换的通道和规则组模式。然后触发转换,直到转换结束会产生信号EOC,如果EOC置位了就可以将该值返回出去。

ADC模块相关函数
void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;  //ADC专属模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;
	GPIO_Init(GPIOA,&GPIO_InitStructure);


	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;  //连续扫描  扫描enable/非扫描
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
	ADC_InitStructure.ADC_NbrOfChannel=1;  //通道数目
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;  //扫描模式,连续enable/单次
	
	ADC_Init(ADC1,&ADC_InitStructure);
	
	ADC_Cmd(ADC1,ENABLE);
	
	//校准部分
	ADC_ResetCalibration(ADC1);
	while (ADC_GetResetCalibrationStatus(ADC1)==SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1)==SET);
	
	
}

uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_55Cycles5);  //规则组模式选择,通道选择
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);  //软件触发
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);   //规则组转换完成
	ADC_GetConversionValue(ADC1);
}   



主函数调用函数:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "AD.h"
uint8_t Keynum;
uint16_t AD0;  
uint16_t AD1;
uint16_t AD2;
uint16_t AD3;

int main()
{
	OLED_Init();

	AD_Init();
	OLED_ShowString(1,1,"AD0:");
	OLED_ShowString(2,1,"AD1:");
	OLED_ShowString(3,1,"AD2:");
	OLED_ShowString(4,1,"AD3:");
	while(1)
		{
			AD0=AD_GetValue(ADC_Channel_0);  //传不同的通道进去
			AD1=AD_GetValue(ADC_Channel_1);
			AD2=AD_GetValue(ADC_Channel_2);
			AD3=AD_GetValue(ADC_Channel_3);
			OLED_ShowNum(1,5,AD0,4);
			OLED_ShowNum(2,5,AD1,4);
			OLED_ShowNum(3,5,AD2,4);
			OLED_ShowNum(4,5,AD3,4);
			Delay_ms(100);
		}
		
}

物联沃分享整理
物联沃-IOTWORD物联网 » 如何使用STM32进行ADC转换

发表评论