基于AT89C51的大棚温湿度控制系统设计与实现
2026/9/17 15:44:17 网站建设 项目流程

简介:基于AT89C51单片机的大棚温湿度控制系统设计文档,面向电子工程、农业自动化及单片机应用开发方向的师生和爱好者,解决传统大棚人工监测效率低、精度差的问题。文档围绕AT89C51与SHT11传感器展开,完整涵盖硬件电路设计、温湿度数据采集与处理、LCD实时显示、键盘扫描参数设置以及执行机构控制逻辑,并给出C语言程序框架与抗干扰设计思路。系统可实现温湿度自动监测与调节,用户可设定上下限阈值,适应不同作物生长需求。资源为单个docx文件,大小1.11MB,内容结构清晰,包含中英文摘要、系统背景、硬件与软件设计等完整章节,可直接用于课程设计、毕业设计或实际项目参考。目前已有213人学习,适合需要快速掌握单片机温湿度控制系统完整设计流程的读者。

1. 大棚温湿度控制系统设计,为什么还选AT89C51

接手这个题目,很多人第一反应是上基于STM32的环境温湿度监测控制系统。但真去算物料成本,AT89C51、5V电源、LCD1602加继电器模块就能把主控部分压在二十元以内,而STM32的BOM和调试器成本都会翻倍。大棚不是桌面实验室,供电波动大,执行器件是加热器、风扇和水泵这些大功率负载,AT89C51外设少,反而让干扰入口少。这个系统的核心不是高精度闭环,而是把温湿度采进来、显示出来,再按设定阈值驱动对应执行机构。只要采集边界和控制逻辑定清楚,这颗老内核完全能扛住。

2. 大棚温湿度控制系统的传感器选型与驱动电路设计

2.1 传感器怎么选:DHT11、DHT22还是DS18B20加HS1101

传感器选型直接决定采集数据的质量。常见的温湿度传感器方案有三条路线:DHT11、DHT22,以及DS18B20加HS1101湿度敏感电容。大棚环境温度范围一般在0到50℃之间,湿度长期偏高,目标成本越低越好。DHT11的测量精度为±2℃和±5%RH,分辨率1℃,采样周期1s,足够判断加热和加湿的开关点。DHT22精度更高,但价格是DHT11的三倍左右。DS18B20只管温度,湿度需要另配HS1101,通过555振荡电路或运放把电容变化转成频率或电压,电路复杂度明显上升。

方案接口测温范围精度(典型)成本适用场景
DHT11单总线0~50℃±2℃ / ±5%RH普通大棚、烘干房
DHT22单总线-40~80℃±0.5℃ / ±2%RH育苗棚、恒温房
DS18B20+HS1101单总线+模拟-55~125℃湿度需标定低温或强干扰环境

DHT11采用单总线协议,所有40位数据只靠一根线传输,位0和位1的时间宽度不同。读完一次要等1秒才能再读。下面这段读取单字节的代码是AT89C51上常见做法。

unsigned char read_byte_dht11(void) { unsigned char i, dat = 0; for (i = 0; i < 8; i++) { while (P3_3 == 0); /* 等数据线从低拉高,标记一位开始 */ delay_us(28); /* 延时28us后判断电平 */ if (P3_3 == 1) { dat |= (0x80 >> i); /* 数据位为1 */ while (P3_3 == 1); /* 等位结束,回到低电平 */ } } return dat; }

这个函数依赖精确的延时,要求晶振12MHz,delay_us用四个NOP指令组保证大约28us。DHT11的数据位0高电平维持26到28us,位1高电平维持约70us,如果在28us后读到的仍是高,就判定为1。如果while(P3_3==0)那里卡死,通常是起始信号拉低时间不够18ms,或者数据线没加上拉电阻。

2.2 继电器驱动与光耦隔离:别让感性负载毁掉AT89C51

AT89C51的IO口高电平驱动能力很弱,P1口输出高电平时的拉电流不到1mA,不能直接驱动继电器。常见的做法是用S8050三极管做开关,基极串联1kΩ电阻接到51的引脚,继电器线圈接在三极管集电极到5V之间。线圈两端必须反向并联1N4148二极管,否则继电器断电瞬间会产生几十伏反电动势,打穿IO口。

更进一步,在强电侧和单片机侧之间加PC817光耦,把220V的加热器、水泵与51系统完全隔开。选择继电器时注意线圈电压5V,触点容量要按负载电流的1.5倍选,加热器用10A继电器,风扇和水泵用5A。

负载继电器触点容量驱动管隔离器件
加热器(220V/500W)10AS8050或ULN2003PC817
排风扇5AS8050PC817
水泵5AS8050或ULN2003PC817

MCU电源和继电器电源不要共用同一条PCB走线,即使共用5V,也要在继电器供电入口放一个100uF电解电容和一个104瓷片电容,给吸合瞬间的电流尖峰一个泄放通道。

2.3 LCD/按键/IO分配:51的引脚资源怎么安排

