• 学习STM32F407 的 ADC(Analog-to-digital converters,模数转换器)功能。

  • ADC 应用于电机控制的多个方面,例如:电源电压采集、电机电流采集、驱动板温度采集等。

ADC 简介

  • ADC 即模拟数字转换器,英文详称 Analog-to-digital converter,可以将外部的模拟信号转换为数字信号。
  • STM32F407IGT6 芯片拥有 3 个 ADC,都可以独立工作,其中 ADC1 和 ADC2 还可以组成双重模式(提高采样率)。这些 ADC 都是 12 位逐次逼近型的模拟数字转换器,有 19 个通道,可测量 16 个外部信号源、2 个内部信号源和 Vbat 通道的信号。ADC 中的各个通道的 A/D转换可以单次连续扫描间断模式执行。ADC 的结果可以以左对齐或者右对齐存储在 16位数据寄存器中。

STM32F407 的 ADC 主要特性

  • 12 位分辨率
  • 转换结束、注入转换结束和发生模拟看门狗事件时产生中断
  • 单次和连续转换模式
  • 自校准
  • 带内嵌数据一致性的数据对齐
  • 采样间隔可以按通道分别编程
  • 规则转换和注入转换均有外部触发选项
  • 间断模式
  • 双重模式(带 2 个或以上 ADC 的器件)
  • ADC 供电要求:2.4V 到 3.6V
  • ADC 输入范围:VREF– ≤ VIN ≤ VREF+
  • 规则通道转换期间有 DMA 请求产生

ADC 的框图

① 输入电压

ADC 的主要特性也对输入电压,ADC 输入范围 VREF–≤VIN≤VREF+,由 VREF–VREF+VDDAVSSA决定的。

VDDA和 VREF+接 VCC3.3,而 VSSA 和 VREF-是接地,所以 ADC 的输入范围即 0~3.3V。

② 输入通道

外部通道对应的是上图中的 ADCx_IN0、ADCx_IN1…ADCx_IN15。ADC1 的通道 16 就是内部通道,连接到芯片内部的温度传感器,通道 17 连接到 Vrefint,通道 18 连接到 VBAT,而 ADC2和 ADC3 的通道 16~18 都是连接到内部的 VSS。

③ 转换顺序

当 ADC 的多个通道以任意顺序进行转换就诞生了成组转换,两种成组转换类型:规则组和注入组。规则组就是图中的规则通道,注入组就是图中的注入通道。

  • 规则组(规则通道):规则组,按字面理解,“规则”就是按照一定的顺序,相当于正常运行的程序
  • 注入组(注入通道):当程序执行的时候,中断是可以打断程序的执行

规则序列

规则组最多允许 16 个输入通道进行转换,那么就需要设置通道转换的顺序,即规则序列。规则序列寄存器有 3 个,分别为 SQR1、SQR2 和 SQR3。SQR3 控制规则序列中的第 1 个到第6 个转换;SQR2 控制规则序列中第 7 个到第 12 个转换;SQR1 控制规则序列中第 13 个到第16 个转换。

当我们想设置 ADC 的某个输入通道在规则序列的第 1 个转换,只需要把相应的输入通道号的值写入 SQR3 寄存器中的 SQ1[4:0]位即可。如果还想让输入通道 8 在第 2 个转换,那么就可以把 8 这个数值写入 SQ2[4:0]位。最后还要设置你的这个规则序列的输入通道个数,只需把输入通道个数写入 SQR1 的 SQL[3:0]位。

注入序列

注入序列,跟规则序列差不多,决定的是注入组的顺序。注入组最大允许 4 个通道输入,它的注入序列由 JSQR 寄存器配置。

如果 JL[ 1 : 0 ]位的值小于 3,即设置注入序列要转换的通道个数小于 4,则注入序列的转换顺序是从 JSQx[ 4 : 0 ](x=4-JL[1:0])开始。例如:JL [ 1 : 0 ]=10、JSQ4 [ 4 : 0 ]= 00100、JSQ3 [ 4 : 0 ]= 00011、JSQ2 [ 4 : 0 ]= 00111、JSQ1 [ 4 : 0 ]= 00010,意味着这个注入序列的转换顺序是:7、3、4,而不是 2、7、3。如果 JL[ 1 : 0 ]=00,那么转换顺序是从 JSQ4 [ 4 : 0 ]开始。

