news 2026/4/25 11:30:17

基于STM32F103的土壤湿度传感器ADC采集与OLED显示实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于STM32F103的土壤湿度传感器ADC采集与OLED显示实战

1. 项目背景与硬件选型

最近在做一个智能农业的小项目,需要实时监测土壤湿度。经过对比多种方案,最终选择了STM32F103C8T6作为主控芯片,搭配常见的土壤湿度传感器和0.96寸OLED显示屏。这个组合性价比高,而且STM32的ADC性能完全能满足土壤湿度检测的需求。

STM32F103系列是意法半导体推出的经典Cortex-M3内核微控制器,价格亲民但性能不俗。我用的这款"蓝莓板"核心板在某宝上只要十几块钱,自带SWD调试接口,特别适合学生和爱好者使用。土壤湿度传感器就更便宜了,模拟量输出的版本不到5块钱,通过AO引脚输出0-3.3V的电压信号,湿度越大输出电压越低。

OLED我选了SSD1306驱动的I2C接口版本,分辨率128x64,显示效果清晰而且省电。这里有个小经验:市面上有些OLED模块的I2C地址可能是0x78而不是常见的0x7A,购买时最好跟卖家确认清楚。

2. 硬件连接与电路设计

2.1 接线示意图

先来看硬件连接,这是最容易出错的部分。我的接线方案是:

  • 土壤湿度传感器:VCC接3.3V,GND接地,AO接PA5(ADC1通道5)
  • OLED显示屏:SCL接PB6,SDA接PB7,VCC接3.3V,GND接地

这里有个关键点:STM32的ADC输入电压不能超过VDDA(通常是3.3V),而有些土壤湿度传感器的工作电压是5V。如果传感器输出可能超过3.3V,一定要在AO引脚加个分压电路,最简单的办法就是用两个电阻组成电压分压器。

2.2 电源设计建议

实际部署时我发现,如果直接用USB给开发板供电,当连接线较长时,电源噪声会影响ADC精度。后来我改用了锂电池供电,并在ADC参考电压引脚加了个0.1uF的滤波电容,效果明显改善。如果项目对精度要求高,建议使用独立的基准电压源芯片,比如TL431。

3. 软件实现详解

3.1 ADC初始化配置

ADC配置是核心部分,我把它封装成了独立的soilMoisture.c文件。初始化代码主要做这几件事:

void soilMoisture_Init(void){ // 1. 使能GPIO时钟和ADC时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE); // 2. 配置GPIO为模拟输入 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // 3. 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); // 4. 校准ADC ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); }

这里有几个经验分享:

  1. ADC时钟不要超过14MHz,我设置的是72MHz主频6分频得到12MHz
  2. 采样时间设置为239.5个周期,适合土壤湿度这种变化缓慢的信号
  3. 每次上电后必须执行校准,否则前几次读数可能不准

3.2 数据采集与滤波处理

土壤湿度信号容易受到干扰,我采用了平均值滤波算法。具体实现是这样的:

int soilMoisture_ReadData(int channel, int count){ int sum_val = 0; for(uint8_t i=0; i<count; i++){ sum_val += soilMoisture_ADC_GET(channel); Delay_ms(10); // 适当延时 } return sum_val/count; }

实测发现采样20次取平均效果最好。注意每次采样后要加个小延时,让ADC电路稳定。转换后的电压值计算公式是:

电压值 = ADC读数 × (3.3V / 4096)

因为STM32F103的ADC是12位的,最大值为4095。

4. OLED显示实现

4.1 显示驱动配置

我用的OLED驱动库是经过优化的,支持显示中文和浮点数。初始化部分很简单:

OLED_Init(); // 初始化I2C和OLED OLED_Clear(); // 清屏

4.2 湿度值实时显示

在主循环中,我每500ms更新一次显示:

while(1){ float moisture = (float)soilMoisture_ReadData(5,20)*(3.3/4096); OLED_ShowChinese(0,16, "土壤湿度:"); OLED_ShowFloatNum(75,16, moisture,2,2,OLED_8X16); OLED_Update(); Delay_ms(500); }

这里有几个实用技巧:

  1. 使用浮点数显示时,最后两个参数分别表示整数位和小数位长度
  2. OLED_Update()必须调用才会真正刷新显示
  3. 显示位置坐标单位是像素,第一个参数是列(0-127),第二个是行(0-7),每行8个像素

5. 实际应用中的优化建议

5.1 湿度标定方法

出厂时传感器需要标定才能得到准确的百分比湿度。我的做法是:

  1. 将传感器完全浸入水中,记录此时的ADC值作为100%湿度基准
  2. 将传感器放在完全干燥的土壤中,记录ADC值作为0%湿度
  3. 实际湿度 = (当前值 - 干燥值) / (湿润值 - 干燥值) × 100%

5.2 低功耗优化

如果用在电池供电的场景,可以这样优化:

  1. 将采样间隔从500ms改为10s
  2. 采样后立即进入STOP模式
  3. 用RTC定时唤醒
  4. 关闭不用的外设时钟

5.3 抗干扰措施

在工业环境中,建议:

  1. 在传感器信号线上加磁珠
  2. 使用屏蔽线连接传感器
  3. 在代码中加入软件滤波算法,比如中值滤波+滑动平均

6. 常见问题排查

调试时遇到过几个典型问题:

  1. ADC读数一直为0:检查GPIO是否配置为模拟输入模式,ADC时钟是否使能
  2. 数值跳动大:尝试增加采样次数,检查电源是否稳定
  3. OLED不显示:检查I2C地址是否正确,上拉电阻是否接好
  4. 湿度值反向变化:检查传感器接线,AO和DO不要接反

7. 项目扩展思路

这个基础框架可以扩展很多实用功能:

  1. 增加蓝牙模块,用手机查看实时数据
  2. 添加阈值报警功能,当湿度过低时触发继电器浇水
  3. 结合RTC芯片,实现湿度变化曲线记录
  4. 使用多个传感器,实现区域湿度监测

我在实际项目中加入了ESP8266 WiFi模块,将数据上传到云平台,这样就可以远程监控大棚的土壤状况。STM32F103的USART接口与ESP8266通信非常方便,只需要简单的AT指令就能实现网络连接。

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

异步编程模式回调承诺与异步等待

异步编程的进化之路&#xff1a;从回调到异步等待 在传统的同步编程中&#xff0c;代码按顺序执行&#xff0c;遇到耗时操作时会阻塞后续任务&#xff0c;导致性能瓶颈。为了解决这一问题&#xff0c;异步编程模式应运而生&#xff0c;它允许程序在等待耗时操作&#xff08;如…

作者头像 李华
网站建设 2026/4/25 11:28:58

CDecrypt:Wii U游戏解密的终极免费解决方案

CDecrypt&#xff1a;Wii U游戏解密的终极免费解决方案 【免费下载链接】cdecrypt Decrypt Wii U NUS content — Forked from: https://code.google.com/archive/p/cdecrypt/ 项目地址: https://gitcode.com/gh_mirrors/cd/cdecrypt 想探索Wii U游戏的神秘内部世界吗&a…

作者头像 李华
网站建设 2026/4/25 11:27:59

MusicFreePlugins:打破音乐平台壁垒的终极免费聚合方案

MusicFreePlugins&#xff1a;打破音乐平台壁垒的终极免费聚合方案 【免费下载链接】MusicFreePlugins MusicFree播放插件 项目地址: https://gitcode.com/gh_mirrors/mu/MusicFreePlugins 厌倦了在不同音乐应用间频繁切换&#xff1f;受够了VIP会员墙和地域版权限制&am…

作者头像 李华
网站建设 2026/4/25 11:27:53

Spring Boot集成Redisson:从YAML配置到自定义配置类的实战解析

1. 为什么选择Redisson与Spring Boot集成 第一次接触Redisson是在一个高并发的秒杀项目中&#xff0c;当时需要实现分布式锁来防止超卖问题。原本打算直接用Redis的SETNX命令&#xff0c;但发现要处理锁续期、可重入等复杂逻辑时&#xff0c;代码变得难以维护。直到发现了Redis…

作者头像 李华