热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:STM32学习笔记(13)——模数转换ADC

篇首语:本文由编程笔记#小编为大家整理,主要介绍了STM32学习笔记(13)——模数转换ADC相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了STM32学习笔记(13)——模数转换ADC相关的知识,希望对你有一定的参考价值。






这个月一直忙于准备考试,已经考完一半科目了,偷闲写了这篇文章。因为还没考完试,估计还得咕一段时间了。



STM32学习笔记(13)——模数转换ADC


  • 第一部分:ADC功能框图
    • 一、输入电压
    • 二、输入通道
    • 三、规则通道
    • 四、注入通道
    • 五、触发源
      • 1. 软件触发
      • 2. 外部事件触发

    • 六、转换时间
    • 六、数据寄存器
      • 1. 数据规则寄存器(ADC_DR)
      • 2. 数据注入寄存器(ADC_JDRx,x=1, 2, 3, 4)

    • 七、中断

  • 第二部分:ADC结构体和库函数
    • 一、ADC初始化结构体
      • 1. 工作模式
      • 2. 扫描模式
      • 3. 连续转换模式
      • 4. 外部触发源选择
      • 5. 数据对齐格式
      • 6. 采集通道数

    • 二、ADC常用库函数



模拟量转换为数字量的过程称为A/D模数转换,完成这一转换过程的器件称为ADC(Analog-to-Digital Converter)。

在STM32中,有三个ADC:ADC1、ADC2、ADC3,其分辨率为12位,每个ADC通道具有18个通道,其中外部通道有16个。


第一部分:ADC功能框图

在这里插入图片描述

我们分为七个部分讲解:


一、输入电压

输入电压一般由参考电压VREF-VREF+VDDA(模拟电压源)VSSA(模拟地)提供,具体的输入电压范围为VREF- ≤ VIN ≤ VREF+

在一般的电路设计中,我们会将VSSAVREF-接地(GND),将VDDAVREF+接高电平(即3.3V),如下图电路原理图所示。因此,ADC的输入电压范围为0 ~ 3.3V

我们可以根据数字量来算出模拟量:首先 ADC 分辨率为12位,电压范围为 0~3.3V,则最小精度为






3.3





0




2


12





\\frac{3.3-0}{2^{12}}


2123.30
,假设数字量为X,则最终模拟量 =






3.3





0




2


12







X



\\frac{3.3-0}{2^{12}}\\cdot X


2123.30X

在这里插入图片描述

当然,ADC可以测量范围为 0 ~ 3.3V 的电压,但如果超出这个范围的电压该如何测量呢?举一个简单的例子:如果我们想扩大测量范围至 -10 ~ +10V,可以将电路设计成如下:

在这里插入图片描述

根据KCL(基尔霍夫定律:节点流入电流之和等于流出电流之和)方程可得出:








V


I


N





V


O


U


T




R


2




+




3.3


V





V


O


U


T




R


1




=




V


O


U


T




R


3





\\frac{VIN-VOUT}{R2}+\\frac{3.3V-VOUT}{R1}=\\frac{VOUT}{R3}


R2VINVOUT+R13.3VVOUT=R3VOUT

已知 R1、R2 和 R3,就能根据这个方程得出 VIN 和 VOUT 的关系式。


二、输入通道

STM32 为三个 ADC 分配了 18 个通道,如下表所示:

在这里插入图片描述

这是 STM32F103ZET6 的通道引脚分配,不同型号的芯片有不同的分配。在这里,对于 ADC1 和 ADC2,通道16和17均为内部通道;对于 ADC3,通道9和通道14~17均为内部通道。注意有部分 IO 引脚被重复占用。


三、规则通道

STM32 的 ADC 输入通道分为两类:规则通道和注入通道。ADC 可以对一组指定的通道,按照既定的顺序,逐个转换这组通道,转换结束后,再从头循环。这些指定的通道组被称为规则通道组(规则组),组内的通道被称为规则转换通道(规则通道)。但在实际情况中,有可能需要临时中断规则组的转换,对某些通道进行转换,这些需要中断的规则组就称为注入通道组(注入组),组内的通道被称为注入转换通道(注入通道)

规则组最多可以设置 16 个通道。

我们可通过规则序列寄存器SQRx(x=1, 2, 3)来设置规则通道的优先顺序。规则序列寄存器一共有三个,除了寄存器SQR1的第23位至20位(SQL[3:0])用做配置转换通道的个数外,其他都是每 5 位一组配置第 n 个转换的通道。如下表所示:

在这里插入图片描述

例如,配置寄存器SQR1SQL[3:0]为3,表明有 3 个规则通道,则可在寄存器SQR3SQ1[4:0]SQ2[4:0]SQ3[4:0]中分别配置为11、5、7,表明通道5、7和11都是规则通道,而且转换顺序是先通道11、再通道5、最后通道7。


四、注入通道

注入通道和规则通道有所不同的是,注入通道与中断程序类似,在规则通道进行转换时“强行”插入进行转换。因此,注入也有插入的意思,插入和规则是相对的,注入通道只有在规则通道存在的时候才会出现。

