一、DAC 是什么

DAC 的全称是 Digital-to-Analog Converter,即数字/模拟转换器。

ADC 负责把模拟量转换成数字量,而 DAC 正好相反,它负责把数字量转换成模拟电压。

典型数据流可以理解为:

传感器 -> ADC -> 单片机 -> DAC -> 模拟控制系统

ADC 和 DAC 是模拟电路与数字电路之间的桥梁:

外设 方向 作用
ADC 模拟量 -> 数字量 采集外部模拟信号
DAC 数字量 -> 模拟量 输出可控模拟电压

DAC 常用于波形发生、音频输出、模拟控制电压输出、传感器模拟、比较器参考电压生成等场景。

二、DAC 的特性参数

1. 分辨率

分辨率表示 DAC 输出模拟电压的最小增量,通常用二进制位数表示,例如 8 位、12 位等。

以 12 位 DAC 为例:

数字量范围 = 0 ~ 4095
总刻度数 = 2^12 = 4096

如果参考电压为 3.3 V,则理论最小输出电压步进约为:

3.3 / 4096 ≈ 0.000805 V

也就是约 0.805 mV。

2. 建立时间

建立时间表示 DAC 将一个数字量转换为稳定模拟信号所需要的时间。

当写入新的数字量后,DAC 输出并不会瞬间稳定到目标电压,而是需要经过一段建立时间。输出频率越高、波形变化越快,对建立时间要求越高。

3. 精度

DAC 精度表示实际输出特性曲线与理想特性曲线之间的偏差。

常见误差来源包括:

  • 比例系统误差

  • 失调误差

  • 非线性误差

  • 元件参数误差

  • 基准电压不稳定

  • 运算放大器零漂

因此,分辨率高不代表实际精度一定高。实际输出电压还会受到参考电压、电源噪声、输出负载和模拟电路设计影响。

三、DAC 参考电压与输出范围

STM32 DAC 模拟部分通常由 VDDAVSSA 供电。

信号 作用
VDDA DAC 模拟电源
VSSA DAC 模拟地
VREF+ DAC 正参考电压
VREF- DAC 负参考电压

常见情况下:

VREF- = 0 V
VREF+ = 3.3 V

因此 DAC 输出电压范围通常为:

0 V <= VOUT <= 3.3 V

更一般地说,DAC 输出范围满足:

VREF- <= VOUT <= VREF+

如果希望得到更稳定的模拟输出,需要重点关注:

  • VDDA 电源质量

  • 模拟地布线

  • 参考电压稳定性

  • 输出端负载

  • 是否启用输出缓冲

四、DAC 数据格式

STM32 DAC 支持 8 位和 12 位数据格式。

1. 8 位模式

8 位模式只能右对齐。

常见寄存器:

寄存器 作用
DHR8Rx 单通道 8 位右对齐数据保持寄存器
DHR8RD 双 DAC 通道 8 位右对齐数据保持寄存器

8 位模式数据范围:

0 ~ 255

2. 12 位模式

12 位模式支持右对齐和左对齐。

数据格式 常见寄存器
12 位右对齐 DHR12RxDHR12RD
12 位左对齐 DHR12LxDHR12LD

12 位模式数据范围:

0 ~ 4095

普通应用中,12 位右对齐最常用,因为数字量和理论输出电压换算关系最直观。

五、DAC 工作原理

DAC 的基本过程可以理解为:

写入数字量到 DHRx -> 数据转移到 DORx -> DAC 输出模拟电压

其中:

名称 说明
DHRx 数据保持寄存器,CPU 或 DMA 写入数字量
DORx 数据输出寄存器,DAC 根据该值产生模拟输出
VOUT DAC 通道最终输出的模拟电压

数据从 DHRx 转移到 DORx 后,模拟输出电压还需要经过建立时间 VSETTLING 才能稳定可用。

六、DAC 触发方式

DAC 支持三种常见触发方式:

触发方式 说明
自动触发 禁止触发功能时,写入数据后自动转移
软件触发 由软件触发位启动转换
外部事件触发 由定时器等外部事件触发转换

1. 禁止触发模式

TENx = 0 时,表示禁止触发功能。

此时写入 DHRx 后,数据会在约 1 个 APB1 时钟周期后转移到 DORx

这种方式适合直接输出固定电压,使用简单。

2. 外部事件触发

TENx = 1TSELx[2:0] 选择外部事件时,DAC 会由外部事件触发转换。

