【STM32 CubeMX + Keil】DAC 输出0~3.3V间任意电压
本文示范使用 CubeMX 配置 DAC,并通过代码实现指定电压输出。
目录
1、DAC 是什么?
二、STM32 内置 DAC 概述
三、CubeMX 配置 DAC
四、代码实现
五、编写电压输出函数
1、DAC 是什么?
DAC(Digital-to-Analog Converter,数模转换器)是一种将数字信号转换为模拟信号的关键外设。
干的事很简单:把数字代码变成模拟电压。
- 输入:0–4095(12位数字值)
- 输出:0V~3.3V(对应范围的模拟电压)
你就理解是个能用代码精确调压的数字电位器,写个值,改变输出电压,贼方便。
典型应用场景:
- 📈 生成各种波形:DAC最典型的应用,如正弦波、三角波等。
- 🔊 音频输出:通过DAC将解码后的数字音频数据转换为模拟信号,经功率放大后驱动扬声器。
- ⚙️ 控制模拟电路:比如调电机转速
- 🔋 作为可编程电压基准源
二、STM32 内置 DAC 概述
大多数 STM32 芯片都内置了 DAC,不过不同系列的通道数有点区别。
1、分辨率
- 清一色 12 位,范围 0–4095;
- STM32所有型号,内置DAC都是12位。
2、输出能力
- 电压:0V ~ 3.3V(与 VDDA 电压相关);
- 电流:就几mA;别指望直接驱动大负载;
3、通道数量
- 多数型号 2 路输出。通道1是PA4、通道2是PA5,不管啥型号都焊死不变。
- G系列是个卷王:4路甚至7路D。
- ⚠️注意:F103C8没有DAC!要F103RC或以上型号才有。
4、触发方式
- 软件触发:程序直接控制,写个值立马输出。前期调电路、验证功能时最常用。
- 定时器触发:通常搭配DMA,自动从数组里搬波形数据给DAC,用来产生精确频率的正弦波、三角波等,自动刷波形,CPU 可躺平。
- 外部引脚触发:用外部信号(如传感器、开关)直接触发DAC输出。信号来了立马响应,比中断还快。
三、CubeMX 配置 DAC
1、新建工程
若你已有现成的CubeMX工程,打开ioc文件即可在工程里进行DAC功能的添加、配置 。
如果打算新建工程进行测试,本文不啰嗦操作过程,可参考下面文章:
① 新建 STM32F407VE 工程
2、打勾使能DAC通道
DAC的配置,极度简单。
- 两个通道,需要哪个通道输出,打勾即可。
- 其它参数默认。
参数说明:
- External Trigger (外部触发):不打勾。EXTI9触发,本篇示例无需使用。
- Output Buffer (输出缓存):Enable。降低输出阻抗,可直接驱动外部负载(省外加运放)。高精度场合建议关闭以减少误差。
- Tigger (触发方式): None,直接调用
DAC_SetChannelxData()
即可设置输出电压,最简单直接。注意,当选择 Software Trigger 软件触发时,设置电压值后必须额外调用DAC_SoftwareTriggerCmd()
才能生效,
触发信号仅持续1个APB1时钟周期,每次修改电压都需重新触发。
3、生成工程配置
DAC的配置,只有上面一步,已全部完成。现在点击"Generate Code"生成工程代码即可。
四、代码实现
用CubeMX配置好后,Kiel里操作DAC主要就这3个函数。
- 启动DAC:
HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
- 停止DAC转换:
HAL_DAC_Stop(&hdac, DAC_CHANNEL_1);
- 设置输出值:
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048);
输出示例:让PA4输出1.7V,PA5输出2.8V, 几行代码即可实现:
HAL_DAC_Start(&hdac, DAC_CHANNEL_1); // 开启通道1
HAL_DAC_Start(&hdac, DAC_CHANNEL_2); // 开启通道2HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2110); // 通道1输出1.7V
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, 3475); // 通道2输出2.8V
为啥1.7V是2110,2.8V是3475?
- DAC是12位,最大值是4095。即,0V对应0000,3.3V对应最大值4095。
- 计算公式:数字值 = (目标电压÷3.3) x 4095
- 1.7V的DAC值是:(1.7÷3.3)x4095 = 2110。 同理,2.8V的DAC值:(2.8÷3.3)x4095=3475。
完成后,是这个样子的:
验证结果
用万用表测PA4引脚电压,确认输出准确:
五、编写电压输出函数
为了减少手工换算DAC值与电压值,编写一个电压输出函数,直接输入mV值即可转换输出。
还是上面那个:数字值 = (目标电压÷3.3) x 4095
编写函数:
// 设置通道1电压值; 单位:mV; 值范围: 0~3300;
void DAC_PA4SetVoltage(uint16_t mV)
{if (mV > 3300){mV = 3300;}uint16_t val = (uint16_t)(mV * 4095UL / 3300); // 毫伏转换为DAC值HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, val); // 设置DAC通道1的值
}// 设置通道2电压值; 单位:mV; 值范围: 0~3300;
void DAC_PA5SetVoltage(uint16_t mV)
{if (mV > 3300){mV = 3300;}uint16_t val = (uint16_t)(mV * 4095UL / 3300); // 毫伏转换为DAC值HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, val); // 设置DAC通道2的值
}
完成后,是这个样子: