当前位置: 首页 > news >正文

用STM32F103的DAC和ADC做个简易信号发生器:从PA4输出,PA1读取并串口显示

STM32F103 DAC与ADC闭环系统实战:构建可交互信号发生器

在嵌入式开发中,数字模拟转换(DAC)和模拟数字转换(ADC)是两个基础但极其重要的外设功能。许多开发者虽然能独立使用它们,却很少尝试将二者结合形成完整的闭环系统。本文将带您用STM32F103的DAC和ADC构建一个实时可调的信号发生器,通过PA4输出模拟信号,同时用PA1读取反馈值并通过串口显示,实现"设置-输出-测量-验证"的全流程。

1. 系统架构设计与核心组件

1.1 硬件资源规划

STM32F103ZET6芯片内置了两个12位精度的DAC模块和一个12位ADC模块,这是我们项目的硬件基础。系统需要合理分配以下资源:

  • DAC通道1:使用PA4引脚作为模拟输出
  • ADC通道1:使用PA1引脚作为模拟输入
  • USART1:用于PC通信和数据显示
  • GPIO按键:用于交互控制输出电压

关键参数对比表

模块分辨率参考电压转换时间输出范围
DAC12位3.3V0-3.3V
ADC12位3.3V1μs0-3.3V

1.2 软件架构设计

整个系统采用分层设计思想,各功能模块通过清晰的接口交互:

主控制循环 ├─ 用户输入处理(按键扫描) ├─ DAC输出控制 ├─ ADC采样处理 └─ 数据显示输出(串口)

这种架构保证了系统的可扩展性,未来可以方便地添加新功能如波形生成、数据存储等。

2. 硬件初始化与配置

2.1 时钟与GPIO配置

所有外设使用前必须使能相应时钟,这是STM32编程的基本要求:

// 使能各外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

PA4(DAC输出)和PA1(ADC输入)都需要配置为模拟模式:

GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入模式 GPIO_Init(GPIOA, &GPIO_InitStructure);

注意:即使DAC是输出功能,其引脚也必须配置为模拟输入模式,这是STM32的特殊设计要求。

2.2 DAC模块深度配置

DAC的配置需要考虑输出缓冲、触发方式等关键参数:

DAC_InitTypeDef DAC_InitStructure; DAC_InitStructure.DAC_Trigger = DAC_Trigger_None; // 不使用硬件触发 DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; // 无波形生成 DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; // 关闭输出缓冲 DAC_Init(DAC_Channel_1, &DAC_InitStructure); DAC_Cmd(DAC_Channel_1, ENABLE); // 使能DAC通道

输出缓冲的取舍

  • 启用缓冲:提高驱动能力,但会引入约20mV的偏移
  • 禁用缓冲:输出阻抗较高,但精度更好

对于需要高精度的测量系统,建议禁用输出缓冲。

3. 核心功能实现

3.1 电压输出控制函数

设计一个可直接设置输出电压的函数,隐藏底层寄存器操作:

// 设置DAC输出电压 // vol: 目标电压值,单位mV,范围0-3300 void DAC_SetVoltage(uint16_t vol) { // 电压值转换为DAC数字量 uint16_t dacValue = (uint32_t)vol * 4095 / 3300; DAC_SetChannel1Data(DAC_Align_12b_R, dacValue); }

这个封装函数使得电压设置更加直观,开发者只需关心需要的电压值,而不必了解底层DAC寄存器的细节。

3.2 ADC采样与数据处理

ADC配置需要考虑采样时间和滤波算法:

// 初始化ADC ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); // ADC时钟配置 RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72MHz/6=12MHz ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);

为提高测量精度,实现了一个带平均滤波的ADC读取函数:

// 获取ADC采样平均值 uint16_t ADC_ReadAverage(uint8_t ch, uint8_t times) { uint32_t sum = 0; for(uint8_t i=0; i<times; i++) { sum += ADC_ReadSingle(ch); delay_ms(1); // 适当延时保证采样间隔 } return sum / times; }

4. 系统集成与性能优化

4.1 主控制逻辑实现

主循环中整合了按键扫描、DAC控制、ADC采样和数据显示功能:

while(1) { key = KEY_Scan(0); // 扫描按键 // 按键处理 if(key == KEY_UP) { voltage += 100; // 电压增加0.1V if(voltage > 3300) voltage = 3300; DAC_SetVoltage(voltage); } else if(key == KEY_DOWN) { voltage -= 100; // 电压减少0.1V if(voltage < 0) voltage = 0; DAC_SetVoltage(voltage); } // 定期采样和显示 if(timer_count >= 100) { // 约1秒间隔 uint16_t adcValue = ADC_ReadAverage(ADC_Channel_1, 10); float measuredVoltage = (float)adcValue * 3.3f / 4095; printf("设定电压: %.2fV, 测量电压: %.2fV\r\n", voltage/1000.0f, measuredVoltage); timer_count = 0; } delay_ms(10); timer_count++; }

4.2 精度优化技巧

通过实践发现几个提高系统精度的关键点:

  1. 电源稳定性:为AVDD和VDDA提供干净稳定的3.3V电源
  2. 参考电压:确保VREF+引脚有良好的去耦电容(100nF+10μF)
  3. PCB布局
    • 模拟信号走线远离数字信号
    • 使用地平面隔离敏感信号
  4. 软件校准
    • 在代码中实现零点校准和增益校准
    • 存储校准参数到Flash或EEPROM

典型误差来源分析

误差类型影响程度解决方法
量化误差±0.8mV软件平均滤波
参考电压波动±10mV使用精密基准源
PCB噪声±5mV优化布局布线

5. 进阶功能扩展

5.1 波形生成功能

基于现有框架,可以扩展DAC的波形生成能力:

// 生成正弦波 void DAC_GenerateSineWave(uint16_t freq) { static const uint16_t sineTable[] = {2048,2447,2831,3185,...}; // 预计算正弦表 static uint8_t index = 0; DAC_SetChannel1Data(DAC_Align_12b_R, sineTable[index]); index = (index + 1) % sizeof(sineTable); // 使用定时器控制频率 TIM_SetAutoreload(TIM2, SystemCoreClock / (freq * sizeof(sineTable))); }

5.2 上位机交互设计

通过串口协议实现更丰富的控制功能:

协议帧格式: [头字节][命令][数据长度][数据][校验和] 示例命令: 0x01 - 设置输出电压 0x02 - 读取当前电压 0x03 - 开始波形生成

在STM32端实现简单的协议解析:

void USART_ProcessCommand(uint8_t* buf) { switch(buf[1]) { // 命令字节 case 0x01: DAC_SetVoltage((buf[3]<<8)|buf[4]); break; case 0x02: USART_SendVoltage(); break; // 其他命令处理... } }

6. 调试技巧与常见问题

6.1 典型问题排查指南

问题1:DAC无输出或输出不正确

  • 检查PA4模式是否为GPIO_Mode_AIN
  • 确认DAC已使能(DAC_Cmd)
  • 测量VREF+电压是否正常

问题2:ADC读数不稳定

  • 增加采样次数使用平均滤波
  • 检查模拟电源是否干净
  • 适当增加采样时间(ADC_SampleTime)

问题3:串口数据显示异常

  • 确认波特率设置匹配
  • 检查串口初始化代码
  • 确保USART时钟已使能

6.2 性能测试方法

建立系统化的测试流程:

  1. 静态精度测试

    • 设置DAC输出从0到3.3V,步进0.1V
    • 记录ADC测量值和万用表实测值
    • 计算误差并绘制曲线
  2. 动态响应测试

    • 快速改变DAC输出
    • 测量ADC跟踪速度
    • 评估系统响应时间
  3. 长期稳定性测试

    • 固定输出某电压值
    • 连续监测8小时以上
    • 观察漂移情况

通过这个项目,您不仅掌握了DAC和ADC的基本用法,更重要的是理解了如何将多个外设有机结合,构建完整的嵌入式系统。在实际产品开发中,这种闭环控制思想随处可见,比如智能家居中的温控系统、工业设备中的伺服控制等。

http://www.gsyq.cn/news/1458174.html

相关文章:

  • 手把手教你用Postman调试天地图OGC服务(WMS/WFS/WMTS接口实战)
  • GPT-5不存在?当前最先进AI模型真相与GPT-4 Turbo实战指南
  • 移动创意工作流构建指南:从云端同步到专业工具链整合
  • 播客AI化不是升级,是重构:3类不可逆架构决策清单(附Gartner 2024成熟度评估矩阵)
  • 别再问师兄了!手把手教你从3GPP官网精准下载V2X协议(附TR 36.885实例)
  • 从硬盘磁铁到角度传感器:拆解日常设备中的永磁体磁场秘密
  • 用STM32F103RCT6和OLED屏,我DIY了一个能控制空调风扇的万能遥控器(附完整代码)
  • Stearic acid-PEG-Rhodamine 硬脂酸-聚乙二醇-罗丹明 SA-PEG-RB 科研应用
  • 大模型研发依赖系统性工程能力而非个体迁移
  • 3分钟学会GitHub精准下载:告别臃肿克隆,只取所需文件
  • DC NXT的SPG流程里,那些容易被忽略的“黑科技”:从adaptive retiming到TNS-Driven布局
  • 鸿蒙开发选Java还是JS?从手机到手表,一文讲清不同设备支持的语言和SDK配置
  • Qwen2.5-0.5B实战指南:轻量编程模型本地部署与调优
  • 从会议记录到智能客服:实战解析如何用Python和开源工具搞定说话人分离(Diarization)
  • OpenCore Legacy Patcher终极指南:4个步骤让旧Mac焕发新生的完整教程 [特殊字符]
  • Gemma系列开源小模型技术解析与边缘部署实战指南
  • 平衡小车PID调参实战:如何让你的STM32F103平衡车从‘摇头晃脑’到‘稳如老狗’
  • Verilog里signed和unsigned的坑,我踩了!手把手教你用$signed()函数避坑
  • 智慧职教刷课脚本:3分钟实现自动化学习的终极指南
  • 构建本地AI视频剪辑工作站:FunClip开源工具终极指南
  • AI辅助开发:让快马AI生成一个专业的网络数据包捕获与简易攻击检测分析工具
  • Mac/Win双平台实测:手把手带你搞定DevEco Studio 2.0.12.201安装与首次启动(附常见报错解决)
  • 基于Xilinx Artix-7的MATLAB建模+Verilog实现图像处理全流程工程包(含仿真、板级验证与毕设答辩资料)
  • 小米红米手机原生运行Gemma-4V多模态模型实战指南
  • Qwen3.5-27B推理蒸馏模型性能大揭秘:96.91% HumanEval通过率的背后
  • 破解Dify工作流复杂配置难题:基于Awesome-Dify-Workflow的高效解决方案
  • 用STM32F103的DAC做个简易信号发生器:从配置到波形输出(标准库版)
  • 完全免费!LX Music桌面版:5分钟掌握开源跨平台音乐播放器终极指南
  • gpt-4o生产稳定性解析:从API容错到接口契约的工程跃迁
  • 蓝桥杯单片机竞赛实战包:STC15开发板模块代码+十一届起真题工程源码