STM32-(29):ADC模数转换(实验)

上一篇:STM32-(28):ADC模数转换(理论分析) 下一篇:STM32-(30):内部温度传感器

ADC的重要寄存器介绍

STM32-(29):ADC模数转换(实验)_第1张图片
AWDEN:在规则通道上开启模拟看门狗
该位由软件设置和清除。
0:在规则通道上禁用模拟看门狗
1:在规则通道上使用模拟看门狗

DUALMOD[3:0]:双模式选择
软件使用这些位选择操作模式
STM32-(29):ADC模数转换(实验)_第2张图片
SCAN:扫描模式
该位由软件设置和清除,用于开启或关闭扫描模式。在扫描模式中,由ADC_SQRx或ADC_JSQRx寄存器选中的通道被转换。
0:关闭扫描模式
1:使用扫描模式
注:如果分别设置了EOCIE或JEOCIE位,只在最后一个通道转换完毕才会产生EOC或JEOC中断。

JEOCIE:允许产生注入通道转换结束中断
该位由软件设置和清除,用于禁止或允许所有注入通道转换结束后产生中断。
0:禁止JEOC中断
1:允许JEOC中断。当硬件设置JEOC位时产生中断。

EOCIE:允许产生EOC中断
该位由软件设置和清除,用于禁止或允许转换结束后产生中断。
0:禁止EOC中断
1:允许EOC中断。当硬件设置EOC位时产生中断。

AWDCH[4:0]:模拟看门狗通道选择位
STM32-(29):ADC模数转换(实验)_第3张图片
注意:STM32的内部参照电压VREFINT和ADCx_IN17相连接,它的作用是相当于一个标准电压测量点,内部参照电压VREFINT只能出现在主ADC1中使用。
STM32-(29):ADC模数转换(实验)_第4张图片
ADCON 位用于开关 AD 转换器。而 CONT 位用于设置是否进行连续转换,我们使用单次转换,所以 CONT 位必须为0。 CAL 和 RSTCAL 用于 AD 校准 。ALIGN用于设置数据对齐,我们使用右对齐,该位设置为0。

EXTSEL [2:0] 用于选择启动规则转换组转换的外部事件。
STM32-(29):ADC模数转换(实验)_第5张图片
使用的是软件触发(SWSTART),所以设罝这3个位为111,ADC_CR2的SWSTART位用于开始规则通道的转换,我们每次转换(单次转换模式下)都需要向该位写1。TSVREFE为用于使能温度传感器和 Vref.

STM32-(29):ADC模数转换(实验)_第6张图片

时间计算

对于毎个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降低ADC的转换速率,ADC的转换时间可以由下式计算:
Tcovn=采样时间+12.5个周期(12.5是量化周期,固定的,采用逐次逼近)
其中:Tcovn为总转换时间, 采样时间是根据毎个通道的SMP位的设置来决定的.例如,当ADCCLK=14Mhz的时候,并设置 1.5个周期的采样时间,则得到:Tcovn=l.5+12.5=14个周期=1 us. 采样越慢,精度越高,因为抗干扰能力越强。

STM32-(29):ADC模数转换(实验)_第7张图片
ADC_SQR2、3是定义余下的转换

STM32-(29):ADC模数转换(实验)_第8张图片
规则序列中的AD转化结果都被存在这个寄存器里面,而注入通道的转换结果被保存在ADC_JDRx里面。
该寄存器的数据可以通过 ADC_CR2的ALIGN 位设置左对齐还是右对齐,在读取数据的时候要注意。

STM32-(29):ADC模数转换(实验)_第9张图片
STM32-(29):ADC模数转换(实验)_第10张图片

实验

单次转换出电压数据,JP2跳到滑动电阻端,测量数据显示在数码管上。
STM32-(29):ADC模数转换(实验)_第11张图片
STM32-(29):ADC模数转换(实验)_第12张图片
STM32-(29):ADC模数转换(实验)_第13张图片
** ADC2连接的是CPU上的PC5,输入通道15(IN15)**

简析:右下角的ADC2 是外部给的信号,JP2连接到滑动变阻器一端时,可以通过改变滑动变阻器的位置,改变出来的电压。R36的作用是限流,防止外部给的信号电流过大。VIN2是外部测量使用的,用于校对电压值是否准确。

ADC1扩展

STM32-(29):ADC模数转换(实验)_第14张图片
ADC1与ADC2相比多了一个U5 数字电位器,可以将外部电压按比例降低,这样就可以测量更宽范围的电压。

代码:

main.c

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"	  //包含了所有的头文件 它是唯一一个用户需要包括在自己应用中的文件,起到应用和库之间界面的作用。
#include 
 
void Delay_Ms(u16 time);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

extern void ADC_Configuration(void);
extern u16 Test_ConversionResult(void);
extern void SMG_Init(void);
extern void NumbTube_Display(u32 data,u8 radix_point);