例如可以使用定时器 TRGO 事件定时触发 DAC 输出,这种方式适合生成周期波形。

外部事件触发时,DHRx 转移到 DORx 通常需要约 3 个 APB1 时钟周期。

3. 软件触发

TENx = 1TSELx[2:0] = 111 时,表示选择软件触发。

此时通过设置 SWTRIGx 位触发转换,数据会在约 1 个 APB1 时钟周期后转移到 DORx

七、DAC DMA 请求

DAC 可以配合 DMA 使用。

DMAENx = 1 时,DAC 可以产生 DMA 请求,使 DMA 自动把内存中的数据搬运到 DAC 数据保持寄存器。

典型应用:

  • 正弦波输出

  • 音频数据输出

  • 任意波形发生

  • 周期变化的模拟控制信号

DAC + DMA + 定时器触发是生成稳定周期波形的常见组合:

定时器TRGO -> 触发DAC转换
DMA -> 自动写入下一个波形采样点
DAC -> 输出模拟电压

这种方式可以大幅减少 CPU 参与,提高波形输出稳定性。

八、DAC 输出电压计算

1. 12 位模式

12 位 DAC 的数字量范围为 0 ~ 4095

理论输出电压可按下面公式计算:

VOUT = DOR / 4095 * VREF+

也有工程中使用 4096 作为刻度数进行近似:

VOUT ≈ DOR * VREF+ / 4096

其中:

  • VOUT:DAC 输出电压

  • DOR:DAC 输出寄存器中的数字量

  • VREF+:DAC 正参考电压

如果 VREF+ = 3.3 V,输出中间电压附近可设置:

DOR ≈ 2048
VOUT ≈ 2048 * 3.3 / 4096 ≈ 1.65 V

2. 8 位模式

8 位 DAC 的数字量范围为 0 ~ 255

理论输出电压可按下面公式估算:

VOUT ≈ DOR * VREF+ / 256

如果 VREF+ = 3.3 V,最小电压步进约为:

3.3 / 256 ≈ 12.89 mV

九、DAC 普通输出配置流程

使用 HAL 库输出固定电压时,可以按以下流程理解。

1. 初始化 DAC

调用:

HAL_DAC_Init();

该函数用于初始化 DAC 外设。

2. 完成 MSP 初始化

调用或重写:

HAL_DAC_MspInit();

MSP 初始化通常包括:

  • DAC 外设时钟

  • GPIO 模拟输出配置

  • NVIC 或 DMA 相关资源

DAC 输出引脚需要配置为模拟模式。

3. 配置 DAC 通道

调用:

HAL_DAC_ConfigChannel();

通道配置重点包括:

  • 是否使能输出缓冲

  • 触发源选择

  • 是否使用噪声波或三角波生成

4. 启动 DAC

调用:

HAL_DAC_Start();

5. 设置输出数字量

调用:

HAL_DAC_SetValue();

常见参数包括:

  • DAC 通道

  • 数据对齐方式

  • 要输出的数字量

6. 读取输出数字量

如有需要,可以调用:

HAL_DAC_GetValue();

该函数读取的是 DAC 当前设置的数字量,不等于直接测量模拟输出电压。实际电压仍应通过 ADC、万用表或示波器测量确认。

十、DAC 波形输出思路

DAC 不仅可以输出固定电压,也可以输出随时间变化的波形。

1. 三角波输出思路

三角波可以通过周期性改变 DAC 输出数字量实现。

基本思路:

数字量从 0 递增到最大值
再从最大值递减到 0
循环重复

需要关注:

  • 最大输出数字量

  • 每次变化步进

  • 每个采样点之间的延时

  • DAC 建立时间

  • CPU 软件更新是否足够稳定

如果采样点更新完全由软件延时控制,波形频率和稳定性会受到 CPU 占用、中断和延时精度影响。

2. 正弦波输出思路

正弦波通常通过查表法实现。

基本流程:

提前生成正弦波采样表
定时器按固定频率触发 DAC
DMA 按顺序把采样表数据写入 DAC
DAC 输出连续变化的模拟电压

正弦波输出频率和两个参数有关:

输出频率 = DAC触发频率 / 单周期采样点数

例如一个正弦周期使用 100 个采样点,定时器触发频率为 10 kHz,则输出正弦波频率为:

10000 / 100 = 100 Hz

3. DAC + DMA + 定时器的优势

相比 CPU 循环写 DAC,使用 DMA 和定时器有明显优势:

