ARM嵌入式学习笔记(九) ADC电压采集

1.前言

上一篇文章介绍了USART串口通信的内容,这篇文章我们来介绍一下STM32单片机中的ADC采集部分,并且使用串口与上位机进行通信,显示采集的电压值。同样地,我们所使用的硬件设备仍然是STM32RCT6单片机等基础设备,关于单片机的原理图在前文均已详细介绍,这里我们就不再赘述。

2.ADC详解

定义

ADC是模拟到数字转换器(Analog-to-Digital Converter)的缩写。它是一种电子设备或模块,用于将连续变化的模拟信号转换为离散的数字信号,以便数字系统(如微处理器、微控制器等)能够对其进行处理和分析。

模拟信号是连续变化的电压或电流信号,其数值在一定范围内变化。而数字信号是由一系列离散的数字表示,只能取有限的值,通常以二进制形式表示。

工作原理

ADC的工作原理是将模拟信号分割成一系列离散的取样,并将每个取样值转换为相应的数字表示。这个过程涉及到两个主要步骤:采样和量化。

采样:ADC将连续变化的模拟信号在一定时间间隔内进行取样。取样频率决定了每秒采集的样本数,通常以赫兹(Hz)表示。采样过程通过保持并测量模拟信号在每个采样时间点的电压值来实现。

量化:采样得到的连续模拟信号经过量化转换为数字形式。量化是将每个采样值映射到一个离散的数字值的过程。这通常通过比较采样值与参考电压之间的差异,并将其转换为数字表示。

ADC的分辨率是指它可以将模拟信号分成多少个离散的级别。较高的分辨率意味着ADC能够提供更精细的数字表示,从而更准确地捕捉和量化模拟信号的细微变化。

ADC功能描述

如图为ADC的功能框图

注意 :ADC3 的规则转换和注入转换触发与 ADC1 ADC2 的不同。
表中为ADC的引脚
PSV DDA V SSA 应该分别连接到 V DD V SS
STM32内的引脚与ADC通道对应关系如下:
ADC采集时序图

如图所示, ADC 在开始精确转换前需要一个稳定时间 t STAB 。在开始 ADC 转换和 14 个时钟周期
后, EOC 标志被设置, 16 ADC 数据寄存器包含转换的结果。

3.软件部分

ADC初始化

ADC初始化用到初始化函数:

ADCx_Init();

 这个函数包含三条语句:

ADCx_GPIO_Config();
ADC_NVIC_Config();
ADCx_Mode_Config();

接下来我们分别看看这三条语句的内容。

ADC GPIO配置

static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	ADC_APBxClock_FUN(ADC_GPIO_CLK, ENABLE );	
	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);				
}

这个函数中主要是ADC引脚的初始化,并且设置IO口为模拟输入模式。

ADC MODE 配置

static void ADCx_Mode_Config(void)
{
	ADC_InitTypeDef ADC_InitStructure;	
	ADC_APBxClock_FUN(ADC_CLK,ENABLE );	

	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;	

	ADC_InitStructure.ADC_NbrOfChannel = 1;			

	ADC_Init(ADCx, &ADC_InitStructure);
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	
	ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
	ADC_Cmd(ADCx, ENABLE);

	ADC_ResetCalibration(ADCx);
	while(ADC_GetResetCalibrationStatus(ADCx));	

	ADC_StartCalibration(ADCx);
	while(ADC_GetCalibrationStatus(ADCx));
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}

这里主要是配置ADC的采样模式,先设置了ADC为连续转换模式,转换通道数为1,初始化ADC。然后配置ADC时钟为PCLK2的8分频,也就是9MHz,配置ADC转换顺序为1,第一个转换,采样时间为55.5个时钟周期,最后开启ADC,并且开始转换。

ADCx NVIC 配置

static void ADC_NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;  
  NVIC_InitStructure.NVIC_IRQChannel = ADCx_IRQ;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

这里主要是ADC的NVIC配置,NVIC的相关原理在前面的文章已经详细介绍,这里不再赘述。

