【单片机课程设计】温室大棚控制系统

  • 课程设计要求
  1. 可以显示温湿度,进行自动调温和灌溉。
  2. 可以手机控制手动灌溉。
  • 主要设计思想
    利用DHT11进行湿度检测、18B20用于温度检测
    灌溉使用电机
    用手机控制可以使用蓝牙或者2.4G远程控制
    主要考察51单片机的综合应用能力
  • 主要代码

DHT11.c

#include "DHT11.h"

#define uchar unsigned char
#define uint unsigned int

sbit DHT11_DQ_OUT=P3^2;

void delay(uint i)
{
    while(i--);
}
void delay_ms(uint i)
{
    while(i--)
        delay(90);
}

//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uchar DHT11_Read_Data(uchar *temp, uchar *humi)    
{        
    uchar buf[5];
    uchar i;
    DHT11_Rst();
    if(DHT11_Check()==0)
    {
        for(i=0;i<5;i++)//读取40位数据
        {
            buf[i]=DHT11_Read_Byte();
        }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
        {
            *humi=buf[0];
            *temp=buf[2];
        }
    }else return 1;
    return 0;       
}

//复位DHT11
void DHT11_Rst()       
{                 
    DHT11_DQ_OUT=0;     //拉低DQ
    delay_ms(20);       //拉低至少18ms
    DHT11_DQ_OUT=1;     //DQ=1 
    delay(3);       //主机拉高20~40us
}

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
uchar DHT11_Check()        
{   
    uchar retry=0;   
    while (DHT11_DQ_OUT&&retry<100)//DHT11会拉低40~50us
    {
        retry++;
        _nop_();
    };   
    if(retry>=100)return 1;
    else retry=0;
    while (!DHT11_DQ_OUT&&retry<100)//DHT11拉低后会再次拉高40~50us
    {
        retry++;
        _nop_();
    };
    if(retry>=100)return 1;     
    return 0;
}

//DHT11初始化 
//返回0:初始化成功,1:失败
uchar DHT11_Init()
{
    DHT11_Rst();      
    return DHT11_Check();   
}

//从DHT11读取一个位
//返回值:1/0
uchar DHT11_Read_Bit(void)           
{
    uchar retry=0;
    while(DHT11_DQ_OUT&&retry<100)//等待变为低电平 12-14us 开始
    {
        retry++;
        _nop_();
    }
    retry=0;
    while((!DHT11_DQ_OUT)&&retry<100)//等待变高电平    26-28us表示0,116-118us表示1
    {
        retry++;
        _nop_();
    }
    delay(1);//等待40us
    if(DHT11_DQ_OUT)return 1;
    else return 0;         
}

//从DHT11读取一个字节
//返回值:读到的数据
uchar DHT11_Read_Byte(void)    
{        
    uchar i,dat=0;
    for (i=0;i<8;i++) 
    {
        dat<<=1; 
        dat|=DHT11_Read_Bit();
    }                           
    return dat;
}

DHT11.h

#ifndef __DHT11_H__
#define __DHT11_H__

#include<reg52.h>   
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int

void delay(uint i);
void delay_ms(uint i);
uchar DHT11_Read_Data(uchar *temp, uchar *humi);
void DHT11_Rst();
uchar DHT11_Check();
uchar DHT11_Init();
uchar DHT11_Read_Bit(void);
uchar DHT11_Read_Byte(void);

#endif

18B20.c

#include"delay.h"
#include"18b20.h"

/*18b20初始化*/
bit Init_DS18B20(void)
{
 bit dat=0;
 DQ = 1;    	//DQ复位
 DelayUs2x(5);   //稍做延时
 DQ = 0;         //单片机将DQ拉低
 DelayUs2x(200); //精确延时 大于 480us 小于960us
 DelayUs2x(200);
 DQ = 1;        //拉高总线
 DelayUs2x(50); //15~60us 后 接收60-240us的存在脉冲
 dat=DQ;        //如果x=0则初始化成功, x=1则初始化失败
 DelayUs2x(25); //稍作延时返回
 return dat;
}

/*读取一个字节*/
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
 {
  DQ = 0; // 给脉冲信号
  dat>>=1;
  DQ = 1; // 给脉冲信号
  if(DQ)
   dat|=0x80;
  DelayUs2x(25);
 }
 return(dat);
}

/*写入一个字节*/
void WriteOneChar(unsigned char dat)
{
 unsigned char i=0;
 for (i=8; i>0; i--)
 {
  DQ = 0;
  DQ = dat&0x01;
  DelayUs2x(25);
  DQ = 1;
  dat>>=1;
 }
DelayUs2x(25);
}

/*读取温度*/
unsigned int ReadTemperature(void)
{
unsigned char a=0;
unsigned int b=0;
unsigned int t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
DelayMs(10);
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作 
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();   //低位
b=ReadOneChar();   //高位

b<<=8;
t=a+b;

return(t);
}