方式 特点
CPU 软件写 DAC 简单,但时间稳定性较差,占用 CPU
定时器触发 + DMA 采样间隔稳定,占用 CPU 少,适合连续波形

波形输出时,推荐使用定时器产生固定触发节拍,再由 DMA 搬运波形表数据。

十一、DAC + DMA 波形输出配置流程

使用 DAC + DMA + 定时器输出周期波形时,可以按以下流程理解。

1. 初始化 DMA

调用:

HAL_DMA_Init();

DMA 负责把内存中的波形数据搬运到 DAC 数据寄存器。

2. 关联 DMA 和 DAC 句柄

调用:

__HAL_LINKDMA();

通过句柄关联,HAL 库才能正确管理 DAC 与 DMA 的关系。

3. 初始化 DAC

调用:

HAL_DAC_Init();

4. 完成 DAC MSP 初始化

调用或重写:

HAL_DAC_MspInit();

需要配置 DAC 时钟、GPIO、DMA 等底层资源。

5. 配置 DAC 通道

调用:

HAL_DAC_ConfigChannel();

此时通常需要选择定时器触发源。

6. 启动 DMA 传输

调用:

HAL_DMA_Start();

DMA 源地址通常是波形数组,目标地址通常是 DAC 数据保持寄存器。

7. 配置并启动定时器

调用:

HAL_TIM_Base_Init();
HAL_TIM_Base_Start();

定时器溢出频率决定 DAC 更新频率。

8. 配置定时器触发 DAC

调用:

HAL_TIMEx_MasterConfigSynchronization();

通过定时器 TRGO 事件触发 DAC 转换。

9. 启动或停止 DAC DMA 输出

常用函数:

HAL_DAC_Start_DMA();
HAL_DAC_Stop_DMA();

启动后,DAC 会按定时器节拍输出波形数组中的数据。

十二、PWM DAC 技术

STM32 内部 DAC 输出通道数量有限,有些应用可能需要更多路模拟输出。如果精度要求不高,可以使用 PWM + RC 滤波器实现低成本 DAC 输出。

1. PWM DAC 的基本思想

PWM 是周期固定、占空比可调的数字信号。

从频域角度看,PWM 可以分解为:

  • 一个直流分量

  • 若干交流谐波分量

如果让 PWM 信号经过低通滤波器,滤除高频交流谐波,只保留直流分量,就可以得到一个近似模拟电压。

基本关系:

PWM占空比越大 -> 滤波后平均电压越高
PWM占空比越小 -> 滤波后平均电压越低

如果 PWM 高电平为 VH,低电平为 VL,占空比为 D,则理想平均电压为:

VOUT = D * VH + (1 - D) * VL

VH = 3.3 VVL = 0 V 时:

VOUT = D * 3.3 V

2. PWM DAC 分辨率

定时器 PWM 周期由 ARR 决定,占空比由 CCRx 决定。

如果 PWM 计数周期为 N,则占空比最小变化约为 1 / N

PWM DAC 分辨率可近似表示为:

分辨率 = log2(N)

例如:

N 近似分辨率
256 8 位
4096 12 位

STM32 定时器通常是 16 位或 32 位,因此理论上可以得到较高的 PWM DAC 分辨率。

但需要注意:

分辨率越高,PWM频率越低
PWM频率越低,低通滤波器设计越困难

所以 PWM DAC 必须在分辨率、响应速度、纹波和滤波器复杂度之间权衡。

3. RC 低通滤波器要求

PWM DAC 的关键是滤除高频谐波。

以 8 位分辨率为例,如果参考电压为 3.3 V,则 1 LSB 约为:

3.3 / 256 = 0.01289 V

如果一次谐波最大幅度约为:

2 * 3.3 / π ≈ 2.1 V

为了让一次谐波对输出电压的影响小于 1 LSB,需要低通滤波器提供的衰减约为:

-20lg(2.1 / 0.01289) ≈ -44 dB

这说明 PWM DAC 的精度不仅取决于定时器分辨率,还强烈依赖滤波器设计。

4. 二阶 RC 低通滤波器

二阶 RC 滤波器比一阶 RC 滤波器具有更强的高频衰减能力。

常见截止频率公式为:

f = 1 / (2πRC)

如果使用两级 RC,常见设计要求为:

R1 * C1 = R2 * C2 = RC

滤波器截止频率需要根据 PWM 频率和目标信号带宽选择:

  • 截止频率太高:PWM 纹波滤除不充分。

  • 截止频率太低:输出响应变慢,目标波形被削弱。

Logo

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

更多推荐