一:DAC知识介绍
DAC(Digital-to-Analog Converter,数模转换器)是将数字信号转换为模拟电压信号的器件。单片机内部处理的都是数字量(0 和 1),但很多外部设备需要连续变化的模拟电压来控制,比如调节 LED 亮度、控制电机转速、产生音频信号、输出可调基准电压等,这时就需要 DAC 把数字量转换为对应的模拟电压输出。
STM32C542RC 内部集成了两个 12 位电压输出型 DAC,可以独立输出两路模拟电压,配合定时器、DMA 等外设,可以很方便地实现波形发生、电压输出等应用。
二:STM32C542RC的DAC特性
根据 STM32C542RC 数据手册,其 DAC 模块主要特性如下:
一个 DAC 接口,两个输出通道(2 × 12-bit DAC)
12 位电压输出型数模转换器,可配置为 8 位或 12 位模式
12 位模式下数据支持左对齐或右对齐
可与 DMA 控制器配合使用,每个通道都支持 DMA 传输,并具备 DMA 欠载错误检测
支持双数据 DMA 能力,可减少总线活动
支持外部触发转换,可由基本定时器(TIM6/TIM7)等触发输出
支持噪声波和三角波生成
DAC 输出通道支持缓冲/非缓冲模式,缓冲模式下可提供较高驱动电流
支持缓冲偏移校准,可对每个输出通道单独校准
DAC 输出可从 DAC_OUTx 引脚断开,连接至片上外设使用,断开时引脚可作 GPIO
支持采样保持(Sample and Hold)模式,用于 Stop 模式下的低功耗运行
参考电压来自 VREF+ 引脚(与其他模拟外设共享),可提升输出精度
三:DAC的基本参数
分辨率:12 位(可配置 8 位模式),对应 4096 个离散电压等级
通道数:2 个独立输出通道
输出类型:电压输出型
参考电压:VREF+(范围 2.5V 至 VDDA)
模拟供电电压 VDDA:2.7V ~ 3.6V
输出缓冲:可选开启,开启时输出阻抗降低、驱动能力增强
输出电压范围:缓冲开启时约 0.2V ~ VDDA-0.2V;缓冲关闭时 0 ~ VREF+
四:软件代码的编程过程
本次实验在 NUCLEO-C542RC 开发板上,使用 STM32C542RCT6 的 DAC1 通道 1 经 PA4 引脚输出模拟电压:周期性更新 DAC 转换值生成 0~3.3V 锯齿波,并通过 PA5(板载 LED LD1)翻转指示锯齿波的输出周期。
4.1 使用 STM32CubeMX2 配置 DAC
1. 新建工程:启动 STM32CubeMX2,以 MCU 方式创建工程,搜索并选中 STM32C542RC(完整型号 STM32C542RCT6),输入项目名称 DAC_Output,保存路径使用纯英文目录。
2. 时钟配置:系统时钟为 48 MHz(HSI ÷ 3),DAC 内核时钟为 144 MHz(PSIS 时钟),预分频系数为 1。
3. 启用 DAC1:在左侧外设列表找到 Analog → DAC1,将 Channel 1 设置为 Connected to external pin only,此时 Pinout 视图中 PA4 自动分配为 DAC1_OUT1(模拟模式)。

4. 配置 DAC 参数:Output Buffer 设为 Enable(输出缓冲开启,带负载能力更强);Trigger 设为 None(无触发,软件触发);Data Alignment 设为 12 bits right(12 位右对齐);Output Connection 设为 External。
5. 配置 PA4 指示引脚:右键 PA4 选择 Assign signal → GPIO,Mode 设为 Output,User Label 填入 LD1,作为锯齿波周期指示。
6. 生成工程:在 Project Settings 中将 IDE Format 设为 CMake、CMake Toolchain 设为 GCC,点击 Generate Code 生成 CMake 工程文件。
4.2 编写代码
初始化:
/* 获取 DAC1 句柄(CubeMX 生成) */
hdac1 = mx_dac1_gethandle();
if (hdac1 == NULL) {
return -1;
}
/*
* 无触发模式下,必须先写数据到保持寄存器,再启动通道。
* 顺序不可颠倒,否则首次转换可能输出不确定值。
*/
if (HAL_DAC_SetChannelData(hdac1, HAL_DAC_CHANNEL_1, DAC_OUTPUT_VALUE) != HAL_OK) {
return -1;
}
if (HAL_DAC_StartChannel(hdac1, HAL_DAC_CHANNEL_1) != HAL_OK) {
return -1;
}主要代码:
DAC_valuedata = DAC_valuedata +128 ; if(DAC_valuedata >=4096) DAC_valuedata = 128 ; (void)HAL_DAC_SetChannelData(hdac1, HAL_DAC_CHANNEL_1 , DAC_valuedata) ; HAL_Delay(100);
我要赚赏金