18B20.H

#ifndef __DS18B20_H__
#define __DS18B20_H__

#include<reg52.h>     //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

#define uchar unsigned char

sbit DQ=P1^3;//ds18b20 端口

unsigned int ReadTemperature(void);
bit Init_DS18B20(void);
unsigned char ReadOneChar(void);
void WriteOneChar(unsigned char dat);

#endif

delay.h和delay.c、1602.c和1602.h见这篇文章

main.c

#include<reg52.h>
#include "DHT11.h"
#include "1602.h"
#include "delay.h"
#include "18b20.h"

#define uchar unsigned char
#define uint unsigned int

sbit k1=P3^3; //模式
sbit k2=P2^1; //加
sbit k3=P2^2; //减

sbit led1=P3^6;
sbit led2=P3^7;

sbit dq=P2^0;
sbit relay=P1^4;     //加热设备
sbit moto=P1^5;      //电机散热
sbit auto_moto=P1^6; //自动灌溉电机

uchar mode=0,xian;
char temph=50,templ=20;
char humih=80,humil=20;
uchar temp,humi;
uchar flag;      //设定报警标志
uchar auto_flag; //设置自动、手动灌溉标志

uchar a,c,t,tempvalue;
uchar code num[10]="0123456789";

uchar code str1[]="Temp:";    //温度
uchar code str2[]="Humi:";    //湿度
uchar code str3[]="Error";  
uchar code str4[]="Success    "; 
uchar code str5[]="%RH";
uchar code str6[]="TempH:";   //设定温度上限显示
uchar code str7[]="TempL:";   //设定温度下限显示
uchar code str8[]="HumiH:";   //设定湿度上限显示
uchar code str9[]="HumiL:";   //设定湿度下限显示

void key_pros()  //按键处理函数
{
    if(k1==0)
    {
        delay(1000);
        if(k1==0)
        {
            mode++;
            if(mode==5)mode=0;
            LCD_Write_Com(0x01);
        }
        while(!k1);
    }
    if(mode==1)       //对温度上限设定
    {
        if(k2==0)         //加
        {
            delay(1000);
            if(k2==0)
            {
                temph++;
                if(temph>=80)temph=80;
            }
            while(!k2);
        }
        if(k3==0)      //减
        {
            delay(1000);
            if(k3==0)
            {
                temph--;
                if(temph<=0)temph=0;
            }
            while(!k3);
        }
    }
    if(mode==2)       //对温度下限设定
    {
        if(k2==0)         //加
        {
            delay(1000);
            if(k2==0)
            {
                templ++;
                if(templ>=80)templ=80;
            }
            while(!k2);
        }
        if(k3==0)      //减
        {
            delay(1000);
            if(k3==0)
            {
                templ--;
                if(templ<=0)templ=0;
            }
            while(!k3);
        }
    }
    if(mode==3)       //对湿度上限设定
    {
        if(k2==0)         //加
        {
            delay(1000);
            if(k2==0)
            {
                humih++;
                if(humih>=80)humih=80;
            }
            while(!k2);
        }
        if(k3==0)      //减
        {
            delay(1000);
            if(k3==0)
            {
                humih--;
                if(humih<=0)humih=0;
            }
            while(!k3);
        }
    }
    if(mode==4)       //对湿度下限设定
    {
        if(k2==0)         //加
        {
            delay(1000);
            if(k2==0)
            {
                humil++;
                if(humil>=80)humil=80;
            }
            while(!k2);
        }
        if(k3==0)      //减
        {
            delay(1000);
            if(k3==0)
            {
                humil--;
                if(humil<=0)humil=0;
            }
            while(!k3);
        }
    }
}

void lcd_init_display()    //LCD初始化显示
{
    uchar i;
    for(i=0;i<5;i++)
    {
        LCD_Write_Com(0x80+i);
        LCD_Write_Data(str1[i]);   
    }

    for(i=0;i<5;i++)
    {
        LCD_Write_Com(0xc0+i);
        LCD_Write_Data(str2[i]);   
    }
}

