个人技术分享

1.ADC在STM32进行数据采集时十分重要。通过ADC可以将外界的数字信号转换为模拟信号,以满足采样的需求。(资料参考于正点原子)

STM32 拥有 1~3 个 ADC ( STM32F101/102 系列只有 1 个 ADC ),这些 ADC 可以独立使用,
也可以使用双重模式(提高采样率)。 STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。
它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫
描或间断模式执行。 ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。
模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高 / 低阀值。
STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。 注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之 后,规则通道才得以继续转换。
配置ADC的基本步骤为:
(1)使能相应的时钟。
(2)配置相应的引脚和引脚对应的ADC。
(3)配置ADC的通道信息。
(4)进行ADC校准,并开启ADC。
2.ADC的相关寄存器:
(1) ADC 控制寄存器( ADC_CR1 和 ADC_CR2 ):
ADC_CR1:
ADC_CR2:
(2) ADC 采样事件寄存器( ADC_SMPR1 和 ADC_SMPR2 ):
ADC_SMPR1:
ADC_SMPR2:
(3) ADC 规则序列寄存器( ADC_SQR1~3 ):
(4) ADC 规则数据寄存器 (ADC_DR):
(5) ADC 状态寄存器( ADC_SR): 该寄存器保存了 ADC 转换时的各种状态。
3.代码:本文只展示adc和main部分的代码,完整的工程可结合前面的文章。
(1)adc.h:
#ifndef __ADC_H
#define __ADC_H

#include "stm32f10x.h"
#include <stdio.h>

void adc_init(void);

#endif

(2) adc.c

#include "adc.h"

void adc_init(void)
{
	//¶¨ÒåGPIOºÍADCÏà¹ØµÄ½á¹¹Ìå
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	//ʹÄÜGPIOAºÍADC1µÄʱÖÓ£º
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1,ENABLE);
	
	//ÉèÖÃADCµÄʱÖÓ£º
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);																//ÉèÖÃΪ6·ÖƵ£¬72/6=12£¬×î´ó²»Äܳ¬¹ý14M
	
	//ÅäÖÃPA1Òý½Å£º
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN;									//Ä£ÄâÊäÈë
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//ÅäÖÃADCµÄÏà¹ØÐÅÏ¢£º
	ADC_DeInit(ADC1);																															//¸´Î»ADC,ʹµÃADCµÄËùÓмĴæÆ÷µÄֵΪȱʡֵ
	ADC_InitStructure.ADC_Mode 								= ADC_Mode_Independent;							//ADCµÄ¹¤×÷ģʽ
	ADC_InitStructure.ADC_ScanConvMode 				= DISABLE;													//ÊÇ·ñɨÃ裬µ¥Í¨µÀʱ²»ÐèҪɨÃè
	ADC_InitStructure.ADC_ContinuousConvMode 	= DISABLE;													//ÊÇ·ñÁ¬Ðø×ª»»
	ADC_InitStructure.ADC_ExternalTrigConv		= ADC_ExternalTrigConv_None;				//ADCµÄ´¥·¢·½Ê½£¬ÕâÀïÑ¡ÔñÈí¼þ´¥·¢
	ADC_InitStructure.ADC_DataAlign 					= ADC_DataAlign_Right;							//Ö¸¶¨ADCÊý¾ÝÓÒ¶ÔÆë
	ADC_InitStructure.ADC_NbrOfChannel				= 1;																//ÉèÖÃADCÒª½øÐÐת»»µÄͨµÀÊýÁ¿
	
	ADC_Init(ADC1,&ADC_InitStructure);											//ÅäÖÃADC1µÄ³õʼ»¯
	ADC_Cmd(ADC1,ENABLE);																		//ʹÄÜADC1
	
	//ÉèÖÃADC1µÄ¹æÔòת»»Í¨µÀ£º
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);	//ADC1,ͨµÀ1£¬¹æÔòת»»Ë³ÐòΪ1£¬²ÉÑùʱ¼äΪ239.5¸öÖÜÆÚ
	
	//Ò»¶¨Òª½øÐÐУ׼£¬·ñÔò»áÓ°Ïì²ÉÑùµÄ׼ȷÐÔ
	ADC_ResetCalibration(ADC1);															//adc1¸´Î»Ð£×¼
	while(ADC_GetResetCalibrationStatus(ADC1));							//µÈ´ý¸´Î»Ð£×¼½áÊø
	
	ADC_StartCalibration(ADC1);															//¿ªÆôADCУ׼
	while(ADC_GetCalibrationStatus(ADC1));									//µÈ´ýУ׼Íê³É
	
	//ADC_SoftwareStartConvCmd(ADC1, ENABLE);									//Èí¼þ¿ªÆôADCת»»		
}


(3) main.c:

#include "stm32f10x.h"
#include "USART.h"
#include <stdio.h>
#include "adc.h"

extern u8 data;

int main(void)
{
	uint16_t adc;
	float temp;
	//ÖжÏÓÅÏȼ¶·Ö×飺
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//³õʼ»¯´®¿ÚUSART1:
	usart_init(9600);
	adc_init();
	
	while(1)
	{
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);									//Èí¼þ¿ªÆôADCת»»		
		while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC))						//µÈ´ýADCת»»Íê³É
		adc =  ADC_GetConversionValue(ADC1);										//»ñȡת»»½á¹û
		temp = (float)adc*(3.3/4096);		//3.3/4096Ϊ²ÉÑù¾«¶È£¬3.3vµÄÁ¿³Ì£¬12λADCÔòΪ4096.	
		printf("ADC = %f\r\n",temp);
	}
	return 0;
}


4. 运行结果:

5.总结:

本文介绍了STM32的ADC,在设计ADC采样时需要去了解相应的寄存器功能,然后利用结构体信息完成初始化。ADC在使用之前应该先进行校准,以提高采样的精确度。此外,需要注意在配置ADC的时钟时不能超过14M。