我们这个系统主要用来采集温室内的温湿度信息,及时的反映出温湿度的变化,以便及时的对温室内的温湿度做出调整,保证一个良好的温湿度环境。在超过温度上下限范围时通过多种控制方式来实现温度的上升或者下降,从而保证在一定范围内的温度。对于湿度的控制也是同样的道理。将系统应用到温室中来控制温室内的一个温湿度,无疑为温室内植被生长提供了更加适宜的温湿度环境。有些植被必须在某些特定环境下才可以生长的很好,这样的情况下安装温湿度装置对其进行监控就是非常有必要的。像温室大棚种植蔬菜、水果、花卉等,我们能够用单片机来实现对温室的一个控制,显而易见会给我们带来很大的一个方便。 我们设计的这个系统可以及时、精确地反映温室内的温度以及湿度的变化,保证温室内温湿度的控制要求。温室温湿监控制系统的设计是一个对实际生产生活非常实用,可行性很高的一个设计,对学生在单片机知识的运用上也是非常好的锻炼课题。 - /*主程序*/
- #include<reg52.h>
- #include"ds1302.h"
- #include"12864.h"
- #include"DHT11.h"
- #include"define.h"
- unsigned char TempData[8];
- void dis_time() //向12864写时钟数据//
- {
- lcd_pos(0,1);
- write_date(TempData[1]/10+0x30);
- write_date(TempData[1]%10+0x30);
- lcd_pos(0,3);
- write_date(TempData[2]/10+0x30);
- write_date(TempData[2]%10+0x30);
- lcd_pos(0,5);
- write_date(TempData[3]/10+0x30);
- write_date(TempData[3]%10+0x30);
- lcd_pos(1,1);
- write_date(TempData[7]%10+0x30);
- lcd_pos(1,2);
- write_date(TempData[4]/10+0x30);
- write_date(TempData[4]%10+0x30);
- lcd_pos(1,4);
- write_date(TempData[5]/10+0x30);
- write_date(TempData[5]%10+0x30);
- lcd_pos(1,6);
- write_date(TempData[6]/10+0x30);
- write_date(TempData[6]%10+0x30);
- }
- bit SetFlag; //更新时间标志位
- unsigned char time_buf2[16];
- void UART_Init(void)
- {
- SCON = 0x50; /* SCON: 模式 1, 8-bit UART, 使能接收*/
- TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
- TH1 = 0xFD; /* TH1: reload value for 9600 baud @ 11.0592MHz */
- TR1 = 1; /* TR1: timer 1 run */
- EA = 1; /*打开总中断*/
- ES = 1; /*打开串口中断*/
- }
- main()
- {
- unsigned char i;
- UART_Init();
- ds1302_init(); /*DS302初始化函数*/
- //ds1302_write_time();
- lcd_init(); //初始化LCD
- delay(15); //延时用于稳定功能
- dht11_receive();
- set_kongzhi();
- while(1)
- {
- dht11_receive();
- kongzhi();
- ds1302_read_time();//读取时钟信息
- for(i=1;i<8;i++)
- TempData[i]=time_buf1[i];
- dis_time(); //液晶显示时间信息
- //KeyPro();
- if(SetFlag) //如果接收到串口信息则更新时钟
- {
- for(i=0;i<8;i++)
- {
- time_buf1[i]=time_buf2[2*i]*10+time_buf2[2*i+1];//数据整合,如2个数 1和5整合成15
- }
- ds1302_write_time(); SetFlag=0; //时钟信息更新后标志位清零
- }
- }
- }
- /******************************************************************/
- /* 串口中断程序 */
- /******************************************************************/
- void UART_SER (void) interrupt 4 //串行中断服务程序
- {
- unsigned char Temp; //定义临时变量
- unsigned char i;
- if(RI) //判断是接收中断产生
- {
- RI=0; //标志位清零
- Temp=SBUF; //读入缓冲区的值
- time_buf2[i]=Temp&0x0F; i++;
- if(i==16) //连续接收16个字符信息
- {
- i=0;SetFlag=1; //接收完成标志位置1
- }
- SBUF=Temp; //把接收到的值再发回电脑端
- //P1=Temp&0x0F; //调试时候显示
- }
- if(TI) //如果是发送标志位,清零
- TI=0;
- }
- /*初始化*/
- #ifndef _define_H
- #define _define_H
- #define uchar unsigned char
- #define uint unsigned int
- sbit speaker=P2^7; //蜂鸣器
- sbit ji1=P2^0; //继电器1
- sbit ji2=P2^1; //继电器2
- sbit ji3=P2^2; //继电器3
- sbit ji4=P2^3; //继电器4
- uchar shuzhi[2]={0}; //存储 输入键值
- #endif
- /*--------------------------------------------------------------------------
- REG52.H STC89C52单片机系统初始化
- --------------------------------------------------------------------------*/
- #ifndef __REG52_H__
- #define __REG52_H__
- /* BYTE Registers */
- sfr P0 = 0x80;sfr P1= 0x90;sfr P2= 0xA0;sfr P3= 0xB0;sfr PSW= 0xD0;
- sfr ACC= 0xE0;sfr B= 0xF0;sfr SP = 0x81;sfr DPL= 0x82;sfr DPH= 0x83;
- sfr PCON= 0x87;sfr TCON= 0x88;sfr TMOD= 0x89;sfr TL0= 0x8A;
- sfr TL1= 0x8B;sfr TH0= 0x8C;sfr TH1= 0x8D;sfr IE= 0xA8;sfr IP= 0xB8;
- sfr SCON= 0x98;sfr SBUF= 0x99;
- /* 8052 Extensions */
- sfr T2CON= 0xC8;sfr RCAP2L = 0xCA;sfr RCAP2H = 0xCB;
- sfr TL2= 0xCC;sfr TH2= 0xCD;
- /* BIT Registers */
- /* PSW */
- sbit CY = PSW^7;sbit AC= PSW^6;sbit F0= PSW^5;sbit RS1= PSW^4;
- sbit RS0= PSW^3;sbit OV= PSW^2;sbit P= PSW^0; //8052 only
- /* TCON */
- sbit TF1= TCON^7;sbit TR1 = TCON^6;sbit TF0= TCON^5;sbit TR0= TCON^4;
- sbit IE1= TCON^3;sbit IT1 = TCON^2;sbit IE0= TCON^1;sbit IT0= TCON^0;
- /* IE */
- sbit EA = IE^7;sbit ET2= IE^5; //8052 onlysbit ES= IE^4;sbit ET1 = IE^3;
- sbit EX1= IE^2;sbit ET0 = IE^1;sbit EX0= IE^0;
- /* IP */
- sbit PT2 = IP^5;sbit PS= IP^4;sbit PT1= IP^3;sbit PX1= IP^2;
- sbit PT0 = IP^1;sbit PX0= IP^0;
- /* P3 */
- sbit RD= P3^7;sbit WR= P3^6;sbit T1= P3^5;sbit T0= P3^4;sbit INT1= P3^3;
- sbit INT0= P3^2;sbit TXD = P3^1;sbit RXD= P3^0;
- /* SCON */
- sbit SM0= SCON^7;sbit SM1 = SCON^6;sbit SM2= SCON^5;sbit REN= SCON^4;
- sbit TB8= SCON^3;sbit RB8= SCON^2;sbit TI= SCON^1;sbit RI = SCON^0;
- /* P1 */
- sbit T2EX = P1^1; // 8052 only sbit T2 = P1^0; // 8052 only
- /* T2CON */
- sbit TF2= T2CON^7;sbit EXF2= T2CON^6;sbit RCLK = T2CON^5;
- sbit TCLK= T2CON^4;sbit EXEN2= T2CON^3;sbit TR2= T2CON^2;
- sbit C_T2= T2CON^1;sbit CP_RL2 = T2CON^0;
- #endif
- /* DS1302时钟模块 */
- #include <reg52.h>
- #include<intrins.h>
- sbit SCK=P2^6; sbit SDA=P2^5; sbit RST=P2^4;
- /*复位脚*/
- #define RST_CLR RST=0/*电平置低*/
- #define RST_SET RST=1/*电平置高*/
- /*双向数据*/
- #define IO_CLR SDA=0/*电平置低*/
- #define IO_SET SDA=1/*电平置高*/
- #define IO_R SDA/*电平读取*/
- /*时钟信号*/
- #define SCK_CLR SCK=0/*时钟信号*/
- #define SCK_SET SCK=1/*电平置高*/
- #define ds1302_sec_add 0x80 //秒数据地址
- #define ds1302_min_add 0x82 //分数据地址
- #define ds1302_hr_add 0x84 //时数据地址
- #define ds1302_date_add 0x86 //日数据地址
- #define ds1302_month_add 0x88 //月数据地址
- #define ds1302_day_add 0x8a //星期数据地址
- #define ds1302_year_add 0x8c //年数据地址
- #define ds1302_control_add 0x8e //控制数据地址
- #define ds1302_charger_add 0x90
- #define ds1302_clkburst_add 0xbe
- unsigned char time_buf1[8] = {20,9,3,13,18,51,00,6};//空年月日时分秒周
- unsigned char time_buf[8] ;//空年月日时分秒周
- /*向DS1302写入一字节数据*/
- void ds1302_write_byte(unsigned char addr, unsigned char d) {
- unsigned char i;
- RST_SET; /*启动DS1302总线*/
- /*写入目标地址:addr*/
- addr = addr & 0xFE;/*最低位置零*/
- for (i = 0; i < 8; i ++) {
- if (addr & 0x01) {
- IO_SET;
- }
- else {
- IO_CLR;
- }
- SCK_SET; SCK_CLR;
- addr = addr >> 1;
- }
- /*写入数据:d*/
- for (i = 0; i < 8; i ++) {
- if (d & 0x01)
- {
- IO_SET;
- }
- else {
- IO_CLR;
- }
- SCK_SET; SCK_CLR; d = d >> 1;
- }
- RST_CLR; /*停止DS1302总线*/
- }
- /*从DS1302读出一字节数据*/
- unsigned char ds1302_read_byte(unsigned char addr) {
- unsigned char i;
- unsigned char temp;
- RST_SET; /*启动DS1302总线*/
- /*写入目标地址:addr*/
- addr = addr | 0x01;/*最低位置高*/
- for (i = 0; i < 8; i ++) {
- if (addr & 0x01) {
- IO_SET;
- }
- else {
- IO_CLR;
- }
- SCK_SET; SCK_CLR;
- addr = addr >> 1;
- }
- /*输出数据:temp*/
- for (i = 0; i < 8; i ++) {
- temp = temp >> 1;
- if (IO_R) {
- temp |= 0x80;
- }
- else {
- temp &= 0x7F;
- }
- SCK_SET; SCK_CLR;
- }
- RST_CLR; /*停止DS1302总线*/
- return temp;
- }
- /*向DS302写入时钟数据*/
- void ds1302_write_time(void) {
- unsigned char i,tmp;
- for(i=0;i<8;i++){ //BCD处理
- tmp=time_buf1[i]/10;
- time_buf[i]=time_buf1[i]%10;
- time_buf[i]=time_buf[i]+tmp*16;
- }
- ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护
- ds1302_write_byte(ds1302_sec_add,0x80); //暂停
- ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电
- ds1302_write_byte(ds1302_year_add,time_buf[1]); //年
- ds1302_write_byte(ds1302_month_add,time_buf[2]); //月
- ds1302_write_byte(ds1302_date_add,time_buf[3]); //日
- ds1302_write_byte(ds1302_day_add,time_buf[7]); //周
- ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时
- ds1302_write_byte(ds1302_min_add,time_buf[5]); //分
- ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒
- ds1302_write_byte(ds1302_day_add,time_buf[7]); //周
- ds1302_write_byte(ds1302_control_add,0x80); //打开写保护
- }
- /*从DS1302读出时钟数据*/
- void ds1302_read_time(void) {
- unsigned char i,tmp;
- time_buf[1]=ds1302_read_byte(ds1302_year_add); //年
- time_buf[2]=ds1302_read_byte(ds1302_month_add); //月
- time_buf[3]=ds1302_read_byte(ds1302_date_add); //日
- time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时
- time_buf[5]=ds1302_read_byte(ds1302_min_add); //分
- time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7F;//秒
- time_buf[7]=ds1302_read_byte(ds1302_day_add); //周
- for(i=0;i<8;i++){ //BCD处理
- tmp=time_buf[i]/16;
- time_buf1[i]=time_buf[i]%16;
- time_buf1[i]=time_buf1[i]+tmp*10;
- }
- }
- /*DS1302初始化函数*/
- void ds1302_init(void) {
- RST_CLR; /*RST脚置低*/
- SCK_CLR; /*SCK脚置低*/
- }
- /*--------------------------------------------------------------------------
- INTRINS.H
- Intrinsic functions for C51.
- Copyright (c) 1988-2004 Keil Elektronik GmbH and Keil Software, Inc.
- All rights reserved.
- --------------------------------------------------------------------------*/
- #ifndef __INTRINS_H__
- #define __INTRINS_H__
- extern void _nop_ (void);
- extern bit _testbit_ (bit);
- extern unsigned char _cror_ (unsigned char, unsigned char);
- extern unsigned int _iror_ (unsigned int, unsigned char);
- extern unsigned long _lror_ (unsigned long, unsigned char);
- extern unsigned char _crol_ (unsigned char, unsigned char);
- extern unsigned int _irol_ (unsigned int, unsigned char);
- extern unsigned long _lrol_ (unsigned long, unsigned char);
- extern unsigned char _chkfloat_(float);
- extern void _push_ (unsigned char _sfr);
- extern void _pop_ (unsigned char _sfr);
- #endif
- /*12864液晶显示模块*/
- #ifndef _12864_H
- #define _12864_H
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /*端口定义*/
- sbit lcdrs=P3^6;sbit lcdrw=P3^5;sbit lcden=P3^4;sbit lcdpsb=P3^7;
- uchar code dis1[]={"20 年 月 日 "};
- uchar code dis2[]={"周 时 分 秒"};
- uchar code dis3[]={"湿度 % 高 低 "};
- uchar code dis4[]={"温度 ℃高 低 "};
- void delay(uint z)
- {
- uint x,y; for(x=0;x<z;x++)
- for(y=0;y<110;y++);
- }
- /*写指令数据到lcd*/
- void write_cmd(uchar cmd)
- {
- lcdrs=0; lcdrw=0; lcden=0; P0=cmd;
- delay(5); lcden=1; delay(5); lcden=0;
- }
- /*写显示数据到lcd*/
- void write_date(uchar date)
- {
- lcdrs=1; lcdrw=0; lcdrw=0; P0=date;
- delay(5); lcden=1; delay(5); lcden=0;
- }
- /*设定显示位置*/
- void lcd_pos(uchar x,uchar y)
- {
- uchar pos; if(x==0) {x=0x80;}
- else if(x==1) {x=0x90;}
- else if(x==2) {x=0x88;}
- else if(x==3) {x=0x98;}
- pos=x+y; write_cmd(pos);
- }
- void lcd_dis(uchar dis[])
- {
- uchar i; i=0;
- while(dis[i] !='\0')
- {
- write_date(dis[i]); i++;
- }
- }
- /********************清屏***************************/
- void lcd_clear(void)
- {
- write_cmd(0x01); //显示清屏
- write_cmd(0x34); // 显示光标移动设置
- write_cmd(0x30); // 显示开及光标设置
- }
- void lcd_init()
- {
- lcdpsb=1; write_cmd(0x30); delay(5);
- write_cmd(0x0C); delay(5); write_cmd(0x01); delay(5);
- lcd_pos(0,0); lcd_dis(dis1); lcd_pos(1,0); lcd_dis(dis2);
- lcd_pos(2,0); lcd_dis(dis3); lcd_pos(3,0); lcd_dis(dis4);
- }
- #endif
- /*DHT11数字温湿度控制模块*/
- #ifndef _DHT11_H
- #define _DHT11_H
- #include<reg52.h>
- #include<intrins.h>
- #include"12864.h"
- #include"key.h"
- #include"define.h"
- #define uchar unsigned char
- #define uint unsigned int
- sbit dht11=P3^2; uchar data_byte; uchar RH,RL,TH,TL;
- int max_wen,min_wen,max_shi,min_shi;
- int input(uint a,uint b)
- {
- int k=0; int zhengshu;
- lcd_pos(a,b);
- while(k<2)
- {
- ReadKey();
- if(l_key<=9) //输入数字0-9
- {
- shuzhi[k]=l_key;
- write_date(shuzhi[k]+0x30);
- l_key=0xff; k++;
- }
- }
- while(k>=2)
- {
- ReadKey();
- if(l_key==15) //确定
- {
- zhengshu=shuzhi[0]*10+shuzhi[1] ;
- l_key=0xff;
- break;
- }
- }
- return zhengshu;
- }
- void dis_dht11(uchar hang,uchar add,char date)
- {
- uchar shi,ge; shi=date/10+0x30; ge=date%10+0x30;
- lcd_pos(hang,add); write_date(shi); write_date(ge);
- }
- void delay10us()//延时10us
- {
- uchar i; i--; i--; i--; i--; i--; i--;
- }
- void start()//开始信号
- {
- dht11=1; delay10us(); dht11=0; delay(40);//>18ms
- dht11=1; delay10us();//20-40us delay10us(); delay10us();
- delay10us(); delay10us();
- }
- uchar receive_byte()//接收一个字节
- {
- uchar i,temp,count;
- for(i=0;i<8;i++)
- {
- count=2;
- while((!dht11)&&count++)//等待50us低电平结束
- temp=0; delay10us(); delay10us(); delay10us();
- delay10us();
- if(dht11==1) temp=1; count=2;
- while((dht11)&&count++);
- if(count==1) break;
- data_byte<<=1; data_byte|=temp;
- }
- return data_byte;
- }
- void dht11_receive()//接收数据
- {
- uchar T_H,T_L,R_H,R_L,check,num_check;
- uchar count; start();//开始信号
- dht11=1;
- if(!dht11)//读取DHT11响应信号
- {
- count=2; while((!dht11)&&count++);//DHT11高电平80us是否结束
- count=2; while((dht11)&&count++);
- R_H=receive_byte(); R_L=receive_byte();
- T_H=receive_byte(); T_L=receive_byte();
- check=receive_byte(); dht11=0;//拉低延时50us
- delay10us(); delay10us(); delay10us();
- delay10us(); delay10us(); dht11=1;
- num_check=R_H+R_L+T_H+T_L;
- if(num_check=check)
- {
- RH=R_H; RL=R_L; TH=T_H; TL=T_L;
- check=num_check;
- }
- }
- dis_dht11(3,2,TH); dis_dht11(2,2,RH);
- }
- void set_kongzhi()
- {
- max_wen=input(3,5) ; min_wen=input(3,7) ;
- max_shi=input(2,5) ; min_shi=input(2,7) ;
- if(TH>max_wen)
- {
- speaker=0; ji1=0 ;
- }
- else
- if(TH<min_wen)
- {
- speaker=0; ji2=0 ;
- }
- if(RH>max_shi)
- {
- speaker=0; ji3=0 ;
- }
- else
- if(RH<min_shi)
- {
- speaker=0; ji4=0 ;
- }
- }
- void kongzhi()
- {
- if(TH>max_wen) { speaker=0; ji1=0 ; }
- else if(TH<min_wen) { speaker=0; ji2=0 ; }
- if(RH>max_shi) { speaker=0; ji3=0 ; }
- else if(RH<min_shi) { speaker=0; ji4=0 ; }
- }
- #endif
- /*4*4矩阵键盘模块*/
- #ifndef _KEY_H
- #define _KEY_H
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- Code uchar key_tab[17]={0xd7,0xee,0xde,0xbe,0xed,0xdd,0xbd,0xeb, 0xdb,0xbb,0x7e,0x7d, 0x7b,0x77,0xb7,0xe7,0XFF};
- //========================此数组为键盘编码
- // 1 2 3 a 0x01 0x02 0x03 0x0a
- // 4 5 6 b 对应16进制码 0x04 0x05 0x06 0x0b
- // 7 8 9 c 0x07 0x08 0x09 0x0c
- // e 0 f d 0x0e 0x00 0x0f 0x0d
- //键盘的读取我们采用分时扫描
- uchar l_key=0xff; //定义变量存放键值
- uchar l_keyold=0xFF; //做为按键松开否的凭证
- void ReadKey(void) //读键盘值
- { uchar i,j,key; j=0xfe;
- key=0xff; //设定初值
- for (i=0;i<4;i++)
- {
- P1=j; //P2口低4位循环输出0扫描键盘
- if ((P1&0xf0)!=0xf0)
- { //如果有键按下P2高4位不会全为1
- delay(10); P1=j;
- if ((P1&0xf0)!=0xf0)
- {
- key=P1; //读取P2口退出循环否则循环下次
- break;
- }
- }
- j=_crol_(j,1); //此函数功能为左循环移位
- }
- if (key==0xff)
- { //如果读取不到P1口的值比如是干扰不做键值处理返回
- l_keyold=0xff; return;
- }
- if(l_keyold==key)
- { //检测按键放开否如
- return;
- }
- l_keyold=key; //获取键码做为放开的凭证
- for(i=0;i<17;i++)
- { //查表获得相应的16进制值存放l_key变量中
- if (key==key_tab[i])
- {
- l_key=i; break;
- }
- } //程序运行到这里就表明有键值被读取存放于l_key变量中主程序就可以检测此变量//
- }
- #endif
复制代码 |