4.完整代码

Main.c

#include "stm32f10x.h"
#include "bsp/usart/bsp_debug_usart.h"
#include "bsp/adc/bsp_adc.h"
 
float ADC_ConvertedValueLocal;   
extern __IO uint16_t ADC_ConvertedValue;

static void Delay(uint32_t time);

int main(void)
{  

  DEBUG_USART_Init();  
  
	ADCx_Init();
  printf("----ÕâÊÇÒ»¸öADCµ¥Í¨µÀµçѹ²É¼¯ÊµÑé-----\n"); 
  

  while (1)
  { 
    ADC_ConvertedValueLocal =(float)ADC_ConvertedValue*3.3/4096; 
	
		printf("ADת»»Ô­Ê¼Öµ = 0x%04X \r\n", ADC_ConvertedValue); 
		printf("¼ÆËãµÃ³öµçѹֵ = %f V \r\n",ADC_ConvertedValueLocal); 
    
    Delay(1000);
  }
}

static void Delay(uint32_t time)
{
  uint32_t i,j;

  for(i=0;i<time;++i)
  {
    for(j=0;j<10000;++j)
    {       
             
    }
  }
}

bsp_adc.c


#include "bsp/adc/bsp_adc.h"

static void ADCx_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_APBxClock_FUN(ADC_GPIO_CLK, ENABLE );	

	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);				
}

static void ADCx_Mode_Config(void)
{
	ADC_InitTypeDef ADC_InitStructure;	

	ADC_APBxClock_FUN(ADC_CLK,ENABLE );	
	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;	
	
	ADC_InitStructure.ADC_NbrOfChannel = 1;			
	
	ADC_Init(ADCx, &ADC_InitStructure);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);
	
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);

	ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);
	ADC_Cmd(ADCx, ENABLE);
	

	ADC_ResetCalibration(ADCx);

	while(ADC_GetResetCalibrationStatus(ADCx));	
	
	ADC_StartCalibration(ADCx);
	
	while(ADC_GetCalibrationStatus(ADCx));
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
}


static void ADC_NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
 
  NVIC_InitStructure.NVIC_IRQChannel = ADCx_IRQ;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);
}

void ADCx_Init(void)
{
	ADCx_GPIO_Config();
  ADC_NVIC_Config();
	ADCx_Mode_Config();	
}

bsp_adc.h

#ifndef __ADC_H__
#define	__ADC_H__

#include <stm32f10x.h>

#define    ADC_APBxClock_FUN             RCC_APB2PeriphClockCmd

//#define    ADCx                          ADC1
//#define    ADC_CLK                       RCC_APB2Periph_ADC1
//#define    ADCx_IRQ                      ADC1_2_IRQn
//#define    ADC_IRQHandler_FUN            ADC1_2_IRQHandler

//#define    ADCx                          ADC2
//#define    ADC_CLK                       RCC_APB2Periph_ADC2
//#define    ADCx_IRQ                      ADC1_2_IRQn
//#define    ADC_IRQHandler_FUN            ADC1_2_IRQHandler

#define    ADCx                          ADC3
#define    ADC_CLK                       RCC_APB2Periph_ADC3
#define    ADCx_IRQ                      ADC3_IRQn
#define    ADC_IRQHandler_FUN            ADC3_IRQHandler

#define    ADC_GPIO_CLK                  RCC_APB2Periph_GPIOC  
#define    ADC_PORT                      GPIOC

#define    ADC_PIN                       GPIO_Pin_0        // 
#define    ADC_CHANNEL                   ADC_Channel_10    // 
//#define    ADC_PIN                       GPIO_Pin_1        // 
//#define    ADC_CHANNEL                   ADC_Channel_11    // 
                                      

void ADCx_Init(void);

#endif /* __ADC_H__ */


5.实验效果

ADC

6.结束语

本次实验讲解了使用Stm32的ADC采集内容,这也是STM32单片机应用很多的一部分内容,希望以上内容对各位朋友有所帮助。

最后,欢迎大家在评论区留言批评指正。谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值