④ 触发源

ADC 的触发转换有两种方法:分别是通过 ADON 位或外部事件触发转换。

ADON 位触发转换

当 ADC_CR2 寄存器的 ADON 位为 1 时,再独立给 ADON 位写 1(其它位不能一起改变,这是为了防止误触发),这时会启动转换。这种控制 ADC 启动转换的方式非常简单。

外部触发转换

通过外部事件触发转换,如定时器捕获、EXTI 线和软件触发,可以分为规则组外部触发和注入组外部触发。

⑤ 转换时间

ADC 的输入时钟是由 APB2 经过分频产生,分频系数是由 RCC_CFGR 寄存器中的PPRE2[2:0]进行设置的,可选择 2/4/6/8/16 分频。需要注意的是,STM32F407 的 ADC 的输入时钟频率最大值是 36MHz,如果超过这个值将会导致 ADC 的转换结果准确度下降。

⑥数据寄存器

ADC 转换完成后的数据输出寄存器。根据转换组的不同,规则组的完成转换的数据输出到 ADC_DR 寄存器,注入组的完成转换的数据输出到 ADC_JDRx 寄存器。假如是使用双重或三重模式,规则组的数据会存放在 ADC_CDR 寄存器。

⑦ 中断

ADC 中断可分为三种:规则组转换结束中断、注入组转换结束中断、设置了模拟看门狗状态位中断。它们都有独立的中断使能位,分别由 ADC_CR 寄存器的 EOCIE、JEOCIE、AWDIE位设置,对应的标志位分别是 EOC、JEOC、AWD。

模拟看门狗中断

模拟看门狗中断发生条件:首先通过 ADC_LTR 和 ADC_HTR 寄存器设置低阈值和高阈值,然后开启了模拟看门狗中断后,当被 ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断。例如我们设置高阈值是 3.0V,那么模拟电压超过 3.0V 的时候,就会产生模拟看门狗中断,低阈值的情况类似。

DMA请求

规则组和注入组的转换结束后,除了产生中断外,还可以产生 DMA 请求,把转换好的数据存储在内存里面,防止读取不及时数据被覆盖。

⑧ 单次转换模式和连续转换模式

单次转换模式

  • 通过将 ADC_CR2 寄存器的 CONT 位置 0 选择单次转换模式。该模式下,ADC 只执行一次转换,由 ADC_CR2 寄存器的 ADON 位启动(只适用于规则组),也可以通过外部触发启动(适用于规则组或注入组)。
  • 如果规则组的一个输入通道被转换,那么转换的数据被储存在 16 位 ADC_DR 寄存器中、EOC(转换结束)标志位被置 1、如果设置了 EOCIE 位,则产生中断,然后 ADC 停止。如果注入组的一个输入通道被转换,那么转换的数据被储存在 16 位 ADC_DRJx 寄存器中、JEOC(转换结束)标志位被置 1、如果设置了 JEOCIE 位,则产生中断,然后 ADC 停止。

连续转换模式

通过将 ADC_CR2 寄存器的 CONT 位置 1 选择连续转换模式。该模式下,ADC 完成上一个通道的转换后会马上自动地启动下一个通道的转换,由ADC_CR2寄存器的ADON位启动,也可以通过外部触发启动。如果规则组的一个输入通道被转换,那么转换的数据被储存在 16 位 ADC_DR 寄存器中、EOC(转换结束)标志位被置 1、如果设置了 EOCIE 位,则产生中断。如果注入组的一个输入通道被转换,那么转换的数据被储存在 16 位 ADC_DRJx 寄存器中、JEOC(转换结束)标志位被置 1、如果设置了 JEOCIE 位,则产生中断。

⑨ 扫描模式

