STM32-DAC
一、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 模拟部分通常由 VDDA 和 VSSA 供电。
| 信号 | 作用 |
|---|---|
| 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 位右对齐 | DHR12Rx、DHR12RD |
| 12 位左对齐 | DHR12Lx、DHR12LD |
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 = 1 且 TSELx[2:0] 选择外部事件时,DAC 会由外部事件触发转换。
例如可以使用定时器 TRGO 事件定时触发 DAC 输出,这种方式适合生成周期波形。
外部事件触发时,DHRx 转移到 DORx 通常需要约 3 个 APB1 时钟周期。
3. 软件触发
当 TENx = 1 且 TSELx[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 V、VL = 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 纹波滤除不充分。
-
截止频率太低:输出响应变慢,目标波形被削弱。
更多推荐


所有评论(0)