第11章 数字-模拟转换器

将数字信号转换成模拟信号的器件称为数字-模拟转换器、D/A转换器或DAC。STM32F0系列微控制器片内集成的DAC模块具有12位的转换速度。本章重点介绍该DAC模块的功能和编程方法。

11.1 DAC模块概述

STM32F072VBT6微控制器片内集成有双DAC模块,这两个DAC模块均是12位电压输出数字-模拟转换器,可以按8位或12位模式进行配置,并且可以与DMA控制器配合使用来提高数据处理能力。两个DAC通道可以单独或同时转换,每个通道都具有DMA功能,且具有多种转换触发方式,可以用于特定的噪声波、三角波生成。

11.1.1 DAC的内部结构

DAC模块由可编程的触发选择、控制寄存器、数据保持寄存器DHR、数据输出寄存器DOR、数字-模拟转换电路(由集成的电阻串构成)和非反向配置的运算放大器构成,其内部结构如图11-1所示。

在引脚配置上,DAC模块与ADC模块共用模拟供电引脚VDDA和VSSA,DAC_OUT是DAC通道输出引脚。当DAC_CR寄存器的TEN1位置位时,DAC通道模拟供电开启,经过一小段启动时间后,DAC通道使能,为了避免寄生的干扰和额外的功率消耗,与DAC_OUT复用的GPIO端口在使能DAC通道之前应设置成模拟输入模式。

DAC模块的转换启动方式可以设置成触发和非触发两种方式,当DAC_CR寄存器的TEN1位清0时,模块设置为非触发启动方式,写入DAC_DHRx寄存器的数据会在一个APB时钟周期后自动传送至DAC_DORx寄存器并且立即开始D/A转换,具体时序如图11-2所示。当DAC_CR寄存器的TEN1位置1时,模块被设置为触发启动方式,DAC模块的转换可以由定时计数器、外部中断线等来触发,存入DAC_DHRx寄存器中的数据会在触发事件产生后的第3个PLCK时钟周期后存入DAC_DORx寄存器中并开始D/A转换。

当DAC_DHRx寄存器的数据加载到DAC_DORx寄存器后,经过一个固定的稳定时间,转换后的模拟电压会在模拟输出端DAC_OUTx产生,稳定时间随电源电压和模拟输出负载的不同而有所变化。另外,在DAC模块的输出部分集成有一个运算放大器,它作为输出缓冲器用于减小输出阻抗并提高驱动负载的能力。输出缓冲器可以通过设置DAC_CR寄存器的BOFFx位来使能。

11.1.2 DAC数据格式

在单通道DAC模式下,每一个DAC通道都有3个数据寄存器可用,分别是12位右对齐寄存器、12位左对齐寄存器和8位右对齐寄存器。根据所选择的数据对齐方式,软件需要将数据按以下方式写入指定的数据寄存器,具体方法如图11-3所示。

·8位右对齐:软件将数据加载到DAC_DHR8Rx[7:0]位(存储到DHRx[11:4]位)。

·12位左对齐:软件将数据加载到DAC_DHR12Lx[15:4]位(存储到DHRx[11:0]位)。

·12位右对齐:软件将数据加载到DAC_DHR12Rx[11:0]位(存储到DHRx[11:0]位)。

在DAC双通道模式下,两个DAC通道共用一组(3个)数据寄存器,具体使用方法见图11-4。

·8位右对齐:DAC通道1数据加载到DAC_DHR8RD[7:0]位(存储到DHR1[11:4]位),DAC通道2数据加载到DAC_DHR8RD[15:8]位(存储到DHR2[11:4]位)。

·12位左对齐:DAC通道1数据加载到DAC_DHR12LD[15:4]位(存储到DHR1[11:0]位),DAC通道2数据加载到DAC_DHR12LD[31:20]位(存储到DHR2[11:0]位)。

·12位右对齐:DAC通道1数据加载到DAC_DHR12RD[11:0]位(存储到DHR1[11:0]位)、DAC通道2数据加载到DAC_DHR12LD[27:16]位(存储到DHR2[11:0]位)。

11.1.3 DAC通道转换

