STM32笔记(十三)---ADC

这篇博客详细介绍了STM32的ADC功能,包括ADC的电压输入范围、通道、转换顺序、触发源、转换时间和中断。并提供了独立模式下单通道中断采集和多通道DMA采集的实验步骤,以及双重ADC同步规则模式的实验要点。
摘要由CSDN通过智能技术生成

ADC-电压采集

一、ADC简介

​ 以STM32f103 系列为例,3 个 ADC,精度为 12 位,每个 ADC 最多有 16 个外部通道。其中ADC1 和 ADC2 都有 16 个外部通道, ADC3 根据 CPU 引脚的不同通道数也不同,一般都有8 个外部通道。 ADC 的模式非常多,功能非常强大,具体的我们在功能框图中分析每个部分的功能。

ADC功能框图

图1 单个ADC功能框图

  • ①电压输入范围
    ADC 输入范围为: VREF- ≤ VIN ≤ VREF+。由 VREF-、 VREF+ 、 VDDA 、 VSSA、这四个外部引脚决定。

    ​ 在设计原理图的时候一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,得到ADC 的输入电压范围为: 0~3.3V。

    ​ 如果想让输入的电压范围变宽,去到可以测试负电压或者更高的正电压,可以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到 0~3.3V,这样 ADC 就可以测量。

  • ②输入通道
    确定好 ADC 输入电压之后,那么电压怎么输入到 ADC?这里我们引入通道的概念,STM32 的 ADC 多达 18 个通道,其中外部的 16 个通道就是框图中的 ADCx_IN0、ADCx_IN1…ADCx_IN5。这 16 个通道对应着不同的 IO 口, 具体是哪一个 IO 口可以从手册查询到。其中 ADC1/2/3 还有内部通道: ADC1 的通道 16 连接到了芯片内部的温度传感器, Vrefint 连接到了通道 17。 ADC2 的模拟通道 16 和 17 连接到了内部的 VSS。ADC3 的模拟通道 9、 14、 15、 16 和 17 连接到了内部的 VSS。
    图2 STM32F103VET6 ADC 通道

​ 外部的 16 个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有 16路,注入通道最多有 4 路。那这两个通道有什么区别?在什么时候使用?
规则通道
规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道,或者应该说我们用到的都是这个通道。

注入通道
注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。

  • ③转换顺序
    规则序列
    规则序列寄存器有 3 个,分别为 SQR3、 SQR2、 SQR1。 SQR3 控制着规则序列中的第一个到第六个转换,对应的位为: SQ1[4:0]~SQ6[4:0],第一次转换的是位 4:0 SQ1[4:0],如果通道 16 想第一次转换,那么在 SQ1[4:0]写 16 即可。 SQR2 控制着规则序列中的第 7 到第12 个转换,对应的位为: SQ7[4:0]~SQ12[4:0],如果通道 1 想第 8 个转换,则 SQ8[4:0]写 1即可。 SQR1 控制着规则序列中的第 13 到第 16 个转换,对应位为: SQ13[4:0]~SQ16[4:0],如果通道 6 想第 10 个转换,则 SQ10[4:0]写 6 即可。具体使用多少个通道,由 SQR1 的位L[3:0]决定,最多 16 个通道。
    图3 规则序列寄存器

注入序列
注入序列寄存器 JSQR 只有一个,最多支持 4 个通道,具体多少个由 JSQR 的 JL[2:0]决定。如果 JL 的 值小于 4 的话,则 JSQR 跟 SQR 决定转换顺序的设置不一样,第一次转换的不是 JSQR1[4:0],而是 JCQRx[4:0] , x = (4-JL),跟 SQR 刚好相反。如果 JL=00(1 个转换),那么转换的顺序是从 JSQR4[4:0]开始,而不是从 JSQR1[4:0]开始。当 JL 等于 4 时,跟 SQR 一样。
图4 注入序列寄存器

