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

简介: 【单片机课程设计】温室大棚控制系统
  • 课程设计要求
  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或易安卓自行开发

相关文章
|
7月前
|
传感器 C语言 智能硬件
基于单片机的温度控制系统
基于单片机的温度控制系统
130 0
|
5月前
单片机课程设计——PWM电机调速
单片机课程设计——PWM电机调速
|
6月前
|
数据安全/隐私保护
单片机课程设计——基于C51电子密码锁(源代码)
单片机课程设计——基于C51电子密码锁(源代码)
|
7月前
基于51单片机的模拟交通灯控制系统
该文档描述了一个基于51单片机的交通灯控制系统的设计要求和实现。系统应用于十字路口,控制主干道(东西方向)和支干道(南北方向)的交通流量。主干道绿灯时间为15秒,支干道为10秒,转换时黄灯闪烁3秒。用户可以通过按键设置通行时间和进行交通管制。系统包括四个状态:主干道绿灯、主干道黄灯、支干道绿灯和支干道黄灯,循环运行。此外,还提供了仿真电路图、原理图和实物照片,以及C代码示例。
191 1
|
传感器 芯片
【单片机课程设计】环境监测控制系统
【单片机课程设计】环境监测控制系统
147 0
|
7月前
|
IDE 开发工具
基于单片机的简易步进电机控制系统
基于单片机的简易步进电机控制系统
101 0
|
7月前
|
传感器 人工智能 前端开发
单片机毕业设计|农家菜园自动灌溉控制系统设计
单片机毕业设计|农家菜园自动灌溉控制系统设计
120 0
|
7月前
|
传感器 人工智能 前端开发
单片机毕业设计|农家菜园自动灌溉控制系统设计
本系统是基于单片机的农家菜园自动灌溉控制系统设计,以51单片机作为控制核心,实现菜园自动灌溉及智能控制系统的设计,能够实现对土壤温湿度以及光照强度的检测,并且根据设置的阈值及时间进行自动检测与灌溉。
147 0
【单片机课程设计】汽车盲区检测系统
【单片机课程设计】汽车盲区检测系统
162 0
|
传感器
【单片机】单片机课程设计(测温打铃)附完整代码和电路图
【单片机】单片机课程设计(测温打铃)附完整代码和电路图
200 0