数据输出寄存器DAC_DORx不能直接写入,任何传输至DAC通道的数据都必须通过写入数据保持寄存器DAC_DHRx(写DAC_DHR8Rx、DAC_DHR12Lx、DAC_DHR12Rx)执行。如果没有选择硬件触发(DAC_CR寄存器TENx位复位),存储在DAC_DHRx寄存器中的数据会在一个APB时钟周期后自动转移到DAC_DORx寄存器中;当选择硬件触发(DAC_CR寄存器TENx位置位),数据将在触发信号出现后的3个PCLK时钟周期后传输至DAC_DORx寄存器中。当DAC_DHRx中的数据传输至DAC_DORx寄存器后,模拟电压将在tSETTLING时间后从DAC_OUT引脚输出。该时间取决于供电电压和模拟输出负载的大小。DAC通道转换时序如图11-5所示。

传输至DAC_DORx寄存器的数据将会线性地转化为输出电压,其值在0和VDDA之间。每个DAC通道引脚上的模拟输出电压都是由以下公式定义:

11.1.4 DAC触发选择

当DAC_CR寄存器的TENx置位时,DAC转换可以由外部事件来触发,这些触发事件可以是定时器的TRGO信号或外部中断等。DAC_CR寄存器的TSELx[2:0]位域用于设定由哪些可能的事件来触发转换,具体见表11-1。

当在定时器TRGO输出或外部中断线9上检测到一个上升沿时,DAC_DHRx寄存器中保持的数据会转移到DAC_DORx寄存器中。如果选择软件触发,一旦设置SWTRIG位,转换即刻开始,如果DAC_DHRx寄存器的内容装入DAC_DORx寄存器后,SWTRIG位将由硬件复位。

11.1.5 DAC的DMA请求

1.生成DMA请求

每个DAC通道都具有DMA功能。两个DMA通道分别用于处理DAC通道的DMA请求。当已经设置了DMAENx位时,如果发生外部触发(不是软件触发),则DAC模块的DMA请求也会产生。在双通道模式下,如果两个DMAENx位均置1,将生成两个DMA请求。如果只需要一个DMA请求,用户只要设置相应的DMAENx位即可。通过这种方式,应用程序可以在双通道模式下通过一个DMA请求和一个特定的DMA通道来管理两个DAC通道。

2.DMA下溢

DAC模块的DMA请求没有缓冲队列,如果数据在第2个外部触发到时没有及时被收到,DAC_SR寄存器的DMA通道下溢标志DMAUDRx将置位。如果DAC_CR寄存器中的DMAUDRIEx置位,将会产生中断。在产生DMA下溢时,DMA数据传输随即停止,并且不再处理其他DMA请求处理,DAC通道仍将转换原有数据。

软件通过对DMAUDRx位写1来清除该标志,之后,需要将相应的DMAEN位清除,并重新初始化DMA和DAC通道才会重新启动正确的传输。再次启动传输时,软件应当修改DAC触发转换频率或减轻DMA工作负担,以免再次发生DMA下溢。

11.2 DAC波形生成

STM32F072VBT6微控制器内部集成的DAC模块内建有噪声和三角波发生器,可以生成无规律的噪声和幅值频率可编程的波形信号。

11.2.1 噪声波生成

DAC模块噪声波形的生成是通过LFSR(线性反馈移位寄存器)生成随机数,并将该随机数用于D/A转换,以获得可变振幅的伪噪声。通过设置WAVEx[1:0]位域为“01”即可选择生成噪声。LFSR的预加载值为0xAAA,在每次触发事件到来后,经过3个APB时钟周期,该寄存器会依照特定的计算算法完成更新。特定的计算算法如图11-6所示。

LFSR的值可以通过DAC_CR寄存器的MAMPx[3:0]位来部分或完全屏蔽,在不发生溢出的情况下,该值将与DAC_DHRx的内容相加,然后存储到DAC_DORx寄存器中用于生成模拟电压。也就是说,如果我们不向DAC_DHRx中写入数据,存储到DAC_DORx寄存器中的值将与LFSR的生成值相等。如果LFSR为0x0000,将自动向其注入一个“1”(防锁定机制),通过复位WAVEx[1:0]位可以令LFSR波形产生功能关闭。LFSR波形生成的DAC转换时序如图11-7所示。

11.2.2 三角波生成

DAC模块可以生成振幅和频率可编程的三角波信号,也可以生成一个叠加有三角波的直流或慢变信号。通过设置WAVEx[1:0]为“10”,可选择DAC生成三角波,其振幅通过DAC_CR寄存器中的MAMPx[3:0]位进行配置。在每个触发事件的3个APB时钟周期后,内部三角波计数器将会递增。在没有溢出发生的前提下,该计数器的值将与DAC_DHRx寄存器内容相加,所得总和将存储到DAC_DORx寄存器中用于产生模拟电压,该值只要小于MAMPx[3:0]位定义的最大振幅,三角波计数器就会一直递增,一旦达到配置的振幅,计数器将递减至0,然后再次递增,以此类推。触发事件的频率将决定三角波的频率,DAC_DHRx寄存器的值用于定义所叠加直流信号的电压幅值,通过复位WAVEx[1:0]位可以将三角波生成功能关闭。三角波生成的原理和三角波形生成的DAC转换时序如图11-8和图11-9所示。