/* Private functions ---------------------------------------------------------*/ 
/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
int main(void)
{
	#ifdef DEBUG
  	debug();
	#endif

	u32 ConversionValue;
  	RCC_Configuration();    //使能外设时钟
	NVIC_Configuration();
	SMG_Init(); //数码管初始化
	ADC_Configuration(); //ADC初始化
 // 	GPIO_Configuration();   //初始化GPIO管脚

  	while (1)
  	{
		ConversionValue = (u32)Test_ConversionResult();

		//ConversionValue = ConversionValue * 1000; 
		
		NumbTube_Display(ConversionValue,4);		//在数码管中显示,第二个参数4是指位数
  	}
}

/*******************************************************************************
* Function Name  : Delay_Ms
* Description    : delay 1 ms.
* Input          : time (ms)
* Output         : None
* Return         : None
*******************************************************************************/
void Delay_Ms(u16 time)  //延时函数
{ 
	u16 i,j;
	for(i=0;i0;j--);
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void) 
{
	//=============================== 使用内部RC晶振 ===================================
    /*   
	RCC_HSICmd(ENABLE);//使能内部高速晶振 ;
 	RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//选择内部高速时钟作为系统时钟SYSCLOCK=8MHZ	
	RCC_HCLKConfig(RCC_SYSCLK_Div1);//选择HCLK时钟源为系统时钟SYYSCLOCK
  	RCC_PCLK1Config(RCC_HCLK_Div4);//APB1时钟为2M 
  	RCC_PCLK2Config(RCC_HCLK_Div4);//APB2时钟为2M
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);//使能APB2外设GPIOB时钟
	*/

	//==========================使用外部RC晶振========================================
  	RCC_DeInit();				//初始化为缺省状态
  	RCC_HSEConfig(RCC_HSE_ON);  //高速时钟使能
  	while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);  //等待高速时钟使能就绪

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	//Enable Prefetch Buffer 
    FLASH_SetLatency(FLASH_Latency_2);	  					// Flash 2 wait state 
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 						// HCLK = SYSCLK 
    RCC_PCLK2Config(RCC_HCLK_Div1);							// PCLK2 = HCLK 
    RCC_PCLK1Config(RCC_HCLK_Div2);	  						// PCLK1 = HCLK/2 
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);	// PLLCLK = 8MHz * 9 = 72 MHz  
    RCC_PLLCmd(ENABLE);	  									// Enable PLL 
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);		// Wait till PLL is ready 

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	  			// Select PLL as system clock source 
    while(RCC_GetSYSCLKSource() != 0x08);					// Wait till PLL is used as system clock source 

	//====================================================================================
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);	// 使能APB2外设GPIOC时钟
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : 初始化GPIO外设
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void GPIO_Configuration(void)
{

  	GPIO_InitTypeDef GPIO_InitStructure;	// 声明一个结构体变量
    //==========为结构体成员填入相应的值============
  	GPIO_InitStructure.GPIO_Pin	= GPIO_Pin_3;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//管脚频率为50MHZ
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//模式为推挽输出
  	GPIO_Init(GPIOA, &GPIO_InitStructure);   			//初始化GPIOB寄存器
}

void NVIC_Configuration(void)
{
   
#ifdef  VECT_TAB_RAM  
  	NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
#else
  	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif
}

ADC.c

#include"stm32f10x_lib.h"

/***********************************************************
* 函数名称:void ADC_Configuration(void)
* 功能描述:ADC模数转换
* 入口参数:无
* 出口参数:无
***********************************************************/
void ADC_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	  //开启ADC1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);  //开启GPIOC的时钟
  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;		 //PC5
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //配置成模拟输入
	GPIO_Init(GPIOC,&GPIO_InitStructure);

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	 //独立模式
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;	 //连续多通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不受外界决定,设为软件触发
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	 //扫描通道数1
	ADC_Init(ADC1,&ADC_InitStructure);
					
	ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 1, ADC_SampleTime_55Cycles5);
	//ADC1,   设定指定ADC的规则组通道15,顺序排在第一个,也只有一个,采样周期为55.5个周期
	//ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 2, ADC_SampleTime_1Cycles5);//ADC1,
	ADC_Cmd(ADC1,ENABLE); //使能指定ADC
	ADC_SoftwareStartConvCmd(ADC1,ENABLE); //使能指定ADC的软件装换启动功能。

}
/***********************************************************
* 函数名称:u16 Test_ConversionResult(void)
* 功能描述:测试ADC转换的结果,通过数码管显示ADC采样的值
* 入口参数:无
* 出口参数: conresult
								ADC转换的结果
***********************************************************/
u16 Test_ConversionResult(void)
{
	u32 conresult=0;
	u16 value;
	if(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==SET)  //如果EOC置1,等于SET,说明转换完成
	{
		conresult = (u32)ADC_GetConversionValue(ADC1); //返回最近一次ADC组的转换结果
		//2(12)=4096    VDD3.3v=3300mv  (右对齐,存储结果为12位,2的12次方为4096,均分3.3V)

		conresult = conresult * 3300;
		conresult = conresult / 4096;				//先乘后除不容易丧失精度
	}
	ADC_ClearITPendingBit(ADC1,ADC_IT_EOC); //清除ADC的中断
	return((u16)conresult);	
}

相关固件函数:
STM32-(29):ADC模数转换(实验)_第15张图片

上一篇:STM32-(28):ADC模数转换(理论分析) 下一篇:STM32-(30):内部温度传感器

你可能感兴趣的:(STM32-(29):ADC模数转换(实验))