扫描模式在框图中是没有标号,为了更好地学习后续的内容,这里简单给大家讲讲。可以通过 ADC_CR1 寄存器的 SCAN 位配置是否使用扫描模式。如果选择扫描模式,ADC会扫描所有被 ADC_SQRx 寄存器或 ADC_JSQR 选中的所有通道,并对规则组或者注入组的每个通道执行单次转换,然后停止转换。但如果还设置了 CONT 位,即选择连续转换模式,那么转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。如果设置了 DMA 位,在每次 EOC 后, DMA 控制器把规则组通道的转换数据传输到SRAM 中。而注入通道转换的数据总是存储在 ADC_JDRx 寄存器中。

单通道 ADC 采集

下面我们组单通道的单次转换模式,并且通过软件触发,即由 ADC_CR2 寄存器的 SWSTART 位启动。

ADC 寄存器

==ADC 控制寄存器 1(ADC_CR1)==

SCAN 位用于选择是否使用扫描模式。本实验我们使用单通道采集,所以没必要选择扫描模式,该位置 0 即可。

==ADC 控制寄存器 2(ADC_CR2)==

ADON 位用于打开或关闭 AD 转换器,还可以用于触发 ADC 转换。CONT 位用于设置单次转换模式还是连续转换模式,本实验我们使用单次转换模式,所以 CONT 位置 0 即可。ALIGN 用于设置数据对齐,我们使用右对齐,所以该位设置为 0。EXTEN[1:0]位用于设置外部触发边沿,本实验使用软件触发,所以设置为 00 即可。

==ADC 采样事件寄存器 1(ADC_SMPR1)==

==ADC 采样事件寄存器 2(ADC_SMPR2)==

ADC 采样时间设置需要由两个寄存器设置,ADC_SMPR1 和 ADC_SMPR2,分别设置通道 10~18 和通道 0~9 的采样时间,每个通道用 3 个位设置。

  • 一般每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降低 ADC 的转换速率,看大家怎么衡量选择了。本实验中,我们设置采样时间是 480 个周期,ADC 精度是 12 位。
TCONV = 采样时间 + 12 个周期
  • 例如APB2 的时钟是 84MHz,经过 ADC 时钟预分频器的 4 分频后,ADC 时钟频率为 21MHz。

====》 ADC 的转换时间大约是 23.4us。

==ADC 规则序列寄存器 1(ADC_SQR1)==

L[3:0]用于设置规则组序列的长度,取值范围:0~15,表示规则组的长度是 1~16。本实验只用了 1 个输入通道,所以 L[3:0]位设置为 0000 即可。

==ADC 规则数据寄存器(ADC_DR)==

在规则序列中 AD 转换结果都将被存在这个寄存器里面,而注入通道的转换结果被保存在 ADC_JDRx 里面。该寄存器的数据可以通过 ADC_CR2 的 ALIGN 位设置左对齐还是右对齐。

==ADC 状态寄存器(ADC_SR)==

该寄存器保存了 ADC 转换时的各种状态。本实验我们通过 EOC 位的状态来判断 ADC 转换是否完成,如果查询到 EOC 位被硬件置 1,就可以从 ADC_DR 寄存器中读取转换结果,否则需要等待转换完成。

单通道 ADC 采集(DMA 读取)

学习单通道 ADC 采集(DMA 读取)。本实验使用规则组单通道的连续转换模式,并且通过软件触发,即由 ADC_CR2 寄存器的 SWSTART 位启动。由于使用连续转换模式,所以使用 DMA 读取转换结果的方式。

ADC&DMA 寄存器

这里很多的设置和单通道 ADC 采集实验是一样的

==ADC 配置寄存器(ADC_CR2)==

  • DMA 位用于配置使用 DMA 模式,本实验该位置 1。在单通道 ADC 采集实验中,默认设置为 0,即不使用 DMA 模式,规则组转换的结果存储在 ADC_DR 寄存器,然后通过手动读取 ADC_DR 寄存器的方式得到转换结果。本实验我们使用 ADC 的连续转换模式,并通过 DMA读取转换结果,这样 DMA 就会自动在 ADC_DR 寄存器中读取转换结果。
  • CONT 位用于设置单次转换模式还是连续转换模式,本实验我们使用连续转换模式,所以 CONT 位置 1 即可。

