HAL库学习笔记-14 ADC和DAC

16 篇文章 45 订阅
16 篇文章 17 订阅


前言

五一前出差了,然后又逢假期,荒废了半月,一直没有状态,学不进去,今天把STM32常用的ADC和DAC总结一下,主要是ADC,因为与外界交互最多的就是采集模拟电压与电流啦,再输出整定后的控制量。


一、ADC与DAC的原理

ADC原理很简单就是模拟量的采样,然后编码输出为数字量,反过来DAC就是将数字量进行解码拟合为模拟量。

二、STM32F4ADC简介

在这里插入图片描述

如图所示是单个ADC的功能框图。STM32F4XX系列一般都有3个ADC,这些ADC可以独立使用,也可以使用双重/三重模式(提高采样率)。

1.源范围

ADC 输入范围为:VREF- ≤ VIN ≤ VREF+。由VREF-、VREF+ 、VDDA 、VSSA、这四个外部引脚决定。
我们在设计原理图的时候一般把VSSA 和VREF-接地,把VREF+和VDDA 接3V3,得到ADC 的输入电压范围为:0~3.3V。
如果我们想让输入的电压范围变宽,可以测试负电压或者更高的正电压,我们可以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到0~3.3V,这样ADC 就可以测量了。

2.采集通道

STM32的ADC是12位逐次逼近型的模拟数字转换器,它有19个通道,0~15为外部通道,可采集外部的源,这16 个通道对应着不同的IO 口,具体是哪一个IO口可以从手册查询到;2个内部源通道和1个Vbat通道的信号。以407为例。
在这里插入图片描述
外部的16 个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4 路。
规则通道
规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道,或者应该说我们用到的都是这个通道,没有什么特别要注意的可讲。
注入通道
注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。
这样将AD转换分组能够简化事件处理程序,提高事件处理速度。将一些常规采集和突发采集分开。

3.转换顺序

规则序列
每个ADC规则序列寄存器有3 个,分别为SQR3、SQR2、SQR1,控制每个ADC的外部16个通道的规则转换顺序。SQR3 控制着规则序列中的第一个到第六个转换,对应的位为:SQ1[4:0]~SQ6[4:0],第一次转换的是位4:0 SQ1[4:0],如图为SQR1寄存器,另外两个没有L位,只有转换位。
在这里插入图片描述
注入序列
每个ADC只有一个注入序列寄存器,最多支持4个通道。
在这里插入图片描述
注意:

  • 当 JL[1:0] = 3(定序器中有 4 次注入转换)时,ADC 将按以下顺序转换通道:JSQ1[4:0]、 JSQ2[4:0]、JSQ3[4:0] 和 JSQ4[4:0]。
  • 当 JL = 2(定序器中有 3 次注入转换)时,ADC 将按以下顺序转换通道:JSQ2[4:0]、JSQ3[4:0] 和 JSQ4[4:0]。
  • 当 JL = 1(定序器中有 2 次注入转换)时,ADC 转换通道的顺序为:先是 JSQ3[4:0],而后 是 JSQ4[4:0]。
  • 当 JL = 0(定序器中有 1 次注入转换)时,ADC 将仅转换 JSQ4[4:0] 通道。

4.触发方式

通道和顺序配置好后,选择触发源和触发方式,一般通过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 这两位来激活。
如果使能了外部触发事件,我们还可以通过设置ADC 控制寄存器2:ADC_CR2 的EXTEN[1:0]和JEXTEN[1:0]来控制触发极性,可以有4 种状态,分别是:禁止触发检测、上升沿检测、下降沿检测以及上升沿和下降沿均检测。
CR1
在这里插入图片描述
ADC_CR1的SCAN位,用于设置扫描模式,由软件设置和清除,如果设置为1,则使用扫描模式,如果为0则关闭扫描模式。在扫描模式下,由序列寄存器选中的通道被转换。如果设置了 EOCIE或 JEOCIE,只在最后一个通道转换完毕才会产生 EOC或 JEOC中断。
ADC_CR1[25:24]用于设置 ADC的分辨率
在这里插入图片描述
CR2
在这里插入图片描述
ADON位用于开关 AD转换器。而 CONT位用于设置是否进行连续转换,ALIGN用于设置数据对齐方式。SWSTART位用于开始规则通道的转换,我们每次(单模式下)都需要向该写 位写 1。

