我们介绍过了 STM32F1 的模数转换器 ADC,接下来我们学习下STM32F1 的数模转换器 DAC。要实现的功能是:通过 K_UP 与K_DOWN 按键控制 STM32F1 DAC1 输出电压,通过串口将 DAC1 输出的电压值打印显示,D1 指示灯闪烁提示系统运行。学习时可以参考《STM32F10x 中文参考手册》-12 数模转换器(DAC)章节,特别是寄存器介绍部分。
STM32F1 DAC简介
DAC(Digital to analog converter)即数字模拟转换器,它可以将数字信号转换为模拟信号。它的功能与 ADC 相反。在常见的数字信号系统中,大部分传感器信号被转化成电压信号,而 ADC 把电压模拟信号转换成易于计算机存储、处理的数字编码,由计算机处理完成后,再由 DAC 输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。如音频信号的采集及还原就是这样一个过程。
STM32F1 DAC 模块是 12 位电压输出数模转换器, 它可以配置为 8 位或 12位模式,也可以与 DMA 控制器配合使用。DAC 工作在 12 位模式下,数据可以采用左对齐或右对齐。DAC 工作在 8 位模式下,数据只有右对齐方式。DAC 有两个输出通道,每个通道各有一个转换器。在 DAC 双通道模式下,每个通道可以单独进行转换;当两个通道组合在一起同步执行更新操作时, 也可以同时进行转换。
DAC 可通过一个输入参考电压引脚 VREF+(与 ADC 共享)来提高转换后的数据精度。
STM32F1 DAC 主要特性:
● 2 个 DAC 转换器:每个转换器对应 1 个输出通道
● 8 位或者 12 位单调输出
● 12 位模式下数据左对齐或者右对齐
● 同步更新功能
● 噪声波形生成
● 三角波形生成
● 双 DAC 通道同时或者分别转换
● 每个通道都有 DMA功能
● 外部触发转换
● 输入参考电压 VREF+
STM32F1 DAC结构框图
STM32F1 DAC 拥有这么多功能,是由 DAC 内部结构决定。要更好的理解STM32F1 的 DAC,就需要了解它内部的结构。如下图所示:(大家也可以查看《STM32F10x 中文参考手册》-12 数模转换器(DAC)-12.3 章节内容)。
我们把 DAC 结构框图分成5个子模块,按照顺序依次进行简单介绍。
(1)标号 1:电压输入引脚
同ADC 一样,VDDA 与 VSSA 是 DAC 模块的供电引脚,而 VREF+是DAC 模块的参考电压,开发板上已经将 VREF+连接到 VDDA,所以参考电压范围是0-3.3V。
(2)标号 2:DAC 转换
DAC 输出是受 DORx 寄存器直接控制的,但是我们不能直接往 DORx 寄存器写入数据,而是通过 DHRx 间接的传给 DORx 寄存器,实现对 DAC 输出的控制。
如果未选择硬件触发 ( DAC_CR 寄存器中的 TENx 位复位) , 那么经过一个 APB1时钟周期后,DAC_DHRx 寄存器中存储的数据将自动转移到 DAC_DORx 寄存器。
但是, 如果选择硬件触发 (置位 DAC_CR 寄存器中的 TENx 位) 且触发条件到来,将在三个 APB1 时钟周期后进行转移。
当 DAC_DORx 加载了 DAC_DHRx 内容时,模拟输出电压将在一段时间tSETTLING 后可用,具体时间取决于电源电压和模拟输出负载。我们可以从
STM32F103ZET6 的数据手册查到的典型值为 3us,最大是 4us。所以 DAC 的转换速度最快是 250K 左右。
本文我们介绍的是不使用硬件触发(TENx=0),其转换时序图如下图所示:
DHRx 内装载着我们要输出的数据,前面我们提到,STM32F1 的 DAC 支持8/12 位模式,8 位模式的时候数据是固定的右对齐的,而 12 位模式数据可以设置左对齐/右对齐。对于DAC单通道 x,总共有 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 通道 1,采用 12 位右对齐方式,所以采用第3种情况。
每个 DAC 通道都具有 DMA 功能。两个 DMA 通道用于处理 DAC 通道的DMA请求。当 DMAENx 位置 1 时,如果发生外部触发(而不是软件触发),则将产生DAC DMA 请求。DAC_DHRx 寄存器的值随后转移到 DAC_DORx 寄存器。在双通道模式下,如果两个 DMAENx 位均置 1,则将产生两个 DMA 请求。如果只需要一个 DMA 请求,应仅将相应 DMAENx 位置 1。这样&#x