==DMA 数据流 x 外设地址寄存器(DMA_SxPAR)(x = 0…7)==

该寄存器存放的是 DMA 读或者写数据的外设数据寄存器的基址。本实验,我们需要通过DMA 读取 ADC 转换后存放在 ADC 规则数据寄存器 (ADC_DR) 的结果数据。所以我们需要给 DMA_SxPAR 寄存器写入 ADC_DR 寄存器的地址。这样配置后,DMA 就会从 ADC_DR 寄存器的地址读取 ADC 的转换后的数据到某个内存空间。这个内存空间地址需要我们通过DMA_SxPAR 寄存器来设置,比如定义一个变量,把这个变量的地址值写入该寄存器。

==DMA 数据流 x 存储器地址寄存器(DMA_SxM0AR)(x = 0…7)==

该寄存器存放的是 DMA 读或者写数据的目标存放的地址。同样的,该寄存器也是受写保护,只有当 DMA_SxCR 的 EN 位为 0 时才可以写入。

==DMA 数据流 x 数据项数寄存器(DMA_SxNDTR)(x = 0…7)==

前面的 DMA_SxPAR 寄存器是传输的源地址,而 DMA_SxM0AR 寄存器是传输的目的地址,DMA_SxNDTR 寄存器则是要传输的数据项数目(0 到 65535)。

多通道 ADC 采集(DMA 读取)

多通道 ADC 采集(DMA 读取)。使用规则组多通道的连续转换模式,并且通过软件触发,即由 ADC_CR2 寄存器的 SWSTART 位启动。由于使用连续转换模式,所以使用 DMA 读取转换结果的方式。

ADC寄存器

这里很多的设置和单通道 ADC 采集(DMA 读取)实验是一样的,针对性选择与单通道 ADC 采集(DMA 读取)不同设置的 ADC_SQRx 寄存器进行介绍,其他的配置基本一样的。另外我们用到 DMA读取数据,配置上和单通道 ADC 采集(DMA 读取)是一样的。

==ADC 规则序列寄存器 1(ADC_SQR1)==

  • L[3:0]位用于设置规则序列的长度,取值范围:0~15,表示规则序列长度为 1~16。本实验使用到 3 个通道,所以设置这几个位的值为 2 即可。
  • SQ13[4:0]~SQ16[4:0]位设置规则组序列的第 13~16 个转换编号,第 1~12 个转换编号的设置请查看 ADC_SQR2 和 ADC_SQR3 寄存器。

内部温度传感器

STM32F407 的内部温度传感器并使用它来读取温度值

内部温度传感器简介

  • STM32 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(内部温度传感器更适合于检测温度的变化,需要测量精确温度的情况下,建议使用外置传感器)。对于STM32F407 来说,该温度传感器在内部和 ADC1_IN16 输入通道相连接,此通道把传感器输出的电压转换成数字值,温度传感器模拟输入采样时间不能小于 10us。STM32 内部温度传感器支持的温度范围为:-40~125 度。精度为±1.5℃左右。
  • STM32 内部温度传感器的使用很简单,只要设置一下内部 ADC,并激活其内部温度传感器通道就差不多了。
  • 使用 STM32 的内部温度传感器,必须先激活 ADC 的内部通道,通过 ADC_CR2 的 TSVREFE 位设置。设置该位为 1 则启用内部温度传感器。
  • STM32F4 的内部温度传感器固定的连接在 ADC1 的通道 16 上,在设置好 ADC1 之后只要读取通道 16 的值,就是温度传感器返回来的电压值了。根据这个

值,我们就可以计算出当前温度。计算公式如下:

    • V25 = Vsense 在 25 度时的数值(典型值为:0.76)
    • Avg_Slope = 温度与 Vsense 曲线的平均斜率(单位:mv/℃或 uv/℃)(典型值:2.5mv/℃)。