11.2.3 DAC双通道转换

为了在同时需要两个DAC通道的应用中有效利用总线带宽,可以使用双模寄存器加载转换数据来实现这一功能。DAC模块的双模数据寄存器有3个:DHR8RD、DHR12RD和DHR12LD,软件可以根据需要选择其中一个写入转换数据,这样只需要一个寄存器的访问即可同时驱动两个DAC通道。

编程向导 双通道独立触发(不使用波形发生器)

1)将两个DAC通道触发,使位TEN1、TEN2置位。

2)通过在TSEL1[2:0]、TSEL2[2:0]设置不同的值来配置不同的触发源。

3)将DAC双通道数据加载到所需的DHR寄存器(DAC_DHR12RD、DAC_DHR12LD或DAC_DHR8RD)中。

当DAC通道1触发信号到达时,DHR1寄存器的数据转移到DAC_DOR1中。当DAC通道2触发信号到来时,DHR2寄存器数据转移到DAC_DOR2中。DAC双通道独立触发的过程可以参考以下代码:

/* 使能DAC模块时钟 */
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
/* 使能DAC通道1和2的DMA传输、 使能DAC通道1和2、 选择TIM6和TIM7作为触发源 */
DAC->CR |= DAC_CR_TSEL2_1 | DAC_CR_DMAUDRIE2 | DAC_CR_DMAEN2
| DAC_CR_TEN2 | DAC_CR_EN2
| DAC_CR_DMAUDRIE1 | DAC_CR_DMAEN1 | DAC_CR_BOFF1
| DAC_CR_TEN1 | DAC_CR_EN1;
/* 初始化DAC通道1的值 */
DAC->DHR12R1 = DAC_OUT1_VALUE;
/* 初始化DAC通道2的值 */
DAC->DHR12R2 = DAC_OUT2_VALUE;

编程向导 双通道独立触发(生成不同的LFSR噪声)

1)设置两个DAC通道触发使能位TEN1和TEN2。

2)通过在TSEL1[2:0]和TSEL2[2:0]位域设置不同的值,配置不同的触发源。

3)配置两个DAC通道WAVEx[1:0]位为“01”,并且在MAMP1[3:0]和MAMP2[3:0]位域中设置不同的LFSR掩码值。

4)将DAC双通道数据加载到所需的DHR寄存器(DAC_DHR12RD、DAC_DHR12LD或DAC_DHR8RD)。

当DAC通道1触发到达时,LFSR1计数器内容(使用MAMP1[3:0]配置的掩码值)与DHR1寄存器内容相加,所得总和转移到DAC_DOR1中,LFSR1计数器随即更新。当DAC通道2触发到达时,LFSR2计数器内容(使用MAMP2[3:0]配置的掩码值)与DHR2寄存器内容相加,所得总和转移到DAC_DOR2中,LFSR2计数器随即更新。DAC双通道独立触发生成噪声波的过程可以参考以下代码:

/* 使能DAC外设时钟 */
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
/* 配置波形发生器值为01、 通道1的LFSR屏蔽值为“1000”、 通道2为“0111”, 并设置TIM6和TIM7为触发源 */
DAC->CR |= DAC_CR_WAVE1_0 | DAC_CR_WAVE2_0 | DAC_CR_MAMP1_3
| DAC_CR_MAMP2_2 | DAC_CR_MAMP2_1 | DAC_CR_MAMP2_0
| DAC_CR_TSEL2_1 | DAC_CR_BOFF2 | DAC_CR_TEN2 | DAC_CR_EN2
| DAC_CR_BOFF1 | DAC_CR_TEN1 | DAC_CR_EN1;
/* 初始化DAC通道1的输出值 */
DAC->DHR12R1 = DAC_OUT1_VALUE;
/* 初始化DAC通道2的输出值 */
DAC->DHR12R2 = DAC_OUT2_VALUE;

11.3 DAC函数

11.3.1 DAC类型定义

11.3 DAC函数

11.3.1 DAC类型定义

11.3.2 DAC常量定义

输出常量11-1:DAC状态

11.3.3 DAC函数定义

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