基于51单片机的蔬菜大棚温湿度智能控制系统设计模块使用:使用dht11、74hc595数码管模块、继电器模块
任务1)根据检测到的温湿度信息控制通风与加热; 2)采用MCU、温湿度传感器、继电器、按键、数码管等; 3)通过按键设定大棚温湿度报警值; 4)上传信息到PC机; 5)当温度或适度超限时用继电器控制小灯状态模拟相应动作的发生。
单片机源程序如下:
- ////////////////////////////////////////////////////10.3 17:58////////////////////////////////////////////////////////
- #include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
- #include <intrins.h>
- #include <math.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit RS = P1^0; //定义端口
- sbit RW = P1^1;
- sbit EN = P2^5;
- sbit DU = P2^0;
- sbit WE = P2^1;
- sbit Data = P3^6;//定义数据线
- uchar rec_dat[19]; //用于显示的接收数据数组
-
- #define RS_CLR RS=0
- #define RS_SET RS=1
-
- #define RW_CLR RW=0
- #define RW_SET RW=1
-
- #define EN_CLR EN=0
- #define EN_SET EN=1
-
- #define DataPort P0
-
-
- void cmg88()//关数码管,点阵函数
- {
- DU=1;
- P0=0X00;
- DU=0;
- }
- /*------------------------------------------------
- uS延时函数,含有输入参数 unsigned char t,无返回值
- unsigned char 是定义无符号字符变量,其值的范围是
- 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
- 长度如下 T=tx2+5 uS
- ------------------------------------------------*/
- void DelayUs2x(unsigned char t)
- {
- while(--t);
- }
- /*------------------------------------------------
- mS延时函数,含有输入参数 unsigned char t,无返回值
- unsigned char 是定义无符号字符变量,其值的范围是
- 0~255 这里使用晶振12M,精确延时请使用汇编
- ------------------------------------------------*/
- void DelayMs(unsigned char t)
- {
-
- while(t--)
- {
- //大致延时1mS
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- // 判忙函数
- bit LCD_Check_Busy(void)
- {
- DataPort= 0xFF;
- RS_CLR;
- RW_SET;
- EN_CLR;
- _nop_();
- EN_SET;
- return (bit)(DataPort & 0x80);
- }
- // 写入命令函数
- void LCD_Write_Com(unsigned char com)
- {
- while(LCD_Check_Busy()); //忙则等待
- RS_CLR;
- RW_CLR;
- EN_SET;
- DataPort= com;
- _nop_();
- EN_CLR;
- }
- // 写入数据函数
- void LCD_Write_Data(unsigned char Data)
- {
- while(LCD_Check_Busy()); //忙则等待
- RS_SET;
- RW_CLR;
- EN_SET;
- DataPort= Data;
- _nop_();
- EN_CLR;
- }
-
- // 清屏函数
- void LCD_Clear(void)
- {
- LCD_Write_Com(0x01);
- DelayMs(5);
- }
- // 写入字符串函数
- void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
- {
- if (y == 0)
- {
- LCD_Write_Com(0x80 + x); //表示第一行
- }
- else
- {
- LCD_Write_Com(0xC0 + x); //表示第二行
- }
- while (*s)
- {
- LCD_Write_Data( *s);
- s ++;
- }
- }
- // 写入字符函数
- void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
- {
- if (y == 0)
- {
- LCD_Write_Com(0x80 + x);
- }
- else
- {
- LCD_Write_Com(0xC0 + x);
- }
- LCD_Write_Data( Data);
- }
- // 初始化函数
- void LCD_Init(void)
- {
- LCD_Write_Com(0x38); /*显示模式设置*/
- DelayMs(5);
- LCD_Write_Com(0x38);
- DelayMs(5);
- LCD_Write_Com(0x38);
- DelayMs(5);
- LCD_Write_Com(0x38);
- LCD_Write_Com(0x08); /*显示关闭*/
- LCD_Write_Com(0x01); /*显示清屏*/
- LCD_Write_Com(0x06); /*显示光标移动设置*/
- DelayMs(5);
- LCD_Write_Com(0x0C); /*显示开及光标设置*/
- }
-
-
- /*------------------------------------------------
- DHT11延时函数
- ------------------------------------------------*/
- void DHT11_delay_us(uchar n)
- {
- while(--n);
- }
-
- void DHT11_delay_ms(uint z)
- {
- uint i,j;
- for(i=z;i>0;i--)
- for(j=110;j>0;j--);
- }
- /*------------------------------------------------
- DHT11开始信号
- ------------------------------------------------*/
- void DHT11_start()
- {
- Data=1;
- DHT11_delay_us(2);
- Data=0;
- DHT11_delay_ms(20); //延时18ms以上
- Data=1;
- DHT11_delay_us(30);
- }
- // 接收八位二进制
- uchar DHT11_rec_byte() //接收一个字节
- {
- uchar i,dat=0;
- for(i=0;i<8;i++) //从高到低依次接收8位数据
- {
- while(!Data); ////等待50us低电平过去
- DHT11_delay_us(8); //延时60us,如果还为高则数据为1,否则为0
- dat<<=1; //移位使正确接收8位数据,数据为0时直接移位
- if(Data==1) //数据为1时,使dat加1来接收数据1
- dat+=1;
- while(Data); //等待数据线拉低
- }
- return dat;
- }
- // 接收40bit数据
- void DHT11_receive() //接收40位的数据
- {
- uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
- DHT11_start();
-
- if(Data==0)
- {
-
- while(Data==0); //等待拉高
-
- DHT11_delay_us(40); //拉高后延时80us
- R_H=DHT11_rec_byte(); //接收湿度高八位
- R_L=DHT11_rec_byte(); //接收湿度低八位
- T_H=DHT11_rec_byte(); //接收温度高八位
- T_L=DHT11_rec_byte(); //接收温度低八位
- revise=DHT11_rec_byte(); //接收校正位
-
- DHT11_delay_us(25); //结束
-
- if((R_H+R_L+T_H+T_L)==revise) //校正
- {
- RH=R_H;
- RL=R_L;
- TH=T_H;
- TL=T_L;
- }
- /*数据处理,方便显示*/
- rec_dat[0]='0'+(RH/10);
- rec_dat[1]='0'+(RH%10);
- rec_dat[2] =' ';
- rec_dat[3] = 'R' ;
- rec_dat[4] = 'H';
- rec_dat[5]=' ';
- rec_dat[6]=' ';
- rec_dat[7]=' ';
- rec_dat[8]=' ';
- rec_dat[9]='0'+(TH/10);
- rec_dat[10]='0'+(TH%10);
- rec_dat[11] =' ';
- rec_dat[12] = 'C';
- rec_dat[13] = ' ' ;
- rec_dat[14]=' ';
- rec_dat[15] =(RH/10);
- rec_dat[16] =(RH%10);
- rec_dat[17] =(TH/10) ;
- rec_dat[18]=(TH%10);
- }
- }
- /////////////////数码管///////////////////////////////////////////////
-
-
- unsigned char code fseg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- unsigned char code segbit[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
- unsigned char disbuf[8]={0,0,0,0,0,0,0,0};
- unsigned char code LED_0F[]; // LED字模表
- sbit DIO = P1^0; //串行数据输入
- sbit rclck = P1^1; //时钟脉冲信号——上升沿有效
- sbit SCLK = P1^2; //打入信号————上升沿有效
- //-----------------------------------------------------------------------------
- // 全局变量
- uchar LED[8]; //用于LED的8位显示缓存
-
- unsigned char code LED_0F[] =
- {// 0 1 2 3 4 5 6 7 8 9 A b C d E F -
- 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF,0xbf
- };
- void LED_OUT(uchar X)
- {
- uchar i;
- for(i=8;i>=1;i--)
- {
- if (X&0x80) DIO=1; else DIO=0;
- X<<=1;
- SCLK = 0;
- SCLK = 1;
- }
- }
- void LED8_Display (void)
- {
- unsigned char code *led_table; // 查表指针
- uchar i;
- //显示第1位
- led_table = LED_0F + LED[0];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x01);
- rclck = 0;
- rclck = 1;
- //显示第2位
- led_table = LED_0F + LED[1];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x02);
- rclck = 0;
- rclck = 1;
- //显示第3位
- led_table = LED_0F + LED[2];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x04);
- rclck = 0;
- rclck = 1;
- //显示第4位
- led_table = LED_0F + LED[3];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x08);
- rclck = 0;
- rclck = 1;
- led_table = LED_0F + LED[4];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x10);
- rclck = 0;
- rclck = 1;
-
- //显示第6位
- led_table = LED_0F + LED[5];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x20);
- rclck = 0;
- rclck = 1;
- //显示第7位
- led_table = LED_0F + LED[6];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x40);
- rclck = 0;
- rclck = 1;
- //显示第8位
- led_table = LED_0F + LED[7];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x80);
- rclck = 0;
- rclck = 1;
- }
-
-
- void LED2_Display (uchar *wei)
- {
- unsigned char code *led_table; // 查表指针
- uchar i;
- if(wei==1)
- {
- //显示第1位
- led_table = LED_0F + LED[0];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x01);
- rclck = 0;
- rclck = 1;
- //显示第2位
- led_table = LED_0F + LED[1];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x02);
- rclck = 0;
- rclck = 1;
- }
- if(wei==2)
- {
- //显示第3位
- led_table = LED_0F + LED[2];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x04);
- rclck = 0;
- rclck = 1;
- //显示第4位
- led_table = LED_0F + LED[3];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x08);
- rclck = 0;
- rclck = 1;
- }
- if(wei==3)
- {
- led_table = LED_0F + LED[4];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x10);
- rclck = 0;
- rclck = 1;
-
- //显示第6位
- led_table = LED_0F + LED[5];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x20);
- rclck = 0;
- rclck = 1;
- }
- if(wei==4)
- {
- //显示第7位
- led_table = LED_0F + LED[6];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x40);
- rclck = 0;
- rclck = 1;
- //显示第8位
- led_table = LED_0F + LED[7];
- i = *led_table;
- LED_OUT(i);
- LED_OUT(0x80);
- rclck = 0;
- rclck = 1;
- }
- }
- uchar wendu;
- uchar shidu;
- void shumaguan_show(void)
- {
- LED[1]=rec_dat[15];
- LED[0]=rec_dat[16];
- shidu=rec_dat[15]*10+rec_dat[16];
- LED[7]=rec_dat[17];
- LED[6]=rec_dat[18];
- wendu=rec_dat[17]*10+rec_dat[18];
- LED[2]=16;
- LED[3]=16;
- LED[4]=16;
- LED[5]=16;
- LED8_Display ();
-
- }
- //////////////////////////////////////////////////////////////////////////
- sbit Beep=P2^2; //设置蜂鸣器引脚
- sbit K1=P2^3;
- sbit K2=P2^4;
- sbit K3=P2^5;
- sbit K4=P2^6;
- sbit K5=P2^7;
- void key_init(void)
- {
- K1=1;
- K2=1;
- K3=1;
- K4=1;
- }
- uchar an=0;
- uchar move=0;
- void caidan(void)
- {
- if(K1==0&&an==0)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K1); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- an=1;
-
- }
- if(K1==0&&an==1)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K1); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- an=0;
- }
- }
- void move_2(void)
- {
- if(K2==0&&move==0)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K2); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- move=1;
- }
-
- if(K2==0&&move==1)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K2); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- move=2;
- }
- if(K2==0&&move==2)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K2); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- move=3;
- }
- if(K2==0&&move==3)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K2); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- move=0;
- }
-
- }
- uchar AlarmTL; // 温度下限报警值
- uchar AlarmTH; // 温度上限报警值
- uchar AlarmHL; // 湿度下限报警值
- uchar AlarmHH; // 湿度上限报警值
- void up_down(void)
- {
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- if(K4==0&&move==0)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K4); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- if(AlarmTL>0) // 只有当湿度上限值大于0时,才能减1
- {
- AlarmTL--;
-
-
- }
- }
- if(K3==0&&move==0) // 判断 “加按键“ 是否被按下
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K3); // 等待按键释放
- DelayMs(10);
- if(AlarmTL<99) // 只有当湿度上限值小于99时,才能加1
- AlarmTL++;
-
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- if(K4==0&&move==1)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K4); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- if(AlarmTH>0) // 只有当湿度上限值大于0时,才能减1
- {
- AlarmTH--;
-
-
- }
- }
- if(K3==0&&move==1) // 判断 “加按键“ 是否被按下
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K3); // 等待按键释放
- DelayMs(10);
- if(AlarmTH<99) // 只有当湿度上限值小于99时,才能加1
- AlarmTH++;
-
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- if(K4==0&&move==2)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K4); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- if(AlarmHL>0) // 只有当湿度上限值大于0时,才能减1
- {
- AlarmHL--;
-
-
- }
- }
- if(K3==0&&move==2) // 判断 “加按键“ 是否被按下
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K3); // 等待按键释放
- DelayMs(10);
- if(AlarmHL<99) // 只有当湿度上限值小于99时,才能加1
- AlarmHL++;
-
- }
- ///////////////////////////////////////////////////////////////////////////////////////////
- if(K4==0&&move==3)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K4); // 等待按键释放
- DelayMs(10); // 去除按键松开的抖动
- if(AlarmHH>0) // 只有当湿度上限值大于0时,才能减1
- {
- AlarmHH--;
-
-
- }
- }
- if(K3==0&&move==3) // 判断 “加按键“ 是否被按下
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K3); // 等待按键释放
- DelayMs(10);
- if(AlarmHH<99) // 只有当湿度上限值小于99时,才能加1
- AlarmHH++;
-
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////
- }
- uchar TAB[8]={0x00,0x00,0x00,0x00,0x00};
- void send(uchar dat)
- {
- SBUF=dat;
- while(TI==0);
- TI=0;
- }
- sbit LED1=P0^6;
- sbit LED2=P0^7;
- sbit LED3=P0^4;
- sbit LED4=P0^5;
- void panduan(void)
- {
- if(wendu<AlarmTL)
- {
- LED1=0;
- Beep=0;
- DelayMs(2);
- Beep=1;
- }
- if(wendu>AlarmTL)
- {
- LED1=1;
- Beep=1;
- }
- if(wendu>AlarmTH)
- {
- LED2=0;
- Beep=0;
- DelayMs(2);
- Beep=1;
- }
- if(wendu<AlarmTH)
- {
- LED2=1;
- Beep=1;
- }
- if(shidu<AlarmHL)
- {
- LED3=0;
- Beep=0;
- DelayMs(2);
- Beep=1;
- }
- if(shidu>AlarmHL)
- {
- LED3=1;
- Beep=1;
- }
- if(shidu>AlarmHH)
- {
- LED4=0;
- Beep=0;
- DelayMs(2);
- Beep=1;
- }
- if(shidu<AlarmHH)
- {
- LED4=1;
- Beep=1;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- /*------------------------------------------------
- 主函数
- ------------------------------------------------*/
- void main(void)
- {
- uchar i;
- TMOD=0X20;
- SCON=0X40;
- PCON=0X00;
- TH1=0xfd;
- TL1=0xfd;
- TR1=1;
- key_init();
- AlarmTL=15;
- AlarmTH=50;
- AlarmHL=15;
- AlarmHH=50;
- DHT11_delay_ms(1000); //DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令
- P0=0xff;
- while (1)
- {
- caidan();
- if(an==0)
- {
- DHT11_receive();
- shumaguan_show();
- panduan();
- }
- if(an==1)
- {
- Beep=1;
- DelayMs(10);
- move_2(); //2位右移
- up_down();
- LED[1]=AlarmHH/10;// 湿度上限报警
- LED[0]=AlarmHH%10;
- LED[2]=AlarmHL%10; // 湿度下限报警
- LED[3]=AlarmHL/10;
- LED[7]=AlarmTL/10; // 温度下限报警
- LED[6]=AlarmTL%10;
- LED[4]=AlarmTH%10;// 温度上限报警
- LED[5]=AlarmTH/10;
-
- if(move==0) LED2_Display (4);
- if(move==1) LED2_Display (3);
- if(move==2) LED2_Display (2);
- if(move==3) LED2_Display (1);
- }
- if(K5==0)
- {
- DelayMs(10); // 去除按键按下的抖动
- while(!K5); // 等待按键释放
- DelayMs(10);
- TAB[0]=rec_dat[15];
- TAB[1]=rec_dat[16];
- TAB[2]=rec_dat[17];
- TAB[3]=rec_dat[18];
- TAB[4]=0x00;
- for(i=0;i<4;i++)
- {
- send(TAB[i]);
- DelayMs(200);
- }
- }
-
- }
- }
复制代码
所有资料51hei提供下载:
基于单片机的蔬菜大棚温湿度智能控制系统设计.rar
(708.89 KB, 下载次数: 275)
|