显示部分用1602液晶最省事,数据口接到P0,三根控制线接P2.0到P2.2。AT89C51的P0是开漏输出,必须外接10kΩ排阻上拉。按键用三个:设置、加、减,分别接P1.4到P1.6。DHT11数据线接P3.3,继电器控制接P3.4到P3.6。这样剩下P1口还能接低电平有效的蜂鸣器报警。

引脚功能备注
P0.0~P0.7LCD1602 D0~D7需要10k上拉
P2.0~P2.2LCD RS、RW、EN
P1.4~P1.6设置键/加/减低电平有效
P3.3DHT11数据接4.7k上拉
P3.4加热器继电器低电平吸合
P3.5排风扇继电器低电平吸合
P3.6水泵继电器低电平吸合

复位电路用10uF电解电容加10kΩ电阻,晶振用12MHz,两个30pF负载电容。如果使用USB供电,要把复位上电时间拉长一点,否则上电瞬间51有时不进主程序。

3. AT89C51大棚温湿度控制系统的核心逻辑:状态机、滞回控制与软看门狗

3.1 主循环状态机

总体程序可以写成一个简单的状态机:系统上电后先初始化LCD、定时器、EEPROM和IO,然后循环执行采集、显示、控制、喂狗。下面给出主函数的骨架。

void main(void) { unsigned char temp, humi; init_lcd1602(); init_timer0_wdt(); read_threshold_from_eeprom(); while (1) { if (read_dht11(&temp, &humi) == 0) { refresh_lcd(temp, humi); control_temp(temp); control_humi(humi); alarm_check(temp, humi); } feed_soft_wdt(); delay_ms(500); } }

这里read_dht11成功返回0,失败返回1。如果传感器未响应就不刷新控制,避免在读到0xFF时直接把加热器关掉或打开。控制周期取500ms,和DHT11的采样速率匹配。不要在一个周期里连续多次读取,DHT11两次读之间必须间隔至少1秒。

3.2 滞回控制解决继电器频繁吸合

大棚控制系统最常见的故障是继电器在设定点附近频繁吸合。如果只做单阈值比较,温度在26度附近抖动,继电器会咔嗒响个不停,触点寿命很快耗尽。解决办法是在温度和湿度控制中加入滞回区间。

温度控制逻辑:当温度低于下限temp_low时打开加热,关闭排风扇;当温度高于上限temp_high时关闭加热,打开排风扇;在两个值之间时保持上次动作不变。这样实际控制的开启点在temp_low,关闭点在temp_high,中间形成滞回带。

sbit HEATER = P3^4; sbit FAN = P3^5; void control_temp(unsigned char t) { if (t <= temp_low) { HEATER = 0; /* 低电平驱动,表示吸合加热 */ FAN = 1; } else if (t >= temp_high) { HEATER = 1; FAN = 0; } /* 上下限之间保持现状,不改变输出 */ }

temp_low和temp_high是用户设定的温度下限和上限。这个函数用低电平驱动,因为继电器板大多做成低电平触发。如果使用高电平触发模块,要把赋值反过来。湿度采用相似结构,湿度过低时打开水泵或加湿器,湿度过高时打开排风扇,控制目标通常是相对湿度60%到70%。

如果大棚里同时有温度风机和湿度风机,建议不要直接共用一个排风扇,否则夏天降温又会把湿度带低。可以加一个手动模式,通过按键切换自动/手动,这样维护人员可以在设备异常时强制启停。

3.3 阈值掉电保存与软看门狗

设定的温湿度上下限必须掉电保存,常见做法是外接一颗AT24C02。AT24C02是I2C接口,AT89C51用软件模拟SCL和SDA即可,不需要硬件I2C。写入时先发设备地址0xA0,再写目标地址和两个字节数据。注意每次写入后要等待5ms,期间不能发下一个写命令。

看门狗方面,AT89C51原片内部没有硬件WDT,可以用定时器0模拟软看门狗。做法是让定时器0每100ms触发一次中断,中断里对计数变量加1,主循环每次执行完把计数清零。如果计数超过5,说明程序跑飞,直接跳回main起始处重新初始化。

volatile unsigned char wdt_cnt = 0; void timer0_isr(void) interrupt 1 { wdt_cnt++; if (wdt_cnt >= 5) { wdt_cnt = 0; main(); /* 软复位到主程序,需要先清TR0 */ } } void feed_soft_wdt(void) { wdt_cnt = 0; }

这种软看门狗只能处理死循环,不能处理低优先级中断被卡死的情况。更可靠的做法是把软看门狗和外部复位芯片配合,或者直接换AT89S51使用内置WDT。Keil C51里调用main()要小心,软复位前要把所有外设寄存器恢复到初值,简单起见用while(1)空转加外部复位芯片更省心。

4. 调试方法与典型坑:时序、电源、继电器和按键

4.1 DHT11时序不准导致读数卡死或报警

DHT11对延时函数非常敏感,用Keil优化等级过高时,delay_us会被优化掉,导致读取位一直为0或直接卡在while(P3_3==0)。先确认优化等级,再看晶振频率是否与实际一致。用12MHz晶振配合NOP延时是最容易复现的方案。