我们可通过注入序列寄存器JQSR来设置注入通道的优先顺序。注入序列寄存器只有一个,第21和20位两位(JL[1:0])用来设置转换通道的个数,其余都是每 5 位一组配置第 n 个转换通道。如下表所示:

在这里插入图片描述

因为与规则通道序列寄存器类似,因此就不举例了。但要注意一点:寄存器JSQR和寄存器SQR的转换顺序是不一样的。JSQR的第 4 个转换通道其实是第一次进行转换的,第 3 个转换通道是第二次进行转换的,正好是反过来的,以此类推。

关于规则组和注入组的例子:系统需要采集温度,但又要适时监控湿度,那么湿度采集的转换通道可以放在注入组中,通过某种触发源启动转换。一旦启动注入通道转换,规则通道转换被暂停,然后等待注入通道转换完成后,规则组在进行转换。


五、触发源


1. 软件触发

是否启动 ADC 由寄存器ADC_CR2ADON位控制,写入1则表示打开或启动模拟至数字转换器的电压。

启动转换器后,由寄存器ADC_CR2SWSTART位和JSWSTART位分别控制规则通道的转换和注入通道的转换,写入1则表示转换使能允许。


2. 外部事件触发

寄存器ADC_CR2EXTSEL位和EXTTRIG位控制规则通道的触发源,触发源来自TIM1_CHx(x=1, 2, 3)TIM2_CH2TIM4_CH4TIM3_TRGOEXTSEL位用于选择使用哪个触发源,EXTTRIG位用于使能触发允许或禁止。

类似地,寄存器ADC_CR2JEXTSEL位和JEXTTRIG位控制注入通道的触发源,触发源来自TIM1_CH4TIM2_CH1TIM3_CH4TIM1_TRGOTIM2_TRGOTIM4_TRGOJEXTSEL位用于选择使用哪个触发源,JEXTTRIG位用于使能触发允许或禁止。

注意,以上描述的是 ADC1 和 ADC2 的触发源,ADC3 与前两者有区别,具体可参考手册内容。

GPIO 外部中断的 EXTI11 和 EXTI15 也可作为触发源。


六、转换时间

转换时间公式为:T(conv) = 采样时间 + 12.5个周期

转换速度由 ADC 模拟时钟(ADC_CLK)决定,其最大频率为 14MHz。 ADC_CLK 由 PCLK2 提供。之前在讲解时钟树的时候已经提及过,PCLK2 在经过 APB2 预分频器后最大频率可达到 72MHz。因为 ADC_CLK 规定最大频率为 14MHz,因此, 时钟信号经过 的 ADC 预分频器的分频因子最小为 6,所以实际的最大频率为72MHz / 6 = 12MHz

在这里插入图片描述

那么在哪里可以配置 ADC 预分频因子呢?注意,并不在 ADC 相关的寄存器中配置,而是在与 RCC 相关的寄存器进行配置。在寄存器RCC_CFGRADCPRE[1:0]可以配置 ADC 预分频因子。

ADC 需要若干个 ADC_CLK 周期才能完成对输入模拟量的采样,因此采样时间可由 n
个 ADC_CLK 周期来表示,即采样的周期数。我们可以通过两个采样时间寄存器ADC_SMPRx(x=1, 2) 来配置(如下表所示),位SMPx[2:0] (x=0-17)用来配置采样的周期。其中寄存器ADC_SMPR2控制的是通道 0~9,寄存器ADC_SMPR1控制的是通道 10~17。这意味着每个通道都可以采用不同的采样周期。

在这里插入图片描述

如上表所示,最快的采样周期为 1.5 个 ADC_CLK 周期,最慢的采样周期为 239.5 个 ADC_CLK 周期。而一个周期的时间一般为1 / 12MHz,所以最短的转换时间为:T(conv) = 采样时间 + 12.5个周期 = 1.5 + 12.5 = 14 个周期 = 14 *(1 / 12us) = 1.17us


六、数据寄存器

ADC将转换好的数据存放到数据寄存器中,规则组的数据存放到寄存器ADC_DR中,注入组的数据则存放到寄存器ADC_JDRx(x=1, 2, 3, 4)中。


1. 数据规则寄存器(ADC_DR)

在这里插入图片描述

对于独立模式,即只使用一个 ADC 的情况(即只使用 ADC1 或 ADC2 或 ADC3)下,由于 ADC 分辨率为 12 位,所以只使用寄存器的低16位中的12位,高16位就不使用了。 这12位数据可以左对齐,也可以右对齐,这是由寄存器ADC_CR2ALIGN来决定。

对于双ADC模式(ADC1和ADC2同时使用,注意ADC3是不能用于双ADC模式的),ADC2 的数据存放在寄存器的高16位,而 ADC1 的数据存放在寄存器的低16位。

由于数据规则寄存器只有一个,因此在使用多通道采集的时候寄存器的数据必然会被覆盖,一般的解决办法是采用DMA模式(ADC1和ADC3可用,2不可用),将转换结果转移进 DMA 中。


