找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4470|回复: 11
打印 上一主题 下一主题
收起左侧

单片机大棚温湿度检测与控制程序+Proteus仿真 LCD1602显示

  [复制链接]
跳转到指定楼层
楼主
ID:528775 发表于 2021-11-17 20:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大棚温湿度,检测与控制LCD1602显示温度与湿度,温度大于设定值时开风扇,小于时开电辅热,使得气温保持一定限制,同时利用AD采集湿度,然后进行浇水。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:

  1. /*=============================================================*/
  2. #include <reg52.H>                //器件配置文件
  3. #include <intrins.h>
  4. #include "lcd.h"


  5. #define u8 unsigned char  
  6. #define u16 unsigned int
  7. #define uchar unsigned char
  8. #define uint unsigned int

  9.                //一般选用500K
  10. sbit DQ=P2^7; //ds18b20 与单片机连接口
  11.                          //将短接片去掉开启位选功能,否则默认IN0为输入引脚

  12. sbit motor=P1^0;//当湿度过低时。给高电平
  13. sbit ledgreen=P1^1;//当温度过高时,打开风扇
  14. sbit ledred=P1^2;   //温度低时,打开辅热
  15. unsigned char AD_DATA[2]; //保存IN0通道转换后的数据

  16. unsigned char disbuff[7] = { 0,0,0,0,};
  17. unsigned char Disp[]="0123456789";         //使用字符串保存数字0~9所对应的ASCLL码
  18. //unsigned char I_Disp[]="value: ";           //初始显示值
  19. unsigned char i,tflag;
  20. unsigned int a,voltage,circuit,electirc,aa,bb,cc,ab;
  21. unsigned char dd,ee,ff,gg;
  22. unsigned int tvalue,time,Level,High,t,ppm; // 温度值
  23.         uint dat=0,shidu;
  24. void delay_18b20(unsigned int i) // 延时 1 微秒
  25. {
  26.         while(i--);
  27. }
  28. void ds18b20rst() //ds18b20 初始化子函数
  29. {
  30.         unsigned charx=0;
  31.         DQ = 1; // 信号线 DQ复位
  32.         delay_18b20(4); // 延时
  33.         DQ = 0; //DQ 拉低
  34.         delay_18b20(100); // 精确延时大于 480us
  35.         DQ = 1; // 拉高
  36.         delay_18b20(40);
  37. }
  38. void ds18b20wr(unsigned char wdata) /* 写数据子函数 , 无返回值,含参数 */
  39. {
  40.         unsigned char i=0;
  41.         for (i=8; i>0; i--)// 要写完一个字节,故需要重复 8 次以下操作
  42.         {
  43.                 DQ = 0; // 数据线拉低
  44.                 DQ = wdata&0x01;// 按从低到高的顺序发送数据(一次发送一位 )
  45.                 delay_18b20(10);
  46.                 DQ = 1; // 最后将数据线拉高
  47.                 wdata>>=1; // 将 wdata 右移 1 位
  48.         }
  49. }
  50. unsigned char ds18b20rd() // 读数据子函数 , 是有返回值 dat
  51. {
  52.         unsigned char i=0;
  53.         unsigned char dat = 0;
  54.         for (i=8;i>0;i--)// 要读完一个字节,故需要重复 8 次以下操作
  55.         {
  56.                 DQ = 0; // 给脉冲信号
  57.                 dat>>=1;
  58.                 DQ = 1; // 给脉冲信号
  59.                 if(DQ)
  60.                         dat|=0x80;
  61.                         delay_18b20(10);
  62.         }
  63.         return(dat); // 返回 dat
  64. }
  65. read_temp() // 读取温度值并转换的子函数,有返回值温度值 tvalue
  66. {
  67.         unsigned char a,b;
  68.         ds18b20rst(); // 调用 ds18b20 初始化子函数
  69.         ds18b20wr(0xcc);// 调用写数据子函数,向 ds18b20 写命令 0xcc
  70.         //ccH 表示跳过 ROM读序列号,适用于单机工作,直接向 18b20 发送温度变换命令
  71.         ds18b20wr(0x44);// 调用写数据子函数,向 ds18b20 写命令 0x44
  72.         //44H 表示启动 ds18b20 温度转换 , 结果自行存入 9 字节的 RAM中
  73.         ds18b20rst(); // 调用 ds18b20 初始化子函数
  74.         ds18b20wr(0xcc);// 同上
  75.         ds18b20wr(0xbe);// 调用写数据子函数,向 ds18b20 写命令 0xbe
  76.         //beH 表示读取 RAM中 9 字节的温度数据
  77.         a=ds18b20rd(); // 调用读数据子函数,并将所得数据给 a
  78.         b=ds18b20rd(); //
  79.         tvalue=b; // 把 b 的值给 tvalue
  80.         tvalue<<=8; //tvalue 左移 8 位
  81.         tvalue=tvalue|a;//tvalue 与 a 进行按位或
  82.         if(tvalue<0x0fff)//
  83.         tflag=0; // 前五位为 0 时,读取的温度为正,标志位为 0,此时只要
  84.         else // 前五位为 1 时,读取的温度为负,标志位为 1,此时需要
  85.         {                 // 将测得数值取反后再加 1,再乘以 0.0625 即可得到实际温度
  86.         tvalue=~tvalue+1;
  87.         tflag=1; // 此时表示负温度
  88.         }
  89.         tvalue=tvalue*(0.625);// 温度值扩大 10 倍,精确到 1 位小数
  90.         return(tvalue); // 返回温度值


  91. }
  92. /***********************************
  93. 函数名:  AD()
  94. 功能:    启动AD转换将值储存于 AD_DATA[0]

  95. ***********************************/
  96. sbit ADCS         =P3^5;
  97. sbit ADCLK  =P3^2;
  98. sbit ADDI         =P3^3;
  99. sbit ADDO         =P3^4;
  100. unsigned int Adc0832(unsigned char channel)
  101. {
  102.         uchar i=0;
  103.         uchar j;

  104.         uchar ndat=0;
  105.         uchar  Vot=0;

  106.         if(channel==0)channel=2;
  107.         if(channel==1)channel=3;
  108.         ADDI=1;
  109.         _nop_();
  110.         _nop_();
  111.         ADCS=0;//拉低CS端
  112.         _nop_();
  113.         _nop_();
  114.         ADCLK=1;//拉高CLK端
  115.         _nop_();
  116.         _nop_();
  117.         ADCLK=0;//拉低CLK端,形成下降沿1
  118.         _nop_();
  119.         _nop_();
  120.         ADCLK=1;//拉高CLK端
  121.         ADDI=channel&0x1;
  122.         _nop_();
  123.         _nop_();
  124.         ADCLK=0;//拉低CLK端,形成下降沿2
  125.         _nop_();
  126.         _nop_();
  127.         ADCLK=1;//拉高CLK端
  128.         ADDI=(channel>>1)&0x1;
  129.         _nop_();
  130.         _nop_();
  131.         ADCLK=0;//拉低CLK端,形成下降沿3
  132.         ADDI=1;//控制命令结束
  133.         _nop_();
  134.         _nop_();
  135.         dat=0;
  136.         for(i=0;i<8;i++)
  137.         {
  138.                 dat|=ADDO;//收数据
  139.                 ADCLK=1;
  140.                 _nop_();
  141.                 _nop_();
  142.                 ADCLK=0;//形成一次时钟脉冲
  143.                 _nop_();
  144.                 _nop_();
  145.                 dat<<=1;
  146.                 if(i==7)dat|=ADDO;
  147.         }
  148.         for(i=0;i<8;i++)
  149.         {
  150.                 j=0;
  151.                 j=j|ADDO;//收数据
  152.                 ADCLK=1;
  153.                 _nop_();
  154.                 _nop_();
  155.                 ADCLK=0;//形成一次时钟脉冲
  156.                 _nop_();
  157.                 _nop_();
  158.                 j=j<<7;
  159.                 ndat=ndat|j;
  160.                 if(i<7)ndat>>=1;
  161.         }
  162.         ADCS=1;//拉低CS端
  163.         ADCLK=0;//拉低CLK端
  164.         ADDO=1;//拉高数据端,回到初始状态
  165.         dat<<=8;
  166.         dat|=ndat;

  167.         return(dat);            //return ad data
  168. }
  169. void Conut(void)
  170. {

  171.                  circuit=dat/256;
  172.        

  173.         ppm=circuit;
  174.         aa=ppm/1000;
  175.          bb=ppm%1000/100;
  176.         cc=ppm%100/10;
  177.          ab=ppm%10;
  178.        
  179.         dd=tvalue/1000; // 百位数
  180.         ee=tvalue%1000/100;// 十位数
  181.         ff=tvalue%100/10 ;// 个位数
  182.         gg=tvalue%10; // 小数位
  183.         if(ppm>150)   //湿度大于150/256=58.59后电机停转
  184.         {motor=0;}
  185.         if(ppm<=80) //小于31.25%电机开始启动
  186.         {motor=1;        }
  187.         if(tvalue>400)  //温度大于40度风扇开始启动
  188.         {ledgreen=1;ledred=0;}
  189.         if(tvalue<=400)  //温度小于40度风扇关闭
  190.         {ledgreen=0;ledred=1;}

  191. }


  192. /***********************************
  193. 函数名:  delayms()
  194. 功能:    延时 ms 毫秒

  195. ***********************************/
  196. void delayms(unsigned int ms)
  197. {
  198.         unsigned char j;
  199.         i=100;
  200.         for(;ms;ms--)
  201.         {
  202.                 while(--i)
  203.                 {
  204.                         j=10;
  205.                         while(--j);
  206.                 }
  207.         }
  208. }
  209. /***********************************
  210. 函数名:  LcdDisplay()
  211. 功能:    用lcd显示数组disbuff[]中的值

  212. ***********************************/


  213. void LcdDisplay(void)
  214. {
  215.   LCD1602_write_com(0x80+1+0x40);
  216.         LCD1602_write_word("c=");
  217.         LCD1602_write_com(0x80+3+0x40);          
  218.         LCD1602_write_data(0x30+aa);
  219.         LCD1602_write_com(0x80+4+0x40);
  220.         LCD1602_write_data(0x30+bb);
  221.   LCD1602_write_com(0x80+5+0x40);          
  222.         LCD1602_write_data(0x30+cc);               
  223.         LCD1602_write_com(0x80+6+0x40);          
  224.         LCD1602_write_data(0x30+ab);       
  225.         LCD1602_write_com(0x80+7+0x40);
  226.         LCD1602_write_word("humid");
  227.        
  228.         LCD1602_write_com(0x80+1);
  229.         LCD1602_write_word("tem=");
  230.         LCD1602_write_com(0x80+5);          
  231.         LCD1602_write_data(0x30+dd);
  232.         LCD1602_write_com(0x80+8);
  233.         LCD1602_write_word(".");
  234.   LCD1602_write_com(0x80+6);          
  235.         LCD1602_write_data(0x30+ee);               
  236.         LCD1602_write_com(0x80+7);          
  237.         LCD1602_write_data(0x30+ff);       
  238.         LCD1602_write_com(0x80+9);          
  239.         LCD1602_write_data(0x30+gg);       
  240.        
  241.        
  242. }
  243. /***********************************
  244. 函数名:  Analog_IO_Sel()
  245. 参数说明: m 的值对应ADC0809芯片上模拟输入的IO
  246. 功能:    确定模拟输入位选

  247. ***********************************/


  248. //void init()
  249. //{if(a==0)
  250. //{
  251. //          EA=1; //开总中断
  252. //    TMOD=0x02; //设定定时器 T0工作方式
  253. //    TH0=21; //利用T0中断产生CLK信号
  254. //    TL0=21;  
  255. ……………………

  256. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei附件下载:
大棚温湿度控制.rar (198.02 KB, 下载次数: 317)

评分

参与人数 1黑币 +20 收起 理由
admin + 20 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏14 分享淘帖 顶4 踩
回复

使用道具 举报

沙发
ID:968456 发表于 2021-11-19 21:04 | 只看该作者
大佬那个温度怎么改才能让他一下加减没那么多
回复

使用道具 举报

板凳
ID:982166 发表于 2021-11-25 23:02 | 只看该作者
用ADC0832可以检测湿度吗,不是应该用湿度传感器吗,有大佬可以说一下吗
回复

使用道具 举报

地板
ID:343102 发表于 2022-1-16 07:06 | 只看该作者
大棚内CO2 浓度也是一项重要指标,没有CO2,作物就不会生长。智能大棚必须要有CO2自动调节功能。
回复

使用道具 举报

5#
ID:1007655 发表于 2022-3-3 22:50 来自手机 | 只看该作者
w13325372056 发表于 2021-11-25 23:02
用ADC0832可以检测湿度吗,不是应该用湿度传感器吗,有大佬可以说一下吗

ADC0832是进行是A/D转换器,用来转换数据的
回复

使用道具 举报

6#
ID:456792 发表于 2022-3-4 10:55 | 只看该作者
w13325372056 发表于 2021-11-25 23:02
用ADC0832可以检测湿度吗,不是应该用湿度传感器吗,有大佬可以说一下吗

题主的设计中,没有湿度传感器。大多数的传感器的输出都是电信号,通过ADC0832模数转换和滑动变阻器来代替湿度传感器进行仿真。
回复

使用道具 举报

7#
ID:1008207 发表于 2022-3-4 22:19 来自手机 | 只看该作者
不明白湿度检测的原理
回复

使用道具 举报

8#
ID:297903 发表于 2022-3-5 08:34 | 只看该作者
很好用的,参考下,谢谢!!
回复

使用道具 举报

9#
ID:1003077 发表于 2022-3-5 10:10 | 只看该作者
单点检测?传感器布置在哪儿合适?
回复

使用道具 举报

10#
ID:1003077 发表于 2022-3-5 10:11 | 只看该作者
为什么不用个DHT11,或者SHT11什么的,一次吧温湿度都给解决了
回复

使用道具 举报

11#
ID:397211 发表于 2022-3-5 11:55 | 只看该作者
w13325372056 发表于 2021-11-25 23:02
用ADC0832可以检测湿度吗,不是应该用湿度传感器吗,有大佬可以说一下吗

可以的,配合模拟量的湿度传感器,0832是模数转换芯片。
回复

使用道具 举报

12#
ID:1019495 发表于 2022-6-14 08:59 | 只看该作者
请问,水泵、风扇、电辅热在硬件上应该怎么选择呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表