信号阶段低电平时间高电平时间判定要点
主机起始信号>18ms20~40us拉低后要释放总线
传感器响应80us80us先低后高
数据位050us26~28us高电平短
数据位150us70us高电平长

调试时可以用逻辑分析仪抓P3.3波形,数一下高电平宽度。位0的高电平宽度接近但不超过30us,位1的高电平宽度至少60us。另外读到的5字节数据应该是湿度整数部分、湿度小数部分、温度整数部分、温度小数部分、校验和。

给出一段用串口输出原始5字节的代码:

if (read_dht11_data(&buf[0]) == 0) { for (i = 0; i < 5; i++) { send_char(buf[i]); /* 用51串口把原始字节发到调试助手 */ } }

如果在串口助手看到固定的0xFF或者前两个字节一直为0,先查上拉电阻和接线,再查起始信号延时是否满足1秒间隔。DHT11采样周期是1秒,读得太快会返回上次数据甚至不响应。

4.2 继电器吸合导致MCU复位、LCD乱码

继电器吸合瞬间电流脉冲会通过共用电源线干扰51,常见现象是每次加热器启动,LCD就闪一下,严重时整个系统重启。先检查继电器线圈有没有续流二极管,这是第一道防线。第二道防线是给继电器驱动端单独走线,不要在单片机地线上形成回路。第三道防线是在继电器供电端加一个100uF电解电容和104瓷片电容的组合,电容尽量靠近继电器。

现象原因对策
MCU复位线圈反电动势未泄放并联1N4148或SS14
LCD乱码电源跌落继电器电源加大电容
IO口冒烟驱动电流过大改用ULN2003
控制偶尔失灵强电干扰PC817光耦隔离

如果加热器是大功率220V设备,触点通断瞬间会产生火花干扰,单片机复位引脚线要尽量短,复位电容可以加大到22uF,让复位门限更迟钝一点。晶振引脚附近放置两个20pF电容,必要时在晶振下方铺地。

4.3 按键消抖和EEPROM阈值写入失败

按键扫描不要直接读一次就认为有效,机械触点按下过程会有10到20ms的抖动。常见做法是检测到低电平后延时20ms再读一次,确认还是低电平才算按下。松手时同样要检测到高电平后延时20ms,避免一次按下被当作多次。

AT24C02写失败的原因大多是总线时序不对,或者WP引脚被拉高了。写入前要把WP接地。另一个坑是AT89C51重启速度比EEPROM快,掉电后重新上电立即读阈值,可能读到0xFF,所以写阈值时先写入两个起始标志字节,例如0xAA55,读取时先校验标志,不通过就用默认值。

if (read_eeprom(0x00) == 0xAA && read_eeprom(0x01) == 0x55) { temp_low = read_eeprom(0x02); temp_high = read_eeprom(0x03); humi_low = read_eeprom(0x04); humi_high = read_eeprom(0x05); }

读EEPROM时同样要模拟I2C的起始和停止条件,SCL高电平期间SDA跳变才是有效命令。这个细节容易被忽略,导致数据偏移一位。

5. 从Proteus仿真到实物移植,再谈要不要换成STM32

5.1 Proteus仿真快速验证控制逻辑

Proteus 8以上的版本自带AT89C51和DHT11仿真模型,可以先不焊板子把逻辑跑通。仿真时把晶振频率设成12MHz,DHT11模型要连一个上拉电阻到电源,否则数据线上没有高电平。另一个容易忽略的是,Proteus里的51默认没有加载程序,需要把Keil编译好的hex文件路径填进AT89C51属性页面,启动仿真后才能运行。仿真运行后添加LCD显示,也可以用虚拟终端看串口输出,方便确认传感器采集是否正常。

5.2 升级到STM32时要动哪些地方

如果后期大棚规模扩大,控制点增加到十几个,AT89C51的I/O资源和RAM开始吃紧。换成基于STM32的环境温湿度监测控制系统,保留LCD、继电器和DHT11外围电路,但要注意三点:第一,STM32的IO口是3.3V电平,继电器模块如果是5V触发,需要加电平转换或改选3.3V继电器;第二,DHT11时序在3.3V供电下可以工作,但代码里的延时函数要用SysTick,不能用51那种NOP方式;第三,P0上拉电阻不再需要,STM32的IO可以配置为开漏输出后使用内部上拉,但外部10k上拉仍然无害。

对比项AT89C51方案STM32方案
温度采集DHT11软件时序定时器输入捕获
控制任务单循环可拆分任务
掉电保存AT24C02软件I2CI2C外设/EEPROM
成本中高

STM32的优点是可以用一个定时器完成DHT11的输入捕获和校验,也可以用FreeRTOS把采集、控制、显示分开成任务。不过51内核还有一个硬件优势,就是IO翻转速度慢,误触发的概率低。对于大棚这个题目,初版直接用AT89C51把阈值控制跑通,后续再根据控制点数量决定是否迁移。

如果坚持用AT89C51做实物,一个值得保留的细节是:把三个继电器的公共端各自串联一只1A熔断器,成本增加几毛钱,但排查故障时能一眼看到哪个执行回路过流,比在程序里反复调阈值高效得多。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询