STM32的ADC介绍

STM32的ADC精度是12位,它有18个通道,可以测量16路外部和2个内部信号源,各通道的A/D转换可以单次、连续、扫描或间断模式执行,ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
主要特征:
, 12-位分辨率
􀁺 转换结束,注入转换结束和发生模拟看门狗事件时产生中断
􀁺 单次和连续转换模式
􀁺 从通道0到通道n的自动扫描模式
􀁺 自校准
􀁺 带内嵌数据一致的数据对齐
􀁺 通道之间采样间隔可编程
􀁺 规则转换和注入转换均有外部触发选项
􀁺 间断模式
􀁺 双重模式(带2个ADC的器件)
􀁺 ADC转换速率1MHz
􀁺 ADC供电要求:2.4V到3.6V
􀁺 ADC输入范围:VREF- ≤ VIN ≤ VREF+
􀁺 规则通道转换期间有DMA请求产生。
关键点:12位分辨率,转换结束,注入转换结束和发生模拟看门狗事件时产生中断,供电要求2.4V到3.6V
ADC电压输入范围:ADC的电压输入范围是Vref-<= Vin<=Vref+;由VREF+,VREF-,VDDA,VSSA四个引脚决定
ADC时钟:
ADC时钟通过PCK2分频得到,最大是14MHZ,超过14MHZ读取ADC数值不准,可以是2/4/6/8分频
采样时间:采样周期最小是1.5个,此时采样最快。
ADC 的转换时间跟ADC 的输入时钟和采样时间有关,公式为:Tconv = 采样时间 +12.5 个周期。当ADCLK = 14MHZ (最高),采样时间设置为1.5 周期(最快),那么总的转换时间(最短)Tconv = 1.5 周期 + 12.5 周期 = 14 周期 = 1us。
在这里插入图片描述

中断读取ADC值:
ADC转换结束后可以产生中断,ADC的中断有三种:规则通道转换结束中断,注入转换通道
转换结束中断,模拟看门狗中断
转换结束中断:ADC中断和平常用的中断一样,要配置中断服务函数,有响应的中断标志位和中断使能位
模拟看门狗中断:当ADC数值高于或者低于某个阈值时产生中断,其中低阈值和高阈值由ADC_LTR 和ADC_HTR 设置
程序如下:

static void ADCx_Mode_Config(void)
{
	ADC_InitTypeDef ADC_InitStructure;	

	// ´ò¿ªADCʱÖÓ
	ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
	
	// ADC ģʽÅäÖÃ
	// ֻʹÓÃÒ»¸öADC£¬ÊôÓÚ¶ÀÁ¢Ä£Ê½
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	
	// ½ûֹɨÃèģʽ£¬¶àͨµÀ²ÅÒª£¬µ¥Í¨µÀ²»ÐèÒª
	ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 

	// Á¬Ðø×ª»»Ä£Ê½
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

	// ²»ÓÃÍⲿ´¥·¢×ª»»£¬Èí¼þ¿ªÆô¼´¿É
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

	// ת»»½á¹ûÓÒ¶ÔÆë
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	
	// ת»»Í¨µÀ1¸ö
	ADC_InitStructure.ADC_NbrOfChannel = 1;	
		
	// ³õʼ»¯ADC
	ADC_Init(ADCx, &ADC_InitStructure);
	
	// ÅäÖÃADCʱÖÓΪPCLK2µÄ8·ÖƵ£¬¼´9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 
	
	// ÅäÖà ADC ͨµÀת»»Ë³ÐòºÍ²ÉÑùʱ¼ä
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, 
	                         ADC_SampleTime_55Cycles5);
	
	// ADC ת»»½áÊø²úÉúÖжϣ¬ÔÚÖжϷþÎñ³ÌÐòÖжÁȡת»»Öµ
	ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
	
	// ¿ªÆôADC £¬²¢¿ªÊ¼×ª»»
	ADC_Cmd(ADCx, ENABLE);
	
	// ³õʼ»¯ADC У׼¼Ä´æÆ÷  
	ADC_ResetCalibration(ADCx);
	// µÈ´ýУ׼¼Ä´æÆ÷³õʼ»¯Íê³É
	while(ADC_GetResetCalibrationStatus(ADCx));
	
	// ADC¿ªÊ¼Ð£×¼
	ADC_StartCalibration(ADCx);
	// µÈ´ýУ׼Íê³É
	while(ADC_GetCalibrationStatus(ADCx));
	
	// ÓÉÓÚûÓвÉÓÃÍⲿ´¥·¢£¬ËùÒÔʹÓÃÈí¼þ´¥·¢ADCת»» 
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}

static void ADC_NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
	// ÓÅÏȼ¶·Ö×é
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  // ÅäÖÃÖжÏÓÅÏȼ¶
  NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

中断读取ADC

void ADC_IRQHandler(void)
{	
	if (ADC_GetITStatus(ADCx,ADC_IT_EOC)==SET) 
	{
		// ¶ÁÈ¡ADCµÄת»»Öµ
		ADC_ConvertedValue = ADC_GetConversionValue(ADCx);
	}
	ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
}