5.转换时间

ADC时钟
ADC 具有两个时钟方案:

  • 用于模拟电路的时钟:ADCCLK,所有 ADC 共用
    此时钟来自于经可编程预分频器分频的 APB2 时钟,该预分频器允许 ADC 在 fPCLK2/2、/4、/6 或 /8 下工作。分频因子由ADC 通用控制寄存器ADC_CCR 的ADCPRE[1:0]设置,可设置的分频系数有2、4、6 和8,注意这里没有1 分频。有关 ADCCLK 的最大值,请参见数据手册。
  • 用于数字接口的时钟(用于寄存器读/写访问)
    此时钟等效于 APB2 时钟。可以通过 RCC APB2 外设时钟使能寄存器 (RCC_APB2ENR)分别为每个 ADC 使能/禁止数字接口时钟。

采样时间
ADC 需要若干个ADC_CLK 周期完成对输入的电压进行采样,采样的周期数可通过ADC 采样时间寄存器ADC_SMPR1 和ADC_SMPR2 中的SMP[2:0]位设置,ADC_SMPR2控制的是通道0~9,ADC_SMPR1 控制的是通道10~17。每个通道可以分别用不同的时间采样。其中采样周期最小是3 个,即如果我们要达到最快的采样,那么应该设置采样周期为3 个周期,这里说的周期就是1/ADC_CLK。
对于每个要转换的通道,采样时间建议尽量长一点以获得较高准确度,但是这样会降低ADC的转换速率。 ADC的转换时间可以由以下公式计算:
T c o v n = 采 样 时 间 + 12 个 周 期 Tcovn=采样时间 +12个周期 Tcovn=+12
当ADCCLK = 30MHz,即PCLK2 为60MHz,ADC 时钟为2 分频,采样时间设置为3
个周期,那么总的转换时为:Tconv = 3 + 12 = 15 个周期 =0.5us。

6.数据寄存器

一切配置好后,我们要将转换后的数据进行保存。ADC 转换后的数据根据转换组的不同,规则组的数据放在ADC_DR 寄存器,注入组的数据放在JDRx。如果是使用双重或者三重模式那规矩组的数据是存放在通用规矩寄存器ADC_CDR 内的。
规则数据寄存器ADC_DR
在这里插入图片描述
ADC 规则组数据寄存器ADC_DR 只有一个,是一个32 位的寄存器,只有低16 位有效并且只是用于独立模式存放转换完成数据。因为ADC 的最大精度是12 位,ADC_DR 是16 位有效,这样允许ADC 存放数据时候选择左对齐或者右对齐,具体是以哪一种方式存放,由ADC_CR2 的11 位ALIGN 设置。假如设置ADC 精度为12 位,如果设置数据为左对齐,那AD 转换完成数据存放在ADC_DR 寄存器的[4:15]位内;如果为右对齐,则存放在ADC_DR 寄存器的[0:11]位内。
规则通道可以有16 个这么多,可规则数据寄存器只有一个,如果使用多通道转换,那转换的数据就全部都挤在了DR 里面,前一个时间点转换的通道数据,就会被下一个时间点的另外一个通道转换的数据覆盖掉,所以当通道转换完成后就应该把数据取走,或者开启DMA 模式,把数据传输到内存里面,不然就会造成数据的覆盖。最常用的做法就是开启DMA 传输。
如果没有使用DMA 传输,我们一般都需要使用ADC 状态寄存器ADC_SR 获取当前ADC 转换的进度状态,进而进行程序控制。
注入数据寄存器ADC_JDRx
ADC 注入组最多有4 个通道,刚好注入数据寄存器也有4 个,每个通道对应着自己的寄存器,不会跟规则寄存器那样产生数据覆盖的问题。ADC_JDRx 是32 位的,低16 位有效,高16 位保留,数据同样分为左对齐和右对齐,具体是以哪一种方式存放,由ADC_CR2 的11 位ALIGN 设置。
通用规则数据寄存器ADC_CDR
规则数据寄存器ADC_DR 是仅适用于独立模式的,而通用规则数据寄存器ADC_CDR是适用于双重和三重模式的。独立模式就是仅仅适用三个ADC 的其中一个,双重模式就是同时使用ADC1 和ADC2,而三重模式就是三个ADC 同时使用。在双重或者三重模式下一般需要配合DMA 数据传输使用。

