第一次接触GD32的DAC功能时,我也被数据手册里密密麻麻的寄存器描述搞得头晕。但实际用起来才发现,只要掌握几个关键点,就能快速实现精准电压输出。DAC(数字模拟转换器)简单来说就是把数字信号转换成模拟电压,在传感器校准、音频输出等场景特别实用。
GD32的DAC模块通常有12位分辨率,意味着可以输出4096个不同的电压等级。以3.3V基准电压为例,每个步进大约是0.8mV的精度,完全能满足大多数精密控制需求。我在做温湿度传感器校准时,就是通过DAC输出不同参考电压来修正读数偏差的。
GD32的DAC输出通道通常固定在特定引脚,比如GD32F103系列的DAC0对应PA4,DAC1对应PA5。这里有个新手容易踩的坑:一定要把引脚模式设置为模拟输入(GPIO_MODE_AIN),即使它是输出功能!这是因为DAC模块需要直接控制引脚电压电平。
实测中发现,如果错误配置为推挽输出,虽然能看到电压变化,但输出值会严重失真。建议在初始化时先关闭所有中断,避免配置过程中被干扰:
c复制// 时钟使能(必须步骤)
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_DAC);
rcu_periph_clock_enable(RCU_AF); // 复用功能时钟
// 引脚配置
gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5);
DAC的库函数看似复杂,其实主要就这五个关键配置:
dac_deinit()相当于硬件重启dac_trigger_disable()关闭触发dac_wave_mode_config(DAC0, DAC_WAVE_DISABLE)禁用波形dac_output_buffer_enable(DAC0)能增强驱动能力dac_enable(DAC0)才真正启动转换特别注意缓冲区使能的取舍:开启后输出阻抗更低,但最小输出电压会被抬高约0.2V。我在做0-1V精密输出时,就因为这个特性不得不重新调整了量程。
DAC的核心公式其实很简单:
code复制输出电压 = (设定值 × 基准电压) / 4096
但实际应用中要考虑三个关键因素:
DAC_ALIGN_12B_R)时直接代入0-4095这里有个实用技巧:先用万用表测量实际基准电压。有次我的输出总是偏高3%,后来发现是板载LDO输出实际为3.42V。修正公式后立即获得±0.1%的精度。
要获得稳定输出,这几个配置缺一不可:
main()开始时添加100ms延时,等电源稳定dac_deinit()清除残留状态分享一个真实案例:在电机控制项目中,DAC输出出现周期性毛刺。最后发现是PWM中断里调用了DAC设置函数,改为在主循环中更新后问题解决。
c复制void DAC_Config(uint32_t dac_channel)
{
dac_deinit();
dac_trigger_disable(dac_channel);
dac_wave_mode_config(dac_channel, DAC_WAVE_DISABLE);
dac_output_buffer_enable(dac_channel); // 根据需求选择
dac_enable(dac_channel);
}
void Set_DAC_Voltage(uint32_t dac_channel, float voltage)
{
float vref = 3.3f; // 实测基准电压
uint16_t dat = (uint16_t)(voltage * 4096 / vref);
dac_data_set(dac_channel, DAC_ALIGN_12B_R, dat);
}
c复制// 分段线性补偿
if(dat < 2048) {
dat = (uint16_t)(dat * 0.998f);
} else {
dat = (uint16_t)(dat * 1.002f - 8);
}
最近在做一个工业控制器项目,需要同时输出多路0-10V信号。通过外接运放放大DAC输出时,发现高温环境下精度下降。后来在DAC输出端增加了电压跟随器,并选用低温漂电阻,最终在-40℃~85℃范围内保持了±0.05%的稳定性。