大棚温湿度,检测与控制LCD1602显示温度与湿度,温度大于设定值时开风扇,小于时开电辅热,使得气温保持一定限制,同时利用AD采集湿度,然后进行浇水。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- /*=============================================================*/
- #include <reg52.H> //器件配置文件
- #include <intrins.h>
- #include "lcd.h"
- #define u8 unsigned char
- #define u16 unsigned int
- #define uchar unsigned char
- #define uint unsigned int
- //一般选用500K
- sbit DQ=P2^7; //ds18b20 与单片机连接口
- //将短接片去掉开启位选功能,否则默认IN0为输入引脚
- sbit motor=P1^0;//当湿度过低时。给高电平
- sbit ledgreen=P1^1;//当温度过高时,打开风扇
- sbit ledred=P1^2; //温度低时,打开辅热
- unsigned char AD_DATA[2]; //保存IN0通道转换后的数据
- unsigned char disbuff[7] = { 0,0,0,0,};
- unsigned char Disp[]="0123456789"; //使用字符串保存数字0~9所对应的ASCLL码
- //unsigned char I_Disp[]="value: "; //初始显示值
- unsigned char i,tflag;
- unsigned int a,voltage,circuit,electirc,aa,bb,cc,ab;
- unsigned char dd,ee,ff,gg;
- unsigned int tvalue,time,Level,High,t,ppm; // 温度值
- uint dat=0,shidu;
- void delay_18b20(unsigned int i) // 延时 1 微秒
- {
- while(i--);
- }
- void ds18b20rst() //ds18b20 初始化子函数
- {
- unsigned charx=0;
- DQ = 1; // 信号线 DQ复位
- delay_18b20(4); // 延时
- DQ = 0; //DQ 拉低
- delay_18b20(100); // 精确延时大于 480us
- DQ = 1; // 拉高
- delay_18b20(40);
- }
- void ds18b20wr(unsigned char wdata) /* 写数据子函数 , 无返回值,含参数 */
- {
- unsigned char i=0;
- for (i=8; i>0; i--)// 要写完一个字节,故需要重复 8 次以下操作
- {
- DQ = 0; // 数据线拉低
- DQ = wdata&0x01;// 按从低到高的顺序发送数据(一次发送一位 )
- delay_18b20(10);
- DQ = 1; // 最后将数据线拉高
- wdata>>=1; // 将 wdata 右移 1 位
- }
- }
- unsigned char ds18b20rd() // 读数据子函数 , 是有返回值 dat
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)// 要读完一个字节,故需要重复 8 次以下操作
- {
- DQ = 0; // 给脉冲信号
- dat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- dat|=0x80;
- delay_18b20(10);
- }
- return(dat); // 返回 dat
- }
- read_temp() // 读取温度值并转换的子函数,有返回值温度值 tvalue
- {
- unsigned char a,b;
- ds18b20rst(); // 调用 ds18b20 初始化子函数
- ds18b20wr(0xcc);// 调用写数据子函数,向 ds18b20 写命令 0xcc
- //ccH 表示跳过 ROM读序列号,适用于单机工作,直接向 18b20 发送温度变换命令
- ds18b20wr(0x44);// 调用写数据子函数,向 ds18b20 写命令 0x44
- //44H 表示启动 ds18b20 温度转换 , 结果自行存入 9 字节的 RAM中
- ds18b20rst(); // 调用 ds18b20 初始化子函数
- ds18b20wr(0xcc);// 同上
- ds18b20wr(0xbe);// 调用写数据子函数,向 ds18b20 写命令 0xbe
- //beH 表示读取 RAM中 9 字节的温度数据
- a=ds18b20rd(); // 调用读数据子函数,并将所得数据给 a
- b=ds18b20rd(); //
- tvalue=b; // 把 b 的值给 tvalue
- tvalue<<=8; //tvalue 左移 8 位
- tvalue=tvalue|a;//tvalue 与 a 进行按位或
- if(tvalue<0x0fff)//
- tflag=0; // 前五位为 0 时,读取的温度为正,标志位为 0,此时只要
- else // 前五位为 1 时,读取的温度为负,标志位为 1,此时需要
- { // 将测得数值取反后再加 1,再乘以 0.0625 即可得到实际温度
- tvalue=~tvalue+1;
- tflag=1; // 此时表示负温度
- }
- tvalue=tvalue*(0.625);// 温度值扩大 10 倍,精确到 1 位小数
- return(tvalue); // 返回温度值
- }
- /***********************************
- 函数名: AD()
- 功能: 启动AD转换将值储存于 AD_DATA[0]
- ***********************************/
- sbit ADCS =P3^5;
- sbit ADCLK =P3^2;
- sbit ADDI =P3^3;
- sbit ADDO =P3^4;
- unsigned int Adc0832(unsigned char channel)
- {
- uchar i=0;
- uchar j;
- uchar ndat=0;
- uchar Vot=0;
- if(channel==0)channel=2;
- if(channel==1)channel=3;
- ADDI=1;
- _nop_();
- _nop_();
- ADCS=0;//拉低CS端
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿1
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- ADDI=channel&0x1;
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿2
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- ADDI=(channel>>1)&0x1;
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿3
- ADDI=1;//控制命令结束
- _nop_();
- _nop_();
- dat=0;
- for(i=0;i<8;i++)
- {
- dat|=ADDO;//收数据
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次时钟脉冲
- _nop_();
- _nop_();
- dat<<=1;
- if(i==7)dat|=ADDO;
- }
- for(i=0;i<8;i++)
- {
- j=0;
- j=j|ADDO;//收数据
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次时钟脉冲
- _nop_();
- _nop_();
- j=j<<7;
- ndat=ndat|j;
- if(i<7)ndat>>=1;
- }
- ADCS=1;//拉低CS端
- ADCLK=0;//拉低CLK端
- ADDO=1;//拉高数据端,回到初始状态
- dat<<=8;
- dat|=ndat;
- return(dat); //return ad data
- }
- void Conut(void)
- {
- circuit=dat/256;
-
- ppm=circuit;
- aa=ppm/1000;
- bb=ppm%1000/100;
- cc=ppm%100/10;
- ab=ppm%10;
-
- dd=tvalue/1000; // 百位数
- ee=tvalue%1000/100;// 十位数
- ff=tvalue%100/10 ;// 个位数
- gg=tvalue%10; // 小数位
- if(ppm>150) //湿度大于150/256=58.59后电机停转
- {motor=0;}
- if(ppm<=80) //小于31.25%电机开始启动
- {motor=1; }
- if(tvalue>400) //温度大于40度风扇开始启动
- {ledgreen=1;ledred=0;}
- if(tvalue<=400) //温度小于40度风扇关闭
- {ledgreen=0;ledred=1;}
- }
- /***********************************
- 函数名: delayms()
- 功能: 延时 ms 毫秒
- ***********************************/
- void delayms(unsigned int ms)
- {
- unsigned char j;
- i=100;
- for(;ms;ms--)
- {
- while(--i)
- {
- j=10;
- while(--j);
- }
- }
- }
- /***********************************
- 函数名: LcdDisplay()
- 功能: 用lcd显示数组disbuff[]中的值
- ***********************************/
- void LcdDisplay(void)
- {
- LCD1602_write_com(0x80+1+0x40);
- LCD1602_write_word("c=");
- LCD1602_write_com(0x80+3+0x40);
- LCD1602_write_data(0x30+aa);
- LCD1602_write_com(0x80+4+0x40);
- LCD1602_write_data(0x30+bb);
- LCD1602_write_com(0x80+5+0x40);
- LCD1602_write_data(0x30+cc);
- LCD1602_write_com(0x80+6+0x40);
- LCD1602_write_data(0x30+ab);
- LCD1602_write_com(0x80+7+0x40);
- LCD1602_write_word("humid");
-
- LCD1602_write_com(0x80+1);
- LCD1602_write_word("tem=");
- LCD1602_write_com(0x80+5);
- LCD1602_write_data(0x30+dd);
- LCD1602_write_com(0x80+8);
- LCD1602_write_word(".");
- LCD1602_write_com(0x80+6);
- LCD1602_write_data(0x30+ee);
- LCD1602_write_com(0x80+7);
- LCD1602_write_data(0x30+ff);
- LCD1602_write_com(0x80+9);
- LCD1602_write_data(0x30+gg);
-
-
- }
- /***********************************
- 函数名: Analog_IO_Sel()
- 参数说明: m 的值对应ADC0809芯片上模拟输入的IO
- 功能: 确定模拟输入位选
- ***********************************/
- //void init()
- //{if(a==0)
- //{
- // EA=1; //开总中断
- // TMOD=0x02; //设定定时器 T0工作方式
- // TH0=21; //利用T0中断产生CLK信号
- // TL0=21;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei附件下载:
大棚温湿度控制.rar
(198.02 KB, 下载次数: 327)
|