news 2026/5/20 16:08:15

GD32F103 DAC1实战:手把手教你用PA5引脚输出可调电压,驱动LED调光或电机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GD32F103 DAC1实战:手把手教你用PA5引脚输出可调电压,驱动LED调光或电机

GD32F103 DAC1实战:从零构建可调电压输出系统

在嵌入式开发中,模拟信号输出是控制外部设备的重要手段。GD32F103系列微控制器内置的12位DAC模块,为开发者提供了精准的电压输出能力。本文将带你从硬件连接到软件配置,完整实现一个基于PA5引脚的可调电压输出系统,适用于LED调光、电机控制等多种场景。

1. 硬件准备与电路设计

1.1 所需材料清单

  • GD32F103开发板(如GD32F103C8T6最小系统板)
  • 万用表或示波器(用于测量输出电压)
  • LED及限流电阻(220Ω-1kΩ)
  • 运算放大器(如LM358,可选)
  • 面包板及连接线

1.2 典型连接电路

对于直接驱动LED的应用,推荐以下连接方式:

VDD 3.3V | [R] 220Ω | LED---PA5(DAC1_OUT) | GND

当需要驱动更大负载时,可添加运放缓冲电路:

DAC1_OUT(PA5) ---[10kΩ]---+ | [OPAMP]---输出 | GND

提示:GD32F103的DAC输出驱动能力有限,直接连接时负载阻抗应大于5kΩ

2. 开发环境搭建

2.1 工具链配置

推荐使用以下开发工具组合:

  • IDE: Keil MDK或PlatformIO
  • 编译工具链: ARM-GCC
  • 调试器: J-Link或ST-Link(兼容模式)

2.2 基础工程创建

  1. 新建工程,选择GD32F103对应型号
  2. 添加标准外设库(GD32F10x_Firmware_Library)
  3. 配置系统时钟为108MHz(默认值)

关键时钟配置代码示例:

void SystemClock_Config(void) { rcu_osci_on(RCU_HXTAL); while(!rcu_osci_stab_wait(RCU_HXTAL)); rcu_pll_config(RCU_PLLSRC_HXTAL, RCU_PLL_MUL_9); rcu_osci_on(RCU_PLL_CK); while(!rcu_osci_stab_wait(RCU_PLL_CK)); rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1); rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV1); rcu_apb1_clock_config(RCU_APB1_CKAHB_DIV2); rcu_system_clock_source_config(RCU_SCSS_PLL_CK); while(rcu_system_clock_source_get() != RCU_SCSS_PLL_CK); }

3. DAC基础配置与电压输出

3.1 DAC模块初始化

GD32F103的DAC1对应PA5引脚,初始化步骤如下:

void DAC1_Init_Basic(void) { // 1. 使能时钟 rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_DAC); // 2. 配置PA5为模拟模式 gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_5); // 3. DAC模块配置 dac_deinit(); dac_trigger_disable(DAC1); // 禁用触发模式 dac_wave_mode_config(DAC1, DAC_WAVE_DISABLE); dac_output_buffer_enable(DAC1); // 启用输出缓冲 // 4. 使能DAC1 dac_enable(DAC1); }

3.2 输出电压控制

设置输出电压的三种方法对比:

方法精度响应速度适用场景
直接写入最高即时静态电压设置
定时器触发可调周期性变化
DMA传输最快复杂波形生成

基础输出电压设置函数:

void Set_DAC_Voltage(float voltage) { if(voltage > 3.3f) voltage = 3.3f; if(voltage < 0.0f) voltage = 0.0f; uint16_t dac_value = (uint16_t)(voltage * 4095 / 3.3f); dac_data_set(DAC1, DAC_ALIGN_12B_R, dac_value); }

4. 进阶应用:定时器触发动态调压

4.1 定时器配置

使用TIMER1作为DAC触发源:

void TIMER1_Config(uint32_t freq_hz) { timer_parameter_struct timer_initpara; rcu_periph_clock_enable(RCU_TIMER1); // 计算ARR和PSC值 uint32_t timer_clock = 108000000; // APB2时钟 uint32_t prescaler = (timer_clock / freq_hz / 65536) + 1; uint32_t period = (timer_clock / prescaler / freq_hz) - 1; timer_initpara.prescaler = prescaler - 1; timer_initpara.period = period; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.clockdivision = TIMER_CKDIV_DIV1; timer_initpara.counterdirection = TIMER_COUNTER_UP; timer_init(TIMER1, &timer_initpara); timer_master_output_trigger_source_select(TIMER1, TIMER_TRI_OUT_SRC_UPDATE); timer_enable(TIMER1); }

4.2 触发模式DAC配置

修改DAC初始化以支持定时器触发:

void DAC1_Init_Timer_Trigger(void) { DAC1_Init_Basic(); dac_trigger_source_config(DAC1, DAC_TRIGGER_T1_TRGO); dac_trigger_enable(DAC1); dac_output_buffer_disable(DAC1); // 触发模式下建议禁用缓冲 }

4.3 动态调压实现

创建正弦波输出示例:

#define WAVE_SAMPLES 32 uint16_t sine_wave[WAVE_SAMPLES]; void Generate_Sine_Wave(void) { for(int i=0; i<WAVE_SAMPLES; i++) { float angle = 2 * 3.1415926f * i / WAVE_SAMPLES; float voltage = 1.65f + 1.65f * sinf(angle); // 0-3.3V范围 sine_wave[i] = (uint16_t)(voltage * 4095 / 3.3f); } } void DMA_Config(void) { dma_parameter_struct dma_init_struct; rcu_periph_clock_enable(RCU_DMA1); dma_deinit(DMA1, DMA_CH3); dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_addr = (uint32_t)sine_wave; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT; dma_init_struct.number = WAVE_SAMPLES; dma_init_struct.periph_addr = (uint32_t)&DAC1_R12DH; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA1, DMA_CH3, &dma_init_struct); dma_circulation_enable(DMA1, DMA_CH3); dma_channel_enable(DMA1, DMA_CH3); dac_dma_enable(DAC1); }

5. 实际应用案例:LED调光控制

5.1 呼吸灯实现

利用PWM原理通过DAC模拟实现:

void Breathing_LED(void) { uint16_t brightness = 0; int8_t direction = 1; while(1) { Set_DAC_Voltage(brightness * 3.3f / 4095.0f); delay_ms(10); brightness += direction * 10; if(brightness >= 4095) direction = -1; if(brightness <= 0) direction = 1; } }

5.2 多级亮度控制

创建亮度预设表:

const float brightness_levels[] = { 0.0f, // 关闭 0.5f, // 25% 1.0f, // 50% 1.65f, // 75% 2.2f, // 90% 3.3f // 100% }; void Set_Brightness(uint8_t level) { if(level >= sizeof(brightness_levels)/sizeof(float)) level = sizeof(brightness_levels)/sizeof(float) - 1; Set_DAC_Voltage(brightness_levels[level]); }

6. 调试技巧与性能优化

6.1 常见问题排查

  • 无输出:检查PA5模式是否为GPIO_MODE_AIN
  • 电压不准:测量VREF+引脚电压(应为3.3V)
  • 响应延迟:降低定时器周期或使用直接写入模式

6.2 性能优化建议

  1. 对于静态电压输出,禁用触发和DMA以减少开销
  2. 需要快速更新时,使用DMA而非定时器中断
  3. 输出缓冲启用可改善驱动能力但增加功耗

测量代码执行时间的实用方法:

void Measure_Update_Time(void) { uint32_t start, end; start = DWT->CYCCNT; Set_DAC_Voltage(1.65f); end = DWT->CYCCNT; printf("Update time: %f us\r\n", (end-start)/108.0f); }

在项目开发中,DAC模块的灵活运用可以大大简化模拟电路设计。特别是在需要精确控制电压而非PWM占空比的场景下,DAC方案能提供更线性的响应特性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 16:08:13

从PIR到红外阵列:MAXREFDES131#实现智能人体存在检测与组网

1. 项目概述&#xff1a;从传统PIR到红外阵列的智能升级在智能家居和楼宇自动化领域&#xff0c;人体感应一直是个基础但核心的功能。我们习惯了那种“人来灯亮&#xff0c;人走灯灭”的被动式红外&#xff08;PIR&#xff09;传感器&#xff0c;它确实解决了有无的问题&#x…

作者头像 李华
网站建设 2026/5/20 16:06:24

Linux内核延时机制详解:从忙等待到休眠与定时器

1. 内核延时&#xff1a;从“傻等”到“休眠”的本质区别在Linux内核开发中&#xff0c;处理时间延迟是再常见不过的需求。无论是等待硬件响应、实现简单的轮询间隔&#xff0c;还是调度未来的某个任务&#xff0c;你都需要和内核的“时钟”打交道。但很多刚接触内核编程的朋友…

作者头像 李华
网站建设 2026/5/20 16:05:22

将Hermes Agent工具连接至Taotoken的详细配置步骤与注意事项

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 将Hermes Agent工具连接至Taotoken的详细配置步骤与注意事项 Hermes Agent 是一款流行的开源 AI 智能体框架&#xff0c;支持通过自…

作者头像 李华
网站建设 2026/5/20 16:04:35

OpenPLC Editor:开源工业控制系统的完整解决方案与实战指南

OpenPLC Editor&#xff1a;开源工业控制系统的完整解决方案与实战指南 【免费下载链接】OpenPLC_Editor 项目地址: https://gitcode.com/gh_mirrors/ope/OpenPLC_Editor 想象一下&#xff0c;你正在为一个工业自动化项目选择PLC编程工具&#xff0c;面对市场上昂贵的商…

作者头像 李华
网站建设 2026/5/20 16:03:40

告别PyTorch训练循环的‘脏活累活’:用PyTorch Lightning保姆级教程,5分钟搞定你的第一个深度学习项目

PyTorch Lightning实战指南&#xff1a;用模块化思维重构深度学习项目 深度学习项目开发中&#xff0c;最令人头疼的往往不是模型设计本身&#xff0c;而是那些重复性的训练循环代码。每次开始新项目时&#xff0c;我们都要重新编写训练、验证、日志记录等样板代码&#xff0c;…

作者头像 李华