STM32 ADC

1.什么是ADC
ADC指模数转换,模拟信号是指时间幅值均连续的信号,对其采样后得到的信号称之为离散时间信号,若再对其进行量化处理则得到数字信号。请注意对模拟信号采样得到的信号不是数字信号,仅仅是离散时间信号。(详情请见数字电子电路,信号与系统,数字信号处理等教材)

2.分辨率
当前的STM32的ADC芯片是12位的,如果参考电压是3.3v那就是说最小量化间隔就是3.3的4096分之一,如果变化量低于一个最小量化间隔则在量化时相对于上一刻无变化。故3.3的4096分之一就是STM32的ADC的分辨率。

3.连续转换,单次转换,扫描模式
一个ADC控制器最多有18个通道,在非扫描模式下是对一个通道进行转换,如果是的单次转换则会在EOC之后停止转换直到再次被触发,如果是连续转换则在一次EOC后立刻进行下次转换;如果是扫描模式则是多多通道进行转换,比如有10个通道,按照顺序依次转换,十个通道均转换完成后视其是单次转换模式还是连续转换模式,如果是连续转换模式则立即进行下一轮转换,如果是单次转换则等待下次触发。

注:扫描模式下每完成一个通道的转换都会把对应通道的EOC标志置位,但EOC中断是在整个一轮转换都完成后触发。规则组通道的数据在ADC_DR寄存器内,注入组的数据在ADC_DRJ寄存器内。如果设置了DMA的位则会在每次转换完成后把规则组的数据传入SRAM,注入组的仍然在ADC_DRJ寄存器内。

4.举例:用ADC测量3.3v电压(即参考电压)
配置:单通道单次转换。(虽然是单次转换也可以搞出连续转换的效果)

//1.main.c
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include "adc.h"
#include "usart.h"
int main()
{
	u16 temp;
	float val;
	delay_init();
	my_adc_init();
	uart_init(115200);
	while(1)
	{
		temp=adc_get_val();
		val=(3.3/4096)*temp;
		printf("ADC:%d  转换值:%f\n",temp,val);
		delay_ms(1000);
	}
}
//2.ADC.C
#include "adc.h"
#include "stm32f10x.h"
	void my_adc_init()
	{
		ADC_InitTypeDef ADC_InitType;
		GPIO_InitTypeDef GPIO_InitType;
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
		
		GPIO_InitType.GPIO_Mode=GPIO_Mode_AIN;
		GPIO_InitType.GPIO_Pin=GPIO_Pin_1;
		GPIO_InitType.GPIO_Speed=GPIO_Speed_50MHz;
		GPIO_Init(GPIOA,&GPIO_InitType);
		
		RCC_ADCCLKConfig(RCC_PCLK2_Div6);
		ADC_DeInit(ADC1);
		
		ADC_InitType.ADC_ContinuousConvMode=DISABLE;//单次转换
		ADC_InitType.ADC_DataAlign=ADC_DataAlign_Right;
		ADC_InitType.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
		ADC_InitType.ADC_Mode=ADC_Mode_Independent;
		ADC_InitType.ADC_NbrOfChannel=1;
		ADC_InitType.ADC_ScanConvMode=DISABLE;//不开启扫描模式
		ADC_Init(ADC1,&ADC_InitType);
		
		ADC_Cmd(ADC1,ENABLE);
		
		ADC_ResetCalibration(ADC1);//复位校准
		while(ADC_GetResetCalibrationStatus(ADC1));
		
		ADC_StartCalibration(ADC1);//AD校准
		while(ADC_GetCalibrationStatus(ADC1));
		
	}
	
	u16 adc_get_val()
	{
		ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);
		ADC_SoftwareStartConvCmd(ADC1,ENABLE);
		
		while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
		ADC_ClearFlag(ADC1,ADC_FLAG_EOC);//清除或不清除都不影响,但如果是中断标志位的话必须清除
		return ADC_GetConversionValue(ADC1);
	}
	
	
//3.ADC.h
#ifndef adc_h
	#define adc_h
	#include "stm32f10x.h"
	void my_adc_init();
	u16 adc_get_val();
	
#endif

结果:
STM32 ADC_第1张图片
这里使用的是PA1,在PA1悬空时可以看到结果是飘忽不定的,当PA1接3.3v时转换结果几乎就是3.3,接地是基本就是0。

5.为什么单次转换能够连续工作:
奥秘在于adc.c下的adc_get_val()函数。该函数是在main.c的while循环里被调用的,每调用一次就会设置一次规则通道配置以及软件触发转换使能
STM32 ADC_第2张图片
如果把这两行放到my_adc_init()里面执行就是转换一次就停止了。

你可能感兴趣的:(STM32)