使用DMA读取ADC值:
规则和注入通道转换结束后,除了产生中断外,还可以产生DMA 请求,把转换好的数据直接存储在内存里面,只有ADC1和ADC3可以产生DMA请求

static void ADCx_Mode_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	ADC_InitTypeDef ADC_InitStructure;
	
	// ´ò¿ªDMAʱÖÓ
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	// ´ò¿ªADCʱÖÓ
	ADC_APBxClock_FUN ( ADC_CLK, ENABLE );
	
	// ¸´Î»DMA¿ØÖÆÆ÷
	DMA_DeInit(ADC_DMA_CHANNEL);
	
	// ÅäÖà DMA ³õʼ»¯½á¹¹Ìå
	// ÍâÉè»ùַΪ£ºADC Êý¾Ý¼Ä´æÆ÷µØÖ·
	DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADCx->DR ) );
	
	// ´æ´¢Æ÷µØÖ·£¬Êµ¼ÊÉϾÍÊÇÒ»¸öÄÚ²¿SRAMµÄ±äÁ¿
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;
	
	// Êý¾ÝÔ´À´×ÔÍâÉè
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	
	// »º³åÇø´óСΪ1£¬»º³åÇøµÄ´óСӦ¸ÃµÈÓÚ´æ´¢Æ÷µÄ´óС
	DMA_InitStructure.DMA_BufferSize = 1;
	
	// ÍâÉè¼Ä´æÆ÷Ö»ÓÐÒ»¸ö£¬µØÖ·²»ÓõÝÔö
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

	// ´æ´¢Æ÷µØÖ·¹Ì¶¨
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 
	
	// ÍâÉèÊý¾Ý´óСΪ°ë×Ö£¬¼´Á½¸ö×Ö½Ú
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	
	// ´æ´¢Æ÷Êý¾Ý´óСҲΪ°ë×Ö£¬¸úÍâÉèÊý¾Ý´óСÏàͬ
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	
	// Ñ­»·´«Êäģʽ
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	

	// DMA ´«ÊäͨµÀÓÅÏȼ¶Îª¸ß£¬µ±Ê¹ÓÃÒ»¸öDMAͨµÀʱ£¬ÓÅÏȼ¶ÉèÖò»Ó°Ïì
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	
	// ½ûÖ¹´æ´¢Æ÷µ½´æ´¢Æ÷ģʽ£¬ÒòΪÊÇ´ÓÍâÉèµ½´æ´¢Æ÷
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	
	// ³õʼ»¯DMA
	DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
	
	// ʹÄÜ DMA ͨµÀ
	DMA_Cmd(ADC_DMA_CHANNEL , ENABLE);
	
	// ADC ģʽÅäÖÃ
	// ֻʹÓÃÒ»¸öADC£¬ÊôÓÚµ¥Ä£Ê½
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	
	// ½ûֹɨÃèģʽ£¬¶àͨµÀ²ÅÒª£¬µ¥Í¨µÀ²»ÐèÒª
	ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 

	// Á¬Ðø×ª»»Ä£Ê½
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

	// ²»ÓÃÍⲿ´¥·¢×ª»»£¬Èí¼þ¿ªÆô¼´¿É
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

	// ת»»½á¹ûÓÒ¶ÔÆë
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	
	// ת»»Í¨µÀ1¸ö
	ADC_InitStructure.ADC_NbrOfChannel = 1;	
		
	// ³õʼ»¯ADC
	ADC_Init(ADCx, &ADC_InitStructure);
	
	// ÅäÖÃADCʱÖÓΪPCLK2µÄ8·ÖƵ£¬¼´9MHz
	RCC_ADCCLKConfig(RCC_PCLK2_Div8); 
	
	// ÅäÖà ADC ͨµÀת»»Ë³ÐòΪ1£¬µÚÒ»¸öת»»£¬²ÉÑùʱ¼äΪ55.5¸öʱÖÓÖÜÆÚ
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	
	// ʹÄÜADC DMA ÇëÇó
	ADC_DMACmd(ADCx, ENABLE);
	
	// ¿ªÆôADC £¬²¢¿ªÊ¼×ª»»
	ADC_Cmd(ADCx, ENABLE);
	
	// ³õʼ»¯ADC У׼¼Ä´æÆ÷  
	ADC_ResetCalibration(ADCx);
	// µÈ´ýУ׼¼Ä´æÆ÷³õʼ»¯Íê³É
	while(ADC_GetResetCalibrationStatus(ADCx));
	
	// ADC¿ªÊ¼Ð£×¼
	ADC_StartCalibration(ADCx);
	// µÈ´ýУ׼Íê³É
	while(ADC_GetCalibrationStatus(ADCx));
	
	// ÓÉÓÚûÓвÉÓÃÍⲿ´¥·¢£¬ËùÒÔʹÓÃÈí¼þ´¥·¢ADCת»» 
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值