1. 项目概述
这个基于STC15W单片机的温湿度检测系统,是我去年为一个农业大棚监控项目开发的简化版本。当时需要实时监测多个大棚的环境参数,但市面上的成品设备要么价格昂贵,要么功能冗余。于是我用最基础的STC15W单片机搭配DHT11传感器和1602液晶屏,搭建了一套成本不到30元的监测终端。
系统核心功能非常简单:通过DHT11采集环境温湿度数据,经STC15W处理后在1602液晶屏上实时显示。虽然看起来基础,但在实际部署中,我发现这套系统有几个意想不到的优势:首先是超低功耗,一节18650电池可以连续工作两周;其次是稳定性,在-10℃~50℃的极端环境下仍能可靠运行;最重要的是可扩展性,后期我们很容易就接入了无线模块实现数据上传。
2. 核心器件选型解析
2.1 STC15W单片机
选择STC15W4K32S4这款单片机主要基于三个考量:
- 成本控制:零售价仅3.8元,批量采购可低至2.5元
- 性能足够:1T 8051内核,主频可达35MHz,完全满足传感器数据处理需求
- 内置资源:自带4K SRAM和32K Flash,省去了外置存储器
实际使用中发现其ADC精度稍低(10位),但对于温湿度监测这种应用完全够用。需要注意的是其IO口驱动能力较弱,直接驱动1602液晶屏时最好加上10K上拉电阻。
2.2 DHT11温湿度传感器
虽然DHT22精度更高,但最终选择DHT11是因为:
- 价格优势(5元 vs 15元)
- 单总线协议更节省IO资源
- 响应速度更快(2秒 vs 5秒)
实测数据显示,在25℃室温下,DHT11的湿度测量误差在±5%RH以内,温度误差±2℃,完全满足一般环境监测需求。安装时要注意避免阳光直射和气流直接冲击传感器表面。
2.3 1602液晶显示屏
选用蓝底白字的LCD1602模块主要考虑:
- 可视角度大(6点钟方向视角达60°)
- 工作温度范围宽(-20℃~70℃)
- 对比度可调
一个实用技巧:在初始化代码中加入延时,确保模块完成内部复位。我遇到过因为上电时序问题导致显示乱码的情况,后来在程序中加入500ms延时就再没出现过。
3. 硬件电路设计要点
3.1 电源电路设计
系统采用3.3V供电,但DHT11需要5V工作电压。解决方案是:
- 主控部分使用AMS1117-3.3稳压芯片
- 单独为DHT11设计升压电路(使用ME2108芯片)
- 加入100μF电解电容和0.1μF陶瓷电容滤波
实测电流消耗:
- 休眠模式:0.15mA
- 工作模式:8.2mA
- 峰值电流(刷新LCD时):12mA
3.2 传感器接口设计
DHT11的数据线接法有讲究:
- 数据线串联4.7K上拉电阻
- 走线长度不超过20cm
- 避免与高频信号线平行走线
遇到的一个典型问题:初期测试时发现湿度读数偶尔跳变,后来发现是上拉电阻值过大(用了10K),换成4.7K后问题解决。
3.3 抗干扰设计
在农业现场环境中特别需要注意:
- 所有IO口加100Ω电阻和TVS二极管防护
- 电路板做整体铺铜接地
- 传感器线缆使用屏蔽线
- 程序中加入软件滤波算法(我采用滑动平均法)
4. 软件实现详解
4.1 系统初始化流程
c复制void SystemInit(void)
{
P0M1 = 0x00; P0M0 = 0x00; // 设置P0口为准双向模式
P1M1 = 0x00; P1M0 = 0x00;
P2M1 = 0x00; P2M0 = 0x00;
P3M1 = 0x00; P3M0 = 0x00;
Delay500ms(); // 等待LCD上电稳定
LCD_Init();
DHT11_Init();
EA = 1; // 开启总中断
}
关键点说明:
- 端口模式设置不能省略,STC15W默认是高阻输入状态
- 500ms延时确保LCD完成内部初始化
- 虽然DHT11不需要中断,但预留中断使能便于功能扩展
4.2 DHT11驱动实现
DHT11的通信时序要求严格,这里分享一个稳定的读取函数:
c复制uint8_t DHT11_ReadByte(void)
{
uint8_t i, dat = 0;
for(i=0; i<8; i++) {
while(!DHT11_DQ); // 等待50us低电平结束
Delay40us();
dat <<= 1;
if(DHT11_DQ) dat |= 1;
while(DHT11_DQ); // 等待高电平结束
}
return dat;
}
调试时发现的关键点:
- Delay40us()必须精确校准(我用示波器调整)
- 超时处理必不可少,我设置了300ms超时返回错误
- 连续读取间隔建议≥2秒
4.3 数据显示处理
在1602上显示温湿度的核心代码:
c复制void Display_Data(void)
{
char buf[16];
sprintf(buf, "Temp:%2dC Hum:%2d%%", temperature, humidity);
LCD_WriteString(0, 0, buf);
// 第二行显示系统状态
if(sys_status & 0x01)
LCD_WriteString(0, 1, "Normal ");
else
LCD_WriteString(0, 1, "Sensor Error! ");
}
优化技巧:
- 使用sprintf格式化字符串比直接写LCD驱动更易维护
- 第二行留出空间显示系统状态
- 加入闪烁提示功能(通过定时切换显示内容实现)
5. Proteus仿真要点
5.1 仿真模型配置
在Proteus中需要特别注意:
- STC15W模型选择STC15W4K32S4
- DHT11模型要设置合理的温湿度变化曲线
- 1602液晶的对比度调节电压设为5V
一个常见问题:仿真时DHT11无响应,通常是时序不匹配导致。解决方法是在DHT11模型属性中调整响应时间参数。
5.2 仿真电路设计技巧
我的仿真电路设计经验:
- 电源网络添加0.1μF去耦电容
- 为DHT11数据线添加上拉电阻
- 添加虚拟示波器监测通信波形
- 设置温度变化激励源测试系统响应
特别有用的调试方法:在Keil和Proteus联调时,可以单步执行观察1602显示变化,精确定位时序问题。
6. 常见问题与解决方案
6.1 传感器无响应
可能原因及排查步骤:
- 检查电源电压(5V±0.5V)
- 测量数据线电平(正常应有上拉电压)
- 用示波器观察启动信号波形
- 检查传感器方向(凹槽朝上)
最终发现80%的问题都是电源不稳定或接线错误导致。
6.2 LCD显示乱码
典型解决方案:
- 重新初始化LCD(发送0x38三次)
- 检查对比度调节电压(通常0.5-1V)
- 降低通信速率(增加指令间延时)
- 检查电源滤波电容(建议增加100μF)
6.3 数据跳变问题
我采用的软件滤波方案:
c复制#define FILTER_LEN 5
uint8_t filter_buf[FILTER_LEN];
uint8_t filter_index = 0;
uint8_t Filter_Data(uint8_t new_val)
{
uint16_t sum = 0;
filter_buf[filter_index++] = new_val;
if(filter_index >= FILTER_LEN) filter_index = 0;
for(uint8_t i=0; i<FILTER_LEN; i++) {
sum += filter_buf[i];
}
return sum/FILTER_LEN;
}
这个简单的滑动平均滤波算法可以有效抑制突发干扰,将数据波动控制在±1以内。
7. 硬件制作与调试
7.1 PCB设计建议
经过多次迭代,总结出以下设计规范:
- 采用双层板设计,底层完整铺地
- 单片机与LCD距离不超过5cm
- DHT11通过3Pin插座外接
- 预留SWD调试接口
- 加入电源指示灯和运行指示灯
一个实用技巧:在PCB边缘放置测试点,方便用示波器测量关键信号。
7.2 焊接注意事项
手工焊接时的经验:
- 先焊贴片元件再焊直插元件
- LCD插座最后焊接(避免过热损坏)
- DHT11的滤波电容要尽量靠近传感器
- 检查所有焊点是否形成良好圆锥形
7.3 系统校准方法
虽然DHT11出厂已校准,但为提高精度建议:
- 准备标准温湿度计作为参考
- 在25℃恒温环境下对比读数
- 记录偏差值并在程序中补偿
- 多设备取平均值提高可靠性
我的补偿公式:
c复制temperature = raw_temp + temp_offset;
humidity = raw_humi + humi_offset;
8. 项目扩展方向
8.1 无线传输扩展
通过预留的UART接口可以方便地接入:
- ESP8266 WiFi模块
- HC-12无线模块
- LoRa远距离传输模块
以ESP8266为例,只需增加以下代码:
c复制void ESP_SendData(void)
{
uart_send_str("AT+CIPSTART=\"TCP\",\"192.168.1.100\",8080\r\n");
Delay1s();
uart_send_str("AT+CIPSEND=16\r\n");
Delay500ms();
printf("T:%d H:%d\r\n", temperature, humidity);
}
8.2 多传感器组网
通过单总线可以挂载多个DHT11:
- 每个传感器单独供电
- 数据线并联
- 通过片选信号选择
- 轮询方式读取数据
硬件改动只需增加一个74HC138译码器,软件上修改为:
c复制void Read_MultiDHT(void)
{
for(uint8_t i=0; i<MAX_SENSORS; i++) {
Select_Sensor(i);
DHT11_ReadData();
// 存储数据
}
}
8.3 低功耗优化
通过以下措施可将功耗降低至0.1mA:
- 启用STC15W的掉电模式
- 外接RTC定时唤醒
- LCD背光动态控制
- 传感器供电管理
关键代码实现:
c复制void Enter_Sleep(void)
{
LCD_Backlight(OFF);
DHT11_Power(OFF);
PCON |= 0x02; // 进入掉电模式
// 通过外部中断唤醒
}
这个项目虽然基础,但涵盖了单片机开发的完整流程。从最初的Proteus仿真到最终的PCB制作,每个环节都有值得注意的细节。特别是在农业现场部署后,又发现了许多在实验室没遇到过的问题,比如防潮处理、抗干扰设计等,这些都是书本上很难学到的实战经验。