1. 项目概述与硬件选型
最近在做一个基于STM32的室内环境监测小项目,核心功能是通过AHT20温湿度传感器采集数据,并在0.96寸OLED屏幕上实时显示。这个方案特别适合需要低成本、低功耗的环境监测场景,比如智能家居、温室大棚或者实验室设备监控。
硬件方面我选择了STM32F103C8T6最小系统板作为主控,这款芯片性价比极高,72MHz主频完全够用。传感器选用的是AHT20,相比传统的DHT11/DHT22,它的精度更高(温度±0.3℃,湿度±2%RH),而且采用I2C接口,接线更简单。显示部分使用SSD1306驱动的0.96寸OLED,128x64分辨率足够显示温湿度信息,而且功耗极低。
注意:AHT20的工作电压是1.8-3.6V,如果使用5V供电的STM32开发板,需要加电平转换电路或者选择3.3V供电的型号
2. 开发环境配置
2.1 STM32CubeMX基础配置
首先用STM32CubeMX新建工程,选择对应的STM32型号。关键配置步骤如下:
-
调试接口配置:在SYS选项卡下选择Debug为Serial Wire。这个设置非常重要,如果不开启,可能会遇到只能下载一次程序的问题,因为默认的JTAG接口会占用部分GPIO引脚。
-
时钟配置:
- 在RCC选项卡将HSE(高速外部时钟)设为Crystal/Ceramic Resonator
- 进入Clock Configuration将系统主频设置为72MHz(先设置PLL源为HSE,然后调整PLL倍频系数)
-
I2C配置:
- 启用I2C1(根据你的实际接线选择)
- 模式选择I2C
- 速度选择Fast Mode(400kHz),这个速度完全满足AHT20的需求
-
项目生成设置:
- 在Project Manager的Code Generator选项卡
- 勾选"Generate peripheral initialization as a pair of .c/.h files"
- 这样每个外设都会有独立的源文件和头文件,方便管理
2.2 驱动文件准备
需要准备两个设备的驱动文件:
-
OLED驱动:
- 包含oled.c/oled.h和font.c/font.h
- 提供屏幕初始化、清屏、显示字符/数字等基础功能
-
AHT20驱动:
- 包含aht20.c/aht20.h
- 提供传感器初始化、温湿度读取等功能
这些文件需要复制到项目的Src和Inc目录下。建议先在取模软件中生成需要的文字和图片的字模数据,保存到font.c中,并在font.h中添加extern声明。
3. 硬件连接与测试
3.1 接线示意图
code复制AHT20 STM32 OLED
VCC ---- 3.3V ---- VCC
GND ---- GND ---- GND
SCL ---- PB6 ---- SCL
SDA ---- PB7 ---- SDA
重要提示:I2C总线上需要接上拉电阻,通常4.7kΩ即可。有些模块已经内置了上拉电阻,如果通信不稳定可以检查这个问题
3.2 初始化代码
在main.c中添加必要的初始化和变量定义:
c复制#include "oled.h"
#include "aht20.h"
float temperature = 0;
float humidity = 0;
int main(void) {
HAL_Init();
SystemClock_Config();
OLED_Init();
AHT20_Init();
OLED_ShowString(0, 0, "Initializing...");
OLED_ShowFrame();
HAL_Delay(1000);
while(1) {
// 温湿度采集和显示代码
}
}
4. 核心功能实现
4.1 温湿度采集逻辑
AHT20的测量需要遵循特定的时序:
- 发送测量命令(0xAC)
- 等待测量完成(检查状态位)
- 读取6字节的测量数据
- 将原始数据转换为实际温湿度值
在while循环中添加以下代码:
c复制AHT20_StartMeasurement();
while(AHT20_IsBusy()) {
HAL_Delay(10);
}
AHT20_ReadData();
temperature = AHT20_GetTemperature();
humidity = AHT20_GetHumidity();
4.2 OLED显示优化
为了提高显示效果,我做了以下优化:
- 双缓冲机制:先操作显存,最后统一刷新,避免闪烁
- 数据格式化:将浮点数转换为固定位数显示
- 界面布局:合理分配显示区域
实现代码示例:
c复制OLED_NewFrame();
// 显示标题
OLED_ShowString(10, 0, "Env Monitor");
// 显示温度
OLED_ShowString(0, 2, "Temp:");
char tempStr[10];
sprintf(tempStr, "%.1f C", temperature);
OLED_ShowString(40, 2, tempStr);
// 显示湿度
OLED_ShowString(0, 4, "Humi:");
char humiStr[10];
sprintf(humiStr, "%.1f %%", humidity);
OLED_ShowString(40, 4, humiStr);
// 添加简单图形
OLED_DrawLine(0, 16, 127, 16);
OLED_ShowFrame();
5. 常见问题与解决方案
5.1 I2C通信失败
现象:OLED或AHT20无响应
排查步骤:
- 检查接线是否正确,特别是电源和地线
- 用逻辑分析仪或示波器检查I2C波形
- 确认上拉电阻是否合适(通常4.7kΩ)
- 检查设备地址是否正确(AHT20地址是0x38)
5.2 数据显示异常
现象:温湿度值明显错误
解决方案:
- 检查AHT20的初始化是否成功
- 确保测量前有足够的延迟(AHT20需要约75ms完成测量)
- 检查数据转换公式是否正确
5.3 OLED显示乱码
现象:显示内容不正确
解决方法:
- 确认字库文件是否正确加载
- 检查显示坐标是否超出范围
- 确保在修改显存后调用了刷新函数
6. 性能优化与扩展
6.1 低功耗优化
如果需要电池供电,可以考虑以下优化:
- 降低主频(通过修改时钟配置)
- 使用HAL_Delay()替代忙等待
- 间歇性采集(如每10秒采集一次)
6.2 功能扩展
这个项目可以轻松扩展更多功能:
- 添加RTC模块实现数据记录
- 通过WiFi/蓝牙模块上传数据
- 增加按键设置报警阈值
- 添加蜂鸣器实现超限报警
6.3 实际应用中的经验
在几个实际项目中应用这个方案后,我总结了以下经验:
- AHT20需要约2秒的稳定时间,上电后不要立即读取
- OLED在低温环境下可能出现显示延迟,建议工作温度在-20℃以上
- I2C总线长度不宜过长,建议控制在30cm以内
- 如果使用杜邦线连接,最好用热熔胶固定接头,避免接触不良
这个温湿度监测系统虽然简单,但涵盖了嵌入式开发的多个关键环节:外设驱动、传感器通信、数据显示等。通过这个项目,可以掌握STM32的基础开发流程,为更复杂的嵌入式应用打下基础。