image-20200706223510963

  • ④触发源
    ADC 转换可以由ADC 控制寄存器 2: ADC_CR2 的 ADON 这个位来控制,写 1 的时候开始转换,写 0 的时候停止转换,这个是最简单也是最好理解的开启 ADC 转换的控制方式。
    除了这种庶民式的控制方法, ADC 还支持触发转换,这个触发包括内部定时器触发和外部 IO 触发。触发源有很多,具体选择哪一种触发源,由 ADC 控制寄存器 2:ADC_CR2 的EXTSEL[2:0]和 JEXTSEL[2:0]位来控制。 EXTSEL[2:0]用于选择规则通道的触发源,JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后,触发源是否要激活,则由ADC 控制寄存器 2:ADC_CR2 的 EXTTRIG 和 JEXTTRIG 这两位来激活。其中 ADC3 的规则转换和注入转换的触发源与 ADC1/2 的有所不同,在框图上已经表示出来。

  • ⑤转换时间
    ADC 时钟
    ADC 输入时钟 ADC_CLK 由 PCLK2 经过分频产生,最大是 14M,分频因子由 RCC 时钟配置寄存器 RCC_CFGR 的位 15:14 ADCPRE[1:0]设置,可以是 2/4/6/8 分频,注意这里没有 1 分频。一般我们设置 PCLK2=HCLK=72M。
    采样时间
    ADC 使用若干个 ADC_CLK 周期对输入的电压进行采样,采样的周期数可通过 ADC采样时间寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位设置, ADC_SMPR2 控制的是通道 0~9, ADC_SMPR1 控制的是通道 10~17。每个通道可以分别用不同的时间采样。其中采样周期最小是 1.5 个,即如果我们要达到最快的采样,那么应该设置采样周期为 1.5个周期,这里说的周期就是 1/ADC_CLK。

    ​ ADC 的转换时间跟 ADC 的输入时钟和采样时间有关,公式为: Tconv = 采样时间 +12.5 个周期。 当 ADCLK = 14MHZ (最高),采样时间设置为 1.5 周期(最快),那么总的转换时间(最短) Tconv = 1.5 周期 + 12.5 周期 = 14 周期 = 1us。
    ​ 一般我们设置 PCLK2=72M,经过 ADC 预分频器能分频到最大的时钟只能是 12M,采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us,这个才是最常用的。

  • ⑥中断
    转换结束中断
    数据转换结束后,可以产生中断,中断分为三种:规则通道转换结束中断,注入转换通道转换结束中断,模拟看门狗中断。其中转换结束中断很好理解,跟我们平时接触的中断一样,有相应的中断标志位和中断使能位,我们还可以根据中断类型写相应配套的中断
    服务程序。
    模拟看门狗中断
    当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是我们开启了模拟看门狗中断,其中低阈值和高阈值由 ADC_LTR 和 ADC_HTR 设置。例如我们设置高阈值是 2.5V,那么模拟电压超过 2.5V 的时候,就会产生模拟看门狗中断,反之低阈值也一样。
    DMA 请求
    规则和注入通道转换结束后,除了产生中断外,还可以产生 DMA 请求,把转换好的数据直接存储在内存里面。要注意的是只有 ADC1 和 ADC3 可以产生 DMA 请求。有关DMA 请求需要配合《STM32F10X-中文参考手册》 DMA 控制器这一章节来学习。一般我们在使用 ADC 的时候都会开启 DMA 传输。

    电压转换
    模拟电压经过 ADC 转换后,是一个 12 位的数字值,如果通过串口以 16 进制打印出来的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟实际的模拟电压(用万用表测)对比,看看转换是否准确。
    我们一般在设计原理图的时候会把 ADC 的输入电压范围设定在: 0~3.3v,因为 ADC是 12 位的,那么 12 位满量程对应的就是 3.3V, 12 位满量程对应的数字值是: 2^12。数值0 对应的就是 0V。 如果转换后的数值为 X , X 对应的模拟电压为 Y,那么会有这么一个等式成立: 2^12 / 3.3 = X / Y, => Y = (3.3 * X ) / 2^12。

二、ADC独立模式单通道中断采集实验

  1. 初始 ADC 用到的 GPIO;
  2. 设置 ADC 的工作参数并初始化;
  3. 设置 ADC 工作时钟;
  4. 设置 ADC 转换通道顺序及采样时间;
  5. 配置使能 ADC 转换完成中断,在中断内读取转换完数据;
  6. 使能 ADC;
  7. 使能软件触发 ADC 转换。
  • 头文件相关宏定义
/*************ADC GPIO相关宏定义**************/
#define ADC_GPIO_APBxCLock_FUN 			RCC_APB2PeriphClockCmd
#define ADC_GPIO_CLK					RCC_APB2Periph_GPIOC
#define ADC_PORT						GPIOC
#define ADC_PIN						    GPIO_Pin_1

/*************ADC 相关宏定义**************/
//选择ADC1
#define ADC_APBxCLock_FUN 				RCC_APB2PeriphClockCmd
#define ADC_CLK							RCC_APB2Periph_ADC1
#define ADCx							ADC1

//根据ADC引脚图 PC1为通道11
#define ADC_CHANNEL						ADC_Channel_11

// ADC 中断相关宏定义
#define ADC_IRQ 						ADC1_2_IRQn
#define ADC_IRQHandler 					ADC1_2_IRQHandler	

  • ADC配置
__IO uint16_t ADC_ConvertedValue;

static void ADCx_GPIO_Config(void)
{
   
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 打开ADC IO端口时钟
	ADC_GPIO_APBxCLock_FUN(ADC_GPIO_CLK, ENABLE);
	
	// 配置ADC IO引脚模式为模拟输入模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin = ADC_PIN;
	// ADC为模拟输入,无需配置速度
	
	GPIO_Init(ADC_PORT, &GPIO_InitStructure);
} 

static void ADCx_Mode_Config(void)
{
   
	ADC_InitTypeDef ADC_InitStructure;
	
	// 打开ADC时钟
	ADC_APBxCLock_FUN(ADC_CLK,ENABLE);
	// 连续转换模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	// 转换结果右对齐
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	// 不用外部触发转换,软件开启即可
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	// 只使用一个 ADC,属于独立模式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
	// 转换通道 1 个
	ADC_InitStructure.ADC_NbrOfChannel = 1;
	// 禁止扫描模式,多通道才要,单通道不需要
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	
	ADC_Init(ADCx, &ADC_InitStructure);
	
	//配置ADC-CLK为6分频 72/6=12M
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	// 配置 ADC 通道转换顺序为 1,第一个转换,采样时间为 55.5 个时钟周期
	ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
	
	//开启ADC转换结束中断,在中断服务函数中读取转换值☆
	ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE);//EOC--规则通道
	
	//开启ADC,并开始转换
	ADC_Cmd(ADCx, ENABLE);
	
	//初始化ADC校准寄存器
	ADC_ResetCalibration(ADCx);
	//等待校准寄存器初始化完成
	while(ADC_GetResetCalibrationStatus(ADCx));
	
	/***********ADC校准开启(不开启也可)**********/
	//ADC开始校准
	ADC_StartCalibration(ADCx);
	//等待校准完成
	while(ADC_GetCalibrationStatus(ADCx));
	
	//由于没有采用外部触发,所以使用软件触发ADC转换
	ADC_SoftwareStartConvCmd(ADCx, ENABLE);
	
}

static void ADC_NVIC_Config(void)
{
   
	NVIC_InitTypeDef NVIC_InitStructure;
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值