2. 数据注入寄存器(ADC_JDRx,x=1, 2, 3, 4)

在这里插入图片描述

和数据规则寄存器一样,由于 ADC 分辨率为 12 位,所以只使用寄存器的低16位中的12位,高16位就不使用了。 这12位数据可以左对齐,也可以右对齐,这是由寄存器ADC_CR2ALIGN来决定。

由于数据注入寄存器有 4 个,因此就不存在多通道采集时所产生的数据覆盖问题了。


七、中断

在这里插入图片描述

ADC能产生三种中断,这三种中断对应的标志事件是:转换结束(EOC)、注入转换结束(JEOC)、模拟看门狗事件(AWID),所对应的中断使能位是EOCIE、JEOCIE、AWIDIE。

这里说明一下模拟看门狗的作用:在某些情况下我们希望模拟电压达到一定阈值后就产生一次中断,可以用模拟看门狗来监测模拟电压是否达到这个阈值,如果是,那么就会发出一次中断请求。在 ADC看门狗高阈值寄存器(ADC_HTR)ADC看门狗低阈值寄存器(ADC_LRT) 可以设置这个阈值电压,两者均为低12位有效。


第二部分:ADC结构体和库函数

一、ADC初始化结构体

typedef struct
{
uint32_t ADC_Mode; // ADC工作模式
FunctionalState ADC_ScanConvMode; // ADC扫描(多通道)或单次(单通道)模式
FunctionalState ADC_ContinuousConvMode; // ADC单次转换或连续转换
uint32_t ADC_ExternalTrigConv; // ADC触发源选择
uint32_t ADC_DataAlign; // ADC数据寄存器对齐格式
uint8_t ADC_NbrOfChannel; // ADC采集通道数

}ADC_InitTypeDef;

1. 工作模式

在寄存器ADC_CR1DUALMOD[3:0]位可以配置ADC工作模式,下面来简要介绍每种模式(除了独立模式外,剩余的模式都属于双重模式,只能搭配ADC1/2):


  • 独立模式(ADC_Mode_Independent):ADC1/2/3 单独使用其中一个。
  • 同步规则模式(ADC_Mode_RegSimult):ADC1 和 ADC2 同时转换一个规则通道组,其中 ADC1 为主,ADC2 为从,ADC1 转换的结果放在ADC_DR低16位,ADC2 转换的结果放在ADC_DR的高16位。
  • 同步注入模式(ADC_Mode_InjecSimult):ADC1 和 ADC2 同时转换一个注入通道组,其中 ADC1 为主,ADC2 为从,ADC1 转换的结果放在各自的ADC_JDR
  • 快速交叉模式(ADC_Mode_FastInterl):ADC1 和 ADC2 交替采集一个规则通道组(通常为一个规则通道),当 ADC2 触发后,ADC1 需要等待 7 个 ADCCLK 之后才能触发。
  • 慢速交叉模式(ADC_Mode_SlowInterl):ADC1 和 ADC2 交替采集一个规则通道组(只能为一个规则通道),当 ADC2 触发后,ADC1 需要等待 14 个 ADCCLK 之后才能触发。
  • 交替触发模式(ADC_Mode_AlterTrig):ADC1 和 ADC2 轮流采集注入通道组,当 ADC1 采集完所有通道后,ADC2 再采集自己的通道,如此循环。
  • 混合的同步规则+注入同步模式(ADC_Mode_RegInjecSimult):规则组同步转换被中断,以启动注入组的同步转换。
  • 混合的同步规则+交替触发模式(ADC_Mode_RegSimult_AlterTrig):规则组同步转换被中断,以启动注入组的交替触发转换。
  • 混合同步注入+快速交叉模式(ADC_Mode_InjecSimult_FastInterl):快速交叉转换被中断,同步注入启动。
  • 混合同步注入+慢速交叉模式(ADC_Mode_InjecSimult_SlowInterl):慢速交叉转换被中断,同步注入启动。

其中,同步规则模式和快速交叉模式比较常用。


2. 扫描模式

在寄存器ADC_CR1SCAN位进行配置。

实际是一个使能位:选择单通道扫描(ENABLE)还是多通道扫描(DISABLE)。


3. 连续转换模式

在寄存器ADC_CR2CONV位进行配置。

实际是一个使能位:对通道选择采集一次(DISABLE)还是不停地重复采集(ENABLE)。


4. 外部触发源选择

寄存器ADC_CR2EXTSEL位和EXTTRIG位控制规则通道的触发源,寄存器ADC_CR2JEXTSEL位和JEXTTRIG位控制注入通道的触发源。

可参考功能框图讲解的第五节触发源。


5. 数据对齐格式

由寄存器ADC_CR2ALIGN来配置数据的左对齐或右对齐。


6. 采集通道数

由寄存器ADC_SQR1L[3:0]位或寄存器ADC_JSQRJL[1:0]位进行配置。


二、ADC常用库函数

以下为ADC常用的库函数:

void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 软件触发
void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 外部引脚触发
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);

ADC未完待续~






推荐阅读
author-avatar
疯狂人儿-
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有