7.中断

转换结束中断
数据转换结束后,可以产生中断,中断分为四种:规则通道转换结束中断,注入转换通道转换结束中断,模拟看门狗中断和溢出中断。其中转换结束中断很好理解,跟我们平时接触的中断一样,有相应的中断标志位和中断使能位,我们还可以根据中断类型写相应配套的中断服务程序。
模拟看门狗中断
当被ADC 转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是我们开启了模拟看门狗中断,其中低阈值和高阈值由ADC_LTR 和ADC_HTR 设置。例如我们设置高阈值是2.5V,那么模拟电压超过2.5V 的时候,就会产生模拟看门狗中断,反之低阈值也一样。
溢出中断
如果发生DMA 传输数据丢失,会置位ADC 状态寄存器ADC_SR 的OVR 位,如果同时使能了溢出中断,那在转换结束后会产生一个溢出中断。
DMA 请求
规则和注入通道转换结束后,除了产生中断外,还可以产生DMA 请求,把转换好的数据直接存储在内存里面。对于独立模式的多通道AD 转换使用DMA 传输非常有必须要,程序编程简化了很多。对于双重或三重模式使用DMA传输几乎可以说是必要的。一般我们在使用ADC 的时候都会开启DMA 传输。

三、STM32ADC使用

1.结构体详解

ADC_ HandleTypeDef 结构体
代码如下(示例):

 typedef struct {
 ADC_TypeDef *Instance; /*寄存器基地址指针*/
 ADC_InitTypeDef Init; /*ADC 初始化参数结构体*/
 __IO uint32_t NbrOfCurrentConversionRank;//正在转换序列的ADC 数目
 DMA_HandleTypeDef *DMA_Handle; /* DMA 处理程序指针 */
 HAL_LockTypeDef Lock; /*ADC 锁定对象 */
 __IO uint32_t State; /*ADC 通信状态*/
 __IO uint32_t ErrorCode; /*ADC 错误码 */
} ADC_HandleTypeDef;

ADC_ InitTypeDef 结构体
代码如下(示例):

typedef struct {
 uint32_t ClockPrescaler; /*ADC 时钟分频系数 */
 uint32_t Resolution; /*ADC 分辨率选择 */
 uint32_t DataAlign; /*输出数据对齐方式 */
 uint32_t ScanConvMode; /*扫描转换模式 */
 uint32_t EOCSelection; /*转换结束标志使用轮询或者中断*/
 uint32_t ContinuousConvMode; /*连续转换模式 */
 uint32_t NbrOfConversion; /*规格转换序列数目 */
 uint32_t DiscontinuousConvMode; /*不连续采样模式 */
 uint32_t NbrOfDiscConversion; /*不连续采样通道 */
 uint32_t ExternalTrigConv; /*外部事件触发选择 */
 uint32_t ExternalTrigConvEdge; /*外部事件触发极性 */
 uint32_t DMAContinuousRequests; /*DMA 连续请求转换 */
} ADC_InitTypeDef;

ADC_Prescaler:ADC 时钟分频系数选择,ADC 时钟是有PCLK2 分频而来,分频系数决定ADC 时钟频率,可选的分频系数为2、4、6 和8。ADC 最大时钟配置为36MHz。
ADC_Resolution:配置ADC的分辨率,可选的分辨率有12 位、10 位、8 位和6 位。分辨率越高,AD 转换数据精度越高,转换时间也越长;分辨率越低,AD 转换数据精度越低,转换时间也越短。
ADC_DataAlign:转换结果数据对齐模式,可选右对齐ADC_DataAlign_Right 或者左对齐ADC_DataAlign_Left。一般我们选择右对齐模式。
ScanConvMode:可选参数为ENABLE 和DISABLE,配置是否使用扫描。如果是单通道AD转换使用DISABLE,如果是多通道AD转换使用ENABLE。
EOCSelection:可选参数为ENABLE 和DISABLE,指定通过轮询和中断来使用EOC(转换结束)标志进行转换。
ContinuousConvMode:可选参数为ENABLE 和DISABLE,配置是启动自动连续转换还是单次转换。使用ENABLE 配置为使能自动连续转换;使用DISABLE 配置为单次转换,转换一次后停止需要手动控制才重新启动转换。
NbrOfConversion:AD 规则转换通道数目。
DiscontinuousConvMode:不连续采样模式。一般为禁止模式。
NbrOfDiscConversion:ADC 不连续转换通道数目。
ExternalTrigConv:外部触发选择,图 30-1 中列举了很多外部触发条件,可根据项目需求配置触发来源。实际上,我们一般使用软件自动触发。
ExternalTrigConvEdge:外部触发极性选择,如果使用外部触发,可以选择触发的极性,可选有禁止触发检测、上升沿触发检测、下降沿触发检测以及上升沿和下降沿均可触发检测。
DMAContinuousRequests:DMA 请求连续转换,开启DMA 传输时用到。
ADC_ ChannelConfTypeDef 结构体
代码如下(示例):

 typedef struct {
 uint32_t Channel; /*ADC 转换通道*/
 uint32_t Rank; /*ADC 序列数目*/
 uint32_t SamplingTime; /*ADC 采样时间*/
 uint32_t Offset; /*预留未用到,设为0 即可*/
} ADC_ ChannelConfTypeDef;

2.实验

三个实验配置方面完全可以使用cubeMX完成,所以只简单记录下要点。后期自行阅读代码了。

1)独立单通道采集

单通道采集适用AD转换完成中断,在中断服务函数中读取数据,不使用DMA 传输,在多通道采集时才使用DMA 传输。
编程要点

  1. 初始化配置ADC 目标引脚为模拟输入模式;
  2. 使能ADC 时钟;
  3. 配置通用ADC 为独立模式,采样4 分频;
  4. 设置目标ADC 为12 位分辨率,1 通道的连续转换,不需要外部触发;
  5. 设置ADC 转换通道顺序及采样时间;
  6. 配置使能ADC 转换完成中断,在中断内读取转换完数据;
  7. 启动ADC 转换;
  8. 使能软件触发ADC 转换。
    主函数中主要实现电压转换。
    代码如下(示例):
 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
 {
 /* 获取结果 */
 ADC_ConvertedValue = HAL_ADC_GetValue(AdcHandle);
 }
ADC_Vol =(float)ADC_ConvertedValue/4096*(float)3.3;//读取转换的AD 值

2)独立多通道采集

ADC 转换结果数据使用DMA方式传输至指定的存储区,这样取代单通道实验使用中断服务的读取方法。实际上,多通道ADC 采集一般使用DMA 数据传输方式更加高效方便。
编程要点

  1. 初始化配置ADC 目标引脚为模拟输入模式;
  2. 使能ADC 时钟和DMA 时钟;
  3. 配置DMA 从ADC 规矩数据寄存器传输数据到我们指定的存储区;
  4. 配置通用ADC 为独立模式,采样4 分频;
  5. 设置ADC 为12 位分辨率,启动扫描,连续转换,不需要外部触发;
  6. 设置ADC 转换通道顺序及采样时间;
  7. 使能DMA 请求,DMA 在AD 转换完自动传输数据到指定的存储区;
  8. 启动ADC 转换;
  9. 使能软件触发ADC 转换。

我们需要对DMA 进行必要的配置。首先设置外设基地址就是ADC 的规则数据寄存器地址;存储器的地址就是我们指定的数据存储区空间,ADC_ConvertedValue 是我们定义的一个全局数组名,它是一个无符号16 位含有4 个元素的整数数组;ADC 规则转换对应只有一个数据寄存器所以地址不能递增,而我们定义的存储区是专门用来存放不同通道数据的,所以需要自动地址递增。ADC 的规则数据寄存器只有低16 位有效,实际存放的数据只有12 位而已,所以设置数据大小为半字大小。ADC 配置为连续转换模式DMA也设置为循环传输模式。设置好DMA相关参数后就使用HAL_DMA_Init 函数初始化。

3)三重ADC 交替模式采集

AD转换包括采样阶段和转换阶段,在采样阶段才对通道数据进行采集;而在转换阶段只是将采集到的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。独立模式的ADC 采集需要在一个通道采集并且转换完成后才会进行下一个通道的采集。双重或者三重ADC 的机制使用两个或以上ADC 同时采样两个或以上不同通道的数据或者使用两个或以上ADC 交叉采集同一通道的数据。双重或者三重ADC 模式较独立模式一个最大的优势就是转换速度快。
双重或者三重ADC 的其他模式与之类似,可以参考三重ADC 交替模式使用。三重ADC 交替模式是针对同一通道的使用三个ADC交叉采集,就是在ADC1 采样完等几个时钟周期后ADC2 开始采样,此时ADC1 处在转换阶段,当ADC2 采样完成再等几个时钟周期后ADC3 就进行采样此时ADC1 和ADC2 处在转换阶段,如果ADC3 采样完成并且ADC1 已经转换完成那么就可以准备下一轮的循环,这样充分利用转换阶段时间达到增快采样速度的效果。AD 转换过程见下图,利用ADC的转换阶段时间另外一个ADC 进行采样,而不用像独立模式必须等待采样和转换结束后才进行下一次采样及转换。
在这里插入图片描述
双重或者三重ADC 需要使用通用规则数据寄存器ADC_CDR,这点跟独立模式不同。ADC 的通用规则数据寄存器是32 位有效,我们配置ADC 为DMA 模式2,设置数据大小为字大小。ADC 配置为连续转换模式DMA 也设置为循环传输模式。设置好DMA 相关参数后就使能DMA 的ADC 通道。
编程要点

  1. 初始化配置ADC 目标引脚为模拟输入模式;
  2. 使能ADC1、ADC2、ADC3 以及DMA 时钟;
  3. 配置DMA 控制将ADC 通用规矩数据寄存器数据转存到指定存储区;
  4. 配置通用ADC 为三重ADC 交替模式,采样4 分频,使用DMA 模式2;
  5. 设置ADC1、ADC2 和ADC3 为12 位分辨率,禁用扫描,连续转换,不需要外部触发;
  6. 设置ADC1、ADC2 和ADC3 转换通道顺序及采样时间;
  7. 使能ADC1 的 DMA 请求,在ADC 转换完后自动请求DMA 进行数据传输;
  8. 启动ADC1、ADC2 和ADC3 转换;
  9. 使能软件触发ADC 转换。

四、STM32F4DAC简介

STM32F4的 DAC模块 (数字 /模拟转换块)是12位数字输入,电压输出型的DAC。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有两个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步更新2个通道输出。DAC可以通过引脚输入参考电压Vref+(与ADC共用)以获得更精确的转换结果。可以生成噪声波形和三角波形。
在这里插入图片描述
图中 VDDA和 VSSA为 DAC模块模拟部分的供电,而Vref+则是DAC模块的参考电压。 DAC_OUTx就是DAC的输出通道了。
从图中可以看出DAC输出是受DORx寄存器直接控制的,但是我们不能直接往DORx寄存器写入数据,而是通过DHRx间接传给DORx寄存器,实现对DAC输出的控制。前面我们提到,STM32F4的DAC支持8/12位模式,8位模式的时候是固定右对齐,而12位模式又可以设置左对齐 /右对齐。

总结

DAC和ADC板载的很少用,很多场景用的都是外部自行设计的ADC模块,所以要参考模块使用手册,看是否采用的串口和MCU进行的传输,进行程序的编写。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值