news 2026/4/19 21:32:58

别再只会用万用表了!用STM32的ADC做个简易电压表(附OLED显示代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再只会用万用表了!用STM32的ADC做个简易电压表(附OLED显示代码)

用STM32打造高精度数字电压表:从ADC原理到OLED显示实战

在电子制作和嵌入式开发中,测量电压是最基础却又最频繁的需求之一。虽然万用表是工程师工具箱里的标配,但当我们希望将电压测量功能集成到自己的项目中时,基于STM32的ADC(模数转换器)方案就显示出独特优势。本文将带你从零开始,利用STM32F103C8T6开发板和0.96寸OLED屏幕,构建一个具有专业显示效果的数字电压表。这个项目不仅能让你的开发板变身实用测量工具,更能深入理解ADC的采样精度、参考电压校准等关键概念。

1. 硬件准备与电路设计

1.1 元器件选型指南

制作电压表的核心器件包括:

  • 主控芯片:STM32F103C8T6(Blue Pill开发板),内置12位精度ADC
  • 显示模块:SSD1306驱动的0.96寸OLED,128x64分辨率
  • 电压分压电路:1%精度的金属膜电阻(10kΩ和3.3kΩ组成分压网络)
  • 参考电压源:TL431精密电压基准(可选,用于提高测量精度)

对于测量范围扩展,建议采用以下电阻配置:

测量范围R1值R2值分压比
0-3.3V直接连接1:1
0-10V10kΩ3.3kΩ约1:4
// 电压分压计算函数示例 float calculate_voltage(uint16_t adc_value, float vref, float divider_ratio) { return (adc_value * vref / 4095.0f) * divider_ratio; }

1.2 硬件连接示意图

正确连接是项目成功的基础,请按以下方式接线:

  1. ADC输入:将待测电压接入PA0(ADC1_IN0)
  2. OLED接口
    • SCL → PB6(I2C1_SCL)
    • SDA → PB7(I2C1_SDA)
  3. 电源部分:确保开发板3.3V稳压输出稳定

注意:测量超过3.3V的电压时,必须使用分压电路,否则可能损坏ADC引脚!

2. ADC模块深度配置

2.1 关键参数优化设置

STM32的ADC性能很大程度上取决于几个核心参数的配置:

ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure);

采样时间对测量结果有显著影响,不同时钟周期下的噪声表现:

采样周期转换时间适用场景
1.5周期1.17μs高速但精度低
7.5周期2.25μs平衡模式
55.5周期5.43μs高精度测量

2.2 校准与参考电压处理

出厂校准是提升精度的关键步骤:

ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1));

对于需要更高精度的场合,可以外接基准电压源到VREF+引脚。实测发现,使用TL431作为2.5V基准时,温度漂移可降低至±50ppm/℃。

3. 软件架构与核心算法

3.1 多阶滤波算法实现

原始ADC数据往往带有噪声,采用复合滤波策略效果更佳:

  1. 硬件层面:在ADC输入端添加0.1μF去耦电容
  2. 软件层面:实现移动平均+中值滤波
#define FILTER_WINDOW 16 uint16_t adc_filter(uint16_t new_value) { static uint16_t buffer[FILTER_WINDOW]; static uint8_t index = 0; static uint32_t sum = 0; sum -= buffer[index]; buffer[index] = new_value; sum += new_value; index = (index + 1) % FILTER_WINDOW; return sum / FILTER_WINDOW; }

3.2 电压转换与显示优化

将ADC原始值转换为实际电压时,需要注意浮点运算效率:

void update_display(uint16_t raw) { static char buf[8]; float voltage = raw * 3.3f / 4095.0f; // 使用定点数运算优化性能 uint16_t integer = (uint16_t)voltage; uint16_t decimal = (uint16_t)((voltage - integer) * 100); OLED_ShowNum(2, 8, integer, 1); OLED_ShowNum(2, 10, decimal, 2); }

4. 高级功能扩展

4.1 多量程自动切换

通过继电器或模拟开关实现量程自动切换:

void auto_range_switch(float voltage) { if(voltage > 3.3f && current_range == RANGE_LOW) { set_high_range(); // 切换到高压量程 HAL_Delay(100); // 等待电路稳定 } else if(voltage < 3.0f && current_range == RANGE_HIGH) { set_low_range(); // 切回低压量程 } }

4.2 数据记录与导出

添加SD卡模块实现测量数据存储:

void log_measurement(float voltage) { static FIL file; static char line[32]; sprintf(line, "%.3f\n", voltage); f_write(&file, line, strlen(line), NULL); }

5. 性能优化与故障排查

5.1 常见问题解决方案

  • 读数跳变严重

    • 检查电源稳定性
    • 增加采样周期
    • 优化滤波算法参数
  • 测量值偏置

    • 重新校准ADC
    • 检查分压电阻精度
    • 测量实际VREF电压

5.2 低功耗设计技巧

当需要电池供电时:

void enter_low_power_mode() { ADC_SoftwareStartConvCmd(ADC1, DISABLE); HAL_ADC_Stop(&hadc1); __HAL_ADC_DISABLE(&hadc1); HAL_I2C_DeInit(&hi2c1); }

在最近的一个智能电池监测项目中,这种电压测量方案成功将静态功耗控制在150μA以下,使设备续航时间延长至6个月。

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

XCOM 2模组管理器终极指南:AML启动器从入门到精通

XCOM 2模组管理器终极指南&#xff1a;AML启动器从入门到精通 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xc…

作者头像 李华
网站建设 2026/4/18 22:51:02

算法题:合并排序数组

目录 一、最优思路:从后往前双指针 二、代码实现 三、过程演示 第1次 第2次 第3次 第4次 四、为什么只需要处理 nums2 剩余部分 1. nums2 先用完 2. nums1 先用完 五、时间复杂度 六、面试回答模板 七、完整示例 八、如果允许额外空间,简单写法 九、一句话总结…

作者头像 李华
网站建设 2026/4/18 19:21:24

2025届最火的五大降AI率助手解析与推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 知网 AI 检测系统开展识别工作所依据的是文本复杂度、语义连贯性以及句式规律。要是想让检测…

作者头像 李华
网站建设 2026/4/18 7:37:13

深入解析Linux TUN/TAP设备:从原理到实战应用

1. Linux TUN/TAP设备基础概念 第一次接触TUN/TAP设备时&#xff0c;我盯着ifconfig里突然出现的tun0接口发了半天呆——这玩意儿既没有MAC地址也不连着网线&#xff0c;凭什么能收发网络数据&#xff1f;后来才发现&#xff0c;这正是虚拟网络设备的精妙之处。简单来说&#x…

作者头像 李华
网站建设 2026/4/18 14:56:07

Linux下通过npm快速安装wscat的完整指南

1. 为什么你需要wscat工具&#xff1f; 如果你经常和WebSocket打交道&#xff0c;wscat绝对是你工具箱里不可或缺的小助手。这个轻量级命令行工具就像WebSocket界的"瑞士军刀"&#xff0c;能快速测试连接、发送消息和调试协议。想象一下&#xff0c;你正在开发一个实…

作者头像 李华
网站建设 2026/4/18 20:01:23

痞子衡嵌入式:MCUXpresso Config Tools实战指南(从零配置到一键生成)

1. 初识MCUXpresso Config Tools&#xff1a;嵌入式开发的效率神器 第一次接触RT1170这种高端MCU时&#xff0c;我盯着密密麻麻的引脚定义图和复杂的时钟树结构图发了半小时呆。作为从STM32转战NXP平台的开发者&#xff0c;这种冲击感就像从手动挡汽车突然跳进了航天飞机驾驶舱…

作者头像 李华