void data_pros()    //数据处理函数
{
    uchar i;        
    uchar temp_buf[2],humi_buf[2];
    uchar temphbuf[2],templbuf[2],humihbuf[2],humilbuf[2];
    float dio;
    uint k;

    tempvalue=ReadTemperature();
    DHT11_Read_Data(&temp,&humi);
    temp_buf[0]=temp/10+0x30;   
    temp_buf[1]=temp%10+0x30;

    humi_buf[0]=humi/10+0x30;   
    humi_buf[1]=humi%10+0x30;

    dio=a*0.0625;
    k=dio*10000;//取小数点后两位有效数字

    temphbuf[0]=temph/10+0x30;
    temphbuf[1]=temph%10+0x30;
    templbuf[0]=templ/10+0x30;
    templbuf[1]=templ%10+0x30;

    humihbuf[0]=humih/10+0x30;
    humihbuf[1]=humih%10+0x30;
    humilbuf[0]=humil/10+0x30;
    humilbuf[1]=humil%10+0x30;

    if(mode==0)
    {
        lcd_init_display();
        LCD_Write_Com(0x85);
        LCD_Write_Data(num[tempvalue%100/10]);
        LCD_Write_Data(num[tempvalue%100%10]);
        LCD_Write_Data('.');
        LCD_Write_Data(num[k/1000]);
        LCD_Write_Data(0xdf);
        LCD_Write_Data('C');

        for(i=0;i<2;i++)
        {
            LCD_Write_Com(0Xc5+i);
            LCD_Write_Data(humi_buf[i]);         
        }   
        for(i=0;i<3;i++)
        {
            LCD_Write_Com(0Xc7+i);
            LCD_Write_Data(str5[i]);         
        }   
    }
    if(mode==1)           //温度上限显示
    {
        LCD_Write_Com(0x80);
        for(i=0;i<6;i++)
        {
            LCD_Write_Data(str6[i]);         
        }
        LCD_Write_Data(temphbuf[0]);
        LCD_Write_Data(temphbuf[1]);           
    }
    if(mode==2)           //温度下限显示
    {
        LCD_Write_Com(0x80);
        for(i=0;i<6;i++)
        {
            LCD_Write_Data(str7[i]);         
        }
        LCD_Write_Data(templbuf[0]);
        LCD_Write_Data(templbuf[1]);           
    }
    if(mode==3)           //湿度上限显示
    {
        LCD_Write_Com(0x80);
        for(i=0;i<6;i++)
        {
            LCD_Write_Data(str8[i]);         
        }
        LCD_Write_Data(humihbuf[0]);
        LCD_Write_Data(humihbuf[1]);           
    }
    if(mode==4)           //湿度下限显示
    {
        LCD_Write_Com(0x80);
        for(i=0;i<6;i++)
        {
            LCD_Write_Data(str9[i]);         
        }
        LCD_Write_Data(humilbuf[0]);
        LCD_Write_Data(humilbuf[1]);           
    }
}

void baojinpros()   //报警处理
{
    if(tempvalue>=temph||humi>=humih)    //检测温度或者湿度高于设定上限值 降温湿
    {
		led1=1;     //降温湿指示灯
		led2=0;
		moto=1;
		relay=1;
		if(humi>=humih&&auto_flag==0)	//湿度过高,自动停止灌溉
		{
			auto_moto=0;
		}
    }
    if(tempvalue<=templ||humi<=humil)   //检测温度或者湿度低于设定下限值  升温湿
    {
		led1=0;	   //升高温湿指示灯
		led2=1;    
		moto=0;
		relay=0;
		if(humi<=humih&&auto_flag==0)	//湿度过低,自动开始灌溉
		{
			auto_moto=1;
		}
    }
    if((tempvalue>templ&&tempvalue<temph)&&(humi>humil&&humi<humih))
    {
        led1=0;
        led2=0;
		moto=0;
		relay=1;
		if(auto_flag==0)	           //自动开始灌溉
		{
			auto_moto=1;
		} 
    }
}

void sss() interrupt 4
{	
	if(RI)
	{ 
		t=SBUF;
	
		if(t=='1')		   //相当于按键k1
		{			
			k1=0;	
			key_pros();
			k1=1;
		}
		if(t=='2')		   //相当于按键k2
		{			
			k2=0;	 
			key_pros();	
			k2=1;		
		}
		if(t=='3')		   //相当于按键k3
		{
			k3=0;
			key_pros();
			k3=1;
		}
		if(t=='4') auto_flag=~auto_flag; //手动、自动灌溉
				
	
	  	RI=0;
	}

}

void main()
{
    uchar i=0;

    led1=0;			 //各模块初始化
    led2=0;
	relay=1;
	moto=0;
	auto_moto=0;
	auto_flag=0;
    LCD_Init();

	TMOD=0X20;		//串口初始化
    TH1=0XFD;
	TL1=0XFD;
 	TR1=1;
	SCON=0X50;
	ES=1;
	EA=1;

    while(DHT11_Init()) //检测DHT11是否存在
    {
        for(i=0;i<5;i++)
        {
            LCD_Write_Com(0x80+i);
            LCD_Write_Data(str3[i]);   
        }           
    }
    LCD_Write_Com(0x01);
    lcd_init_display();    //LCD初始化显示
    i=0;
    while(1)
    {   
        i++;
        key_pros();		//按键处理
        baojinpros();   //报警处理
        if(i==15)
        {
            i=0;
            data_pros();     //读取一次DHT11数据最少要大于100ms
        }
        delay(1000);
    }   
}

安卓界面的代码略,读者可用Java或易安卓自行开发

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为梦而生~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值