作者主页:编程指南针
作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师
主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互助
收藏点赞不迷路 关注作者有好处
文末获取源码
项目编号:BS-DPJ-006
一,环境介绍
语言环境:C
开发技术:51单片机
二,项目简介
随着时代的发展,电子控制技术在人们的生活中得到了广泛的应用。如何运用现代的电子技术,对农家菜园温度、湿度进行自动监测,并依据相关的数据进行相应的灌溉作业。这对于促进温室作物的增产、节省劳动力都是十分必要的。该系统包括单片机STC89C52,湿度传感器,温度传感器,按键,光照传感器,液晶显示屏,水泵,蓝牙和电源。该系统以STC89C52单片机为核心,以 AltiumDesigner 10为主要硬件,以 Keil为主要开发工具,以 C语言编写。论文首先对系统方案进行了整体的描述,并提出了硬件方面的设计,其中包括控制器的选择,温湿度检测模块的硬件选择,光照强度检测模块的选择,显示模块的选择,水泵灌溉模块的选择,蓝牙模块的设计。软件模块主要包括整个软件流程图、温湿度检测、光强检测等部分流程图,并采用单片机实现对电动机的控制,最后使用 C语言编写了相应的程序。
本系统是基于单片机的农家菜园自动灌溉控制系统设计,以51单片机作为控制核心,实现菜园自动灌溉及智能控制系统的设计,能够实现对土壤温湿度以及光照强度的检测,并且根据设置的阈值及时间进行自动检测与灌溉。具体来说,本文的研究内容如下:
(1)本论文的研究内容为:自动灌溉系统的设计,包括土壤湿度检测、土壤温度检测、光照强度检测、水泵灌溉、定时自动灌溉。LCD显示屏和蓝牙无线接入。本课题的研究内容包括:灌区自动控制系统总体方案设计、硬件电路设计、软件流程设计等。本论文是一项细致而有效的自动化控制工作。其终极目的是实现自动灌溉和智能化控制,可通过设定的温度、湿度和光照强度来自动监测和灌溉。
(2)首先,本文对农户菜园自动灌溉控制系统的整体结构进行了阐述,并提出了硬件方面的设计,其中包括控制器的选择,温湿度检测模块的硬件选择,光照强度检测模块的选择,显示模块的选择,水泵灌溉模块的选择,蓝牙模块的设计。软件模块主要包括整个软件流程图、温湿度检测、光强检测等部分流程图,并采用单片机实现对电动机的控制,最后使用 C语言编写了相应的程序。
(3)根据硬件设计方案,实现了农户菜园自动灌溉控制系统的实际生产,并按“先局部后整体”的原则,对控制器模块、温湿度检测模块、光照强度检测模块、显示模块、水泵灌溉模块和蓝牙模块进行模块测试,并对整个系统进行全面测试,并将有关数据进行记录。通过试验,实现了菜园的自动灌溉和智能控制,可以检测土壤的温度、湿度和光照,并根据设定的阈值和时间,自动检测和灌溉,保证了测量精度和精度。
三,系统展示
编辑
编辑
编辑
编辑
四,核心代码展示
#include <reg52.h> #include <intrins.h> #define uchar unsigned char // 以后unsigned char就可以用uchar代替 #define uint unsigned int // 以后unsigned int 就可以用uint 代替 sbit ADC_CS = P1^6; // ADC0832的CS引脚 sbit ADC_CLK = P1^7; // ADC0832的CLK引脚 sbit ADC_DAT = P3^2; // ADC0832的DI/DO引脚 sbit SCK_P = P1^0; // 时钟芯片DS1302的SCK管脚 sbit SDA_P = P1^1; // 时钟芯片DS1302的SDA管脚 sbit RST_P = P1^2; // 时钟芯片DS1302的RST管脚 sbit LcdRs_P = P1^3; // 1602液晶的RS管脚 sbit LcdRw_P = P1^4; // 1602液晶的RW管脚 sbit LcdEn_P = P1^5; // 1602液晶的EN管脚 sbit KeyMode_P = P3^3; // 模式切换 sbit KeySet_P = P3^4; // 设置时间按键 sbit KeySet2_P = P3^5; // 设置时间模式的开关时间和光照控制强度 sbit KeyDown_P = P3^6; // 减按键 sbit KeyUp_P = P3^7; // 加按键 sbit Led_P = P2^0; // 指示灯 sbit led2=P2^1; sbit fm=P2^2; bit bjflag; sbit ds=P3^1; bit closeflag,openflag; uchar gMode=1; // uchar OpenHour = 12; // 开启水泵的小时 uchar OpenMinute = 00; // 开启水泵的分钟 uchar CloseHour = 12; // 关闭水泵的小时 uchar CloseMinute = 30; // 关闭水泵的分钟 uchar gLight = 30; // 水泵开关的阈值 uchar wDu=20; uchar X_sd=40; uint wd=13,t; uchar xsflag; uchar bjcount; uchar TimeBuff[7]={17,9,1,6,18,30,40}; // 时间数组,默认2017年9月1日,星期五,18:30:40 // TimeBuff[0] 代表年份,范围00-99 // TimeBuff[1] 代表月份,范围1-12 // TimeBuff[2] 代表日期,范围1-31 // TimeBuff[3] 代表星期,范围1-7 // TimeBuff[4] 代表小时,范围00-23 // TimeBuff[5] 代表分钟,范围00-59 // TimeBuff[6] 代表秒钟,范围00-59 /*********************************************************/ // 毫秒级的延时函数,time是要延时的毫秒数 /*********************************************************/ void DelayMs(uint time) { uint i,j; for(i=0;i<time;i++) for(j=0;j<112;j++); } void delay(uint z) //延时函数 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } /*********************************************************/ // 1602液晶写命令函数,cmd就是要写入的命令 /*********************************************************/ void LcdWriteCmd(uchar cmd) { LcdRs_P = 0; LcdRw_P = 0; LcdEn_P = 0; P0=cmd; DelayMs(2); LcdEn_P = 1; DelayMs(2); LcdEn_P = 0; } /*********************************************************/ // 1602液晶写数据函数,dat就是要写入的数据 /*********************************************************/ void LcdWriteData(uchar dat) { LcdRs_P = 1; LcdRw_P = 0; LcdEn_P = 0; P0=dat; DelayMs(2); LcdEn_P = 1; DelayMs(2); LcdEn_P = 0; } /*********************************************************/ // 1602液晶初始化函数 /*********************************************************/ void LcdInit() { LcdWriteCmd(0x38); // 16*2显示,5*7点阵,8位数据口 LcdWriteCmd(0x0C); // 开显示,不显示光标 LcdWriteCmd(0x06); // 地址加1,当写入数据后光标右移 LcdWriteCmd(0x01); // 清屏 } /*********************************************************/ // 液晶光标定位函数 /*********************************************************/ void LcdGotoXY(uchar line,uchar column) { // 第一行 if(line==0) LcdWriteCmd(0x80+column); // 第二行 if(line==1) LcdWriteCmd(0x80+0x40+column); } /*********************************************************/ // 液晶输出字符串函数 /*********************************************************/ void LcdPrintStr(uchar *str) { while(*str!='\0') LcdWriteData(*str++); } /*********************************************************/ // 液晶输出数字(0-99) /*********************************************************/ void LcdPrintNum(uchar num) { LcdWriteData(num/10+48); // 十位 LcdWriteData(num%10+48); // 个位 } /*********************************************************/ // 显示模式 /*********************************************************/ void LcdPrintMode(uchar num) { switch(num) { case 1: LcdPrintStr("sdms"); break; case 2: LcdPrintStr("dsms"); break; default: break; } } /*********************************************************/ // 液晶显示内容的初始化 /*********************************************************/ void LcdShowInit() { LcdGotoXY(0,0); LcdPrintStr("20du - : "); LcdGotoXY(1,0); LcdPrintStr(" sd: gz: "); LcdGotoXY(1,0); LcdPrintMode(gMode); } /*********************************************************/ // 刷新时间显示 /*********************************************************/ void FlashTime() { LcdGotoXY(0,0); // 年份 LcdPrintNum(wd); LcdGotoXY(0,5); // 月份 LcdPrintNum(TimeBuff[1]); LcdGotoXY(0,8); // 日期 LcdPrintNum(TimeBuff[2]); LcdGotoXY(0,11); // 小时 LcdPrintNum(TimeBuff[4]); LcdGotoXY(0,14); // 分钟 LcdPrintNum(TimeBuff[5]); LcdGotoXY(0,13); // 秒钟 if(TimeBuff[6]%2==0) // 秒钟是偶数显示冒号 LcdWriteData(':'); else // 秒钟是奇数显示空格 LcdWriteData(' '); } /*********************************************************/ // 初始化DS1302 /*********************************************************/ void DS1302_Init(void) { RST_P=0; // RST脚置低 SCK_P=0; // SCK脚置低 SDA_P=0; // SDA脚置低 } /*********************************************************/ // 从DS1302读出一字节数据 /*********************************************************/ uchar DS1302_Read_Byte(uchar addr) { uchar i; uchar temp; RST_P=1; /* 写入目标地址:addr*/ for(i=0;i<8;i++) { if(addr&0x01) SDA_P=1; else SDA_P=0; SCK_P=1; _nop_(); SCK_P=0; _nop_(); addr=addr>> 1; } /* 读出该地址的数据 */ for(i=0;i<8;i++) { temp=temp>>1; if(SDA_P) temp|= 0x80; else temp&=0x7F; SCK_P=1; _nop_(); SCK_P=0; _nop_(); } RST_P=0; return temp; } /*********************************************************/ // 向DS1302写入一字节数据 /*********************************************************/ void DS1302_Write_Byte(uchar addr, uchar dat) { uchar i; RST_P = 1; /* 写入目标地址:addr*/ for(i=0;i<8;i++) { if(addr&0x01) SDA_P=1; else SDA_P=0; SCK_P=1; _nop_(); SCK_P=0; _nop_(); addr=addr>>1; } /* 写入数据:dat*/ for(i=0;i<8;i++) { if(dat&0x01) SDA_P=1; else SDA_P=0; SCK_P=1; _nop_(); SCK_P=0; _nop_(); dat=dat>>1; } RST_P=0; } /*********************************************************/ // 向DS1302写入时间数据 /*********************************************************/ void DS1302_Write_Time() { uchar i; uchar temp1; uchar temp2; for(i=0;i<7;i++) // 十进制转BCD码 { temp1=(TimeBuff[i]/10)<<4; temp2=TimeBuff[i]%10; TimeBuff[i]=temp1+temp2; } DS1302_Write_Byte(0x8E,0x00); // 关闭写保护 DS1302_Write_Byte(0x80,0x80); // 暂停时钟 DS1302_Write_Byte(0x8C,TimeBuff[0]); // 年 DS1302_Write_Byte(0x88,TimeBuff[1]); // 月 DS1302_Write_Byte(0x86,TimeBuff[2]); // 日 DS1302_Write_Byte(0x8A,TimeBuff[3]); // 星期 DS1302_Write_Byte(0x84,TimeBuff[4]); // 时 DS1302_Write_Byte(0x82,TimeBuff[5]); // 分 DS1302_Write_Byte(0x80,TimeBuff[6]); // 秒 DS1302_Write_Byte(0x80,TimeBuff[6]&0x7F); // 运行时钟 DS1302_Write_Byte(0x8E,0x80); // 打开写保护 } /*********************************************************/ // 从DS1302读出时间数据 /*********************************************************/ void DS1302_Read_Time() { uchar i; TimeBuff[0]=DS1302_Read_Byte(0x8D); // 年 TimeBuff[1]=DS1302_Read_Byte(0x89); // 月 TimeBuff[2]=DS1302_Read_Byte(0x87); // 日 TimeBuff[3]=DS1302_Read_Byte(0x8B); // 星期 TimeBuff[4]=DS1302_Read_Byte(0x85); // 时 TimeBuff[5]=DS1302_Read_Byte(0x83); // 分 TimeBuff[6]=(DS1302_Read_Byte(0x81))&0x7F; // 秒 for(i=0;i<7;i++) // BCD转十进制 { TimeBuff[i]=(TimeBuff[i]/16)*10+TimeBuff[i]%16; } } /*********************************************************/ // ADC0832的时钟脉冲 /*********************************************************/ void WavePlus() { _nop_(); ADC_CLK = 1; _nop_(); ADC_CLK = 0; } /*********************************************************/ // 获取指定通道的A/D转换结果 /*********************************************************/ uchar Get_ADC0832() { uchar i; uchar dat1=0; uchar dat2=0; ADC_CLK = 0; // 电平初始化 ADC_DAT = 1; _nop_(); ADC_CS = 0; WavePlus(); // 起始信号 ADC_DAT = 1; WavePlus(); // 通道选择的第一位 ADC_DAT = 0; WavePlus(); // 通道选择的第二位 ADC_DAT = 1; for(i=0;i<8;i++) // 第一次读取 { dat1<<=1; WavePlus(); if(ADC_DAT) dat1=dat1|0x01; else dat1=dat1|0x00; } for(i=0;i<8;i++) // 第二次读取 { dat2>>= 1; if(ADC_DAT) dat2=dat2|0x80; else dat2=dat2|0x00; WavePlus(); } _nop_(); // 结束此次传输 ADC_DAT = 1; ADC_CLK = 1; ADC_CS = 1; if(dat1==dat2) // 返回采集结果 return dat1; else return 0; } uchar Get_ADC08322() { uchar i; uchar dat1=0; uchar dat2=0; ADC_CLK = 0; // 电平初始化 ADC_DAT = 1; _nop_(); ADC_CS = 0; WavePlus(); // 起始信号 ADC_DAT = 1; WavePlus(); // 通道选择的第一位 ADC_DAT = 1; WavePlus(); // 通道选择的第二位 ADC_DAT = 1; for(i=0;i<8;i++) // 第一次读取 { dat1<<=1; WavePlus(); if(ADC_DAT) dat1=dat1|0x01; else dat1=dat1|0x00; } for(i=0;i<8;i++) // 第二次读取 { dat2>>= 1; if(ADC_DAT) dat2=dat2|0x80; else dat2=dat2|0x00; WavePlus(); } _nop_(); // 结束此次传输 ADC_DAT = 1; ADC_CLK = 1; ADC_CS = 1; if(dat1==dat2) // 返回采集结果 return dat1; else return 0; } /*********************************************************/ unsigned char UART_data; //定义串口接收数据变量 /*********************************************************/ // 按键扫描(设置当前时间) /*********************************************************/ void KeyScanf1() { if(KeySet_P==0 || UART_data == 'b') { UART_data = 'z'; LcdGotoXY(0,13); // 显示秒钟的冒号 LcdWriteData(':'); DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 LcdGotoXY(0,6); // 定位光标到月份闪烁 LcdWriteCmd(0x0f); // 启动光标闪烁 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整月份 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(TimeBuff[1]>1) // 判断月份是否大于1 TimeBuff[1]--; // 是的话就减去1 LcdGotoXY(0,5); // 光标定位到月份的位置 LcdPrintNum(TimeBuff[1]); // 刷新显示改变后的月份 LcdGotoXY(0,6); // 定位光标到月份闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(TimeBuff[1]<12) // 判断月份是否小于12 TimeBuff[1]++; // 是的话就加上1 LcdGotoXY(0,5); // 光标定位到月份的位置 LcdPrintNum(TimeBuff[1]); // 刷新显示改变后的月份 LcdGotoXY(0,6); // 定位光标到月份闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeySet_P==0 || UART_data =='b') { UART_data = 'z'; break; } } LcdGotoXY(0,9); // 定位光标到日期闪烁 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整日期 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(TimeBuff[2]>1) // 判断日期是否大于1 TimeBuff[2]--; // 是的话就减去1 LcdGotoXY(0,8); // 光标定位到日期的位置 LcdPrintNum(TimeBuff[2]); // 刷新显示改变后的日期 LcdGotoXY(0,9); // 定位光标到日期闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(TimeBuff[2]<31) // 判断日期是否小于31 TimeBuff[2]++; // 是的话就加上1 LcdGotoXY(0,8); // 光标定位到日期的位置 LcdPrintNum(TimeBuff[2]); // 刷新显示改变后的日期 LcdGotoXY(0,9); // 定位光标到日期闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeySet_P==0 || UART_data == 'b') { UART_data = 'z'; break; } } LcdGotoXY(0,12); // 定位光标到小时闪烁 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整小时 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(TimeBuff[4]>0) // 判断小时是否大于0 TimeBuff[4]--; // 是的话就减去1 LcdGotoXY(0,11); // 光标定位到小时的位置 LcdPrintNum(TimeBuff[4]); // 刷新显示改变后的小时 LcdGotoXY(0,12); // 定位光标到小时闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(TimeBuff[4]<23) // 判断小时是否小于23 TimeBuff[4]++; // 是的话就加上1 LcdGotoXY(0,11); // 光标定位到小时的位置 LcdPrintNum(TimeBuff[4]); // 刷新显示改变后的小时 LcdGotoXY(0,12); // 定位光标到小时闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeySet_P==0 || UART_data == 'b') { UART_data = 'z'; break; } } LcdGotoXY(0,15); // 定位光标到分钟闪烁 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整分钟 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(TimeBuff[5]>0) // 判断分钟是否大于0 TimeBuff[5]--; // 是的话就减去1 LcdGotoXY(0,14); // 光标定位到分钟的位置 LcdPrintNum(TimeBuff[5]); // 刷新显示改变后的分钟 LcdGotoXY(0,15); // 定位光标到分钟闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(TimeBuff[5]<59) // 判断分钟是否小于59 TimeBuff[5]++; // 是的话就加上1 LcdGotoXY(0,14); // 光标定位到分钟的位置 LcdPrintNum(TimeBuff[5]); // 刷新显示改变后的分钟 LcdGotoXY(0,15); // 定位光标到分钟闪烁 DelayMs(300); // 延时0.3秒左右 } if(KeySet_P==0 || UART_data == 'b') { UART_data = 'z'; break; } } /* 退出前的设置 */ LcdWriteCmd(0x0C); // 关闭光标闪烁 DS1302_Write_Time(); // 把新设置的时间值存入DS1302芯片 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 } } uint temp,mm;uchar i;float f_temp; /******************************************************* 温度函数 *******************************************************/ void dsreset(void) //下边是温度获取子程衼E { uint i; ds=0; i=103; while(i>0)i--; ds=1; i=4; while(i>0)i--; } bit tempreadbit(void) //读一位 { uint i; bit dat; ds=0;i++; ds=1;i++;i++; dat=ds; i=8;while(i>0)i--; return(dat); } uchar tempread(void) //获取温度 { uchar i,j,dat; dat=0; for(i=1;i<=8;i++) { j=tempreadbit(); dat=(j<<7)|(dat>>1); } return(dat); } void tempwritebyte(uchar dat) //写一个字节 { uint i; uchar j; bit testb; for(j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if(testb) { ds=0; ds=1; i=8;while(i>0)i--; } else { ds=0; i=8;while(i>0)i--; ds=1; i++;i++; } } } void tempchange(void) //温度转换 { dsreset(); delay(1); tempwritebyte(0x44); } uint get_temp() //获取温度 { uchar a,b; dsreset(); delay(1); tempwritebyte(0xcc); tempwritebyte(0xbe); a=tempread(); b=tempread(); temp=b; temp<<=8; temp=temp|a; f_temp=temp*0.0625; temp=f_temp*10+0.5; f_temp=f_temp+0.05; return temp; } /***********************************/ /*********************************************************/ // 按键扫描(设置水泵的动作) /*********************************************************/ void KeyScanf2() { if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; LcdGotoXY(0,0); // 光标定位 LcdPrintStr(" OpenTime : "); // 显示第1行内容 LcdGotoXY(1,0); // 光标定位 LcdPrintStr("CloseTime : "); // 显示第2行内容 LcdGotoXY(0,10); // 光标定位 LcdPrintNum(OpenHour); // 显示开启水泵的小时 LcdGotoXY(0,13); // 光标定位 LcdPrintNum(OpenMinute); // 显示开启水泵的分钟 LcdGotoXY(1,10); // 光标定位 LcdPrintNum(CloseHour); // 显示关闭水泵的小时 LcdGotoXY(1,13); // 光标定位 LcdPrintNum(CloseMinute); // 显示关闭水泵的分钟 LcdWriteCmd(0x0f); // 启动光标闪烁 LcdGotoXY(0,11); // 定位光标 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整开启的小时 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data ='z'; if(OpenHour>0) // 判断小时是否大于0 OpenHour--; // 是的话就减去1 LcdGotoXY(0,10); // 光标定位 LcdPrintNum(OpenHour); // 刷新显示改变后的小时 LcdGotoXY(0,11); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(OpenHour<23) // 判断小时是否小于23 OpenHour++; // 是的话就加上1 LcdGotoXY(0,10); // 光标定位 LcdPrintNum(OpenHour); // 刷新显示改变后的小时 LcdGotoXY(0,11); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; break; } } LcdGotoXY(0,14); // 定位光标 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整开启的分钟 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(OpenMinute>0) // 判断分钟是否大于0 OpenMinute--; // 是的话就减去1 LcdGotoXY(0,13); // 光标定位 LcdPrintNum(OpenMinute); // 刷新显示改变后的分钟 LcdGotoXY(0,14); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(OpenMinute<59) // 判断分钟是否小于59 OpenMinute++; // 是的话就加上1 LcdGotoXY(0,13); // 光标定位 LcdPrintNum(OpenMinute); // 刷新显示改变后的分钟 LcdGotoXY(0,14); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; break; } } LcdGotoXY(1,11); // 定位光标 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整关闭的小时 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(CloseHour>0) // 判断小时是否大于0 CloseHour--; // 是的话就减去1 LcdGotoXY(1,10); // 光标定位 LcdPrintNum(CloseHour); // 刷新显示改变后的小时 LcdGotoXY(1,11); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(CloseHour<23) // 判断小时是否小于23 CloseHour++; // 是的话就加上1 LcdGotoXY(1,10); // 光标定位 LcdPrintNum(CloseHour); // 刷新显示改变后的小时 LcdGotoXY(1,11); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; break; } } LcdGotoXY(1,14); // 定位光标 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 调整关闭的分钟 */ while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(CloseMinute>0) // 判断分钟是否大于0 CloseMinute--; // 是的话就减去1 LcdGotoXY(1,13); // 光标定位 LcdPrintNum(CloseMinute); // 刷新显示改变后的分钟 LcdGotoXY(1,14); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(CloseMinute<59) // 判断分钟是否小于59 CloseMinute++; // 是的话就加上1 LcdGotoXY(1,13); // 光标定位 LcdPrintNum(CloseMinute); // 刷新显示改变后的分钟 LcdGotoXY(1,14); // 定位光标 DelayMs(300); // 延时0.3秒左右 } if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; break; } } DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 /* 光照强度的设置 */ LcdWriteCmd(0x0C); // 关闭光标闪烁 LcdGotoXY(0,0); // 光标定位 LcdPrintStr(" Light Set "); // 显示第1行内容 LcdGotoXY(1,0); // 光标定位 LcdPrintStr(" "); // 显示第2行内容 LcdGotoXY(1,7); // 光标定位 LcdPrintNum(gLight); // 显示水泵的光线控制强度阈值 while(1) { if(KeyDown_P==0 || UART_data == 'd') // 如果减按键被下去 { UART_data = 'z'; if(gLight>0) // 判断光线阈值是否大于0 gLight--; // 是的话就减去1 LcdGotoXY(1,7); // 光标定位 LcdPrintNum(gLight); // 刷新显示改变后的光线阈值 DelayMs(300); // 延时0.3秒左右 } if(KeyUp_P==0 || UART_data == 'e') // 如果加按键被下去 { UART_data = 'z'; if(gLight<99) // 判断光线阈值是否小于59 gLight++; // 是的话就加上1 LcdGotoXY(1,7); // 光标定位 LcdPrintNum(gLight); // 刷新显示改变后的光线阈值 DelayMs(300); // 延时0.3秒左右 } if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; break; } } DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 // 设置温度 LcdWriteCmd(0x0C); // 关闭光眮E了? LcdGotoXY(0,0); // 光眮Eㄎ? LcdPrintStr(" Wendu Set "); // 显示第1行内容 LcdGotoXY(1,0); // 光眮Eㄎ? LcdPrintStr(" "); // 显示第2行内容 LcdGotoXY(1,7); // 光眮Eㄎ? LcdPrintNum(wDu); // 显示水泵的光线控制强度阈值 while(1){ LcdGotoXY(1,7); // 光眮Eㄎ? LcdPrintNum(wDu); // 显示水泵的光线控制强度阈值 if(KeyDown_P==0 || UART_data == 'd') // 如果减按紒E幌氯? { UART_data = 'z'; if(wDu>0) // 判断光线阈值是否大于0 wDu--; // 是的话就减去1 DelayMs(300); // 延时0.3脕E笥? } if(KeyUp_P==0 || UART_data == 'e') // 如果加按紒E幌氯? { UART_data = 'z'; if(wDu<99) // 判断光线阈值是否小于59 wDu++; // 是的话就加上1 DelayMs(300); // 延时0.3脕E笥? } if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; break; } } DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 // 设置湿度 LcdWriteCmd(0x0C); // 关闭光眮E了? LcdGotoXY(0,0); // 光眮Eㄎ? LcdPrintStr(" Shidu Set "); // 显示第1行内容 LcdGotoXY(1,0); // 光眮Eㄎ? LcdPrintStr(" "); // 显示第2行内容 LcdGotoXY(1,7); // 光眮Eㄎ? LcdPrintNum(X_sd); // 显示水泵的光线控制强度阈值 while(1){ LcdGotoXY(1,7); // 光眮Eㄎ? LcdPrintNum(X_sd); // 显示水泵的光线控制强度阈值 if(KeyDown_P==0 || UART_data == 'd') // 如果减按紒E幌氯? { UART_data = 'z'; if(X_sd>0) // 判断光线阈值是否大于0 X_sd--; // 是的话就减去1 DelayMs(300); // 延时0.3脕E笥? } if(KeyUp_P==0 || UART_data == 'e') // 如果加按紒E幌氯? { UART_data = 'z'; if(X_sd<99) // 判断光线阈值是否小于59 X_sd++; // 是的话就加上1 DelayMs(300); // 延时0.3脕E笥? } if(KeySet2_P==0 || UART_data == 'c') { UART_data = 'z'; break; } } /* 退出前的设置 */ LcdShowInit(); // 液晶显示内容初始化 DelayMs(10); // 延时等待,消除按键按下的抖动 while(!KeySet2_P); // 等待按键释放 DelayMs(10); // 延时等待,消除按键松开的抖动 } } /*********************************************************/ // 按键扫描(模式切换) /*********************************************************/ void KeyScanf3() { if(KeyMode_P==0 || UART_data == 'a') { UART_data = 'z'; gMode++; // 切换到下一模式 if(gMode==3) // 如果到尽头了 gMode=1; // 回到第一种模式 LcdGotoXY(1,0); // 光标定位 LcdPrintMode(gMode); // 显示模式 DelayMs(10); // 去除按键按下的抖动 while(!KeyMode_P); // 等待按键是否 DelayMs(10); // 去除按键松开的抖动 Led_P=1; bjflag=0; } } /*********************************************************/ // 开窗 /*********************************************************/ void Open() { Led_P=0; bjflag=1; } /*********************************************************/ // 关窗 /*********************************************************/ void Close() { Led_P=1; bjflag=0; } /*********************************************************/ // 主函数 /*********************************************************/ void main() { uchar light; uchar sd; LcdInit(); // 执行液晶初始化 DS1302_Init(); // 时钟芯片的初始化 LcdShowInit(); // 液晶显示内容的初始化 TMOD=0x21;//定时器0 模式1 16位定时模式 EA=1; //开启总中断 ES = 1; //允许UART串口的中断 PCON = 0x80; //波特率倍频(屏蔽本句波特率为2400) SCON = 0x50; //串口工作方式1,允许串口接收(SCON = 0x40 时禁止串口接收) TH1 = 0xFa; //定时器初值高8位设置 //12MHZ晶振,波特率为4800 0xf3 TL1 = 0xFa; //定时器初值低8位设置 //11.0592MHZ晶振,波特率为4800 0xf4 9600 0xfa 19200 0xfd TR1=1; if(DS1302_Read_Byte(0x81)>=128) // 判断时钟芯片是否正在运行 { DS1302_Write_Time(); // 如果没有,则初始化一个时间 } while(1) { tempchange(); t=get_temp(); if(t>=0&&t<=1250) //温度合法范围,不在这个范围就是没有获取到合适的值 { wd=t/10; } DS1302_Read_Time(); // 获取当前时钟芯片的时间,存在数组time_buf中 FlashTime(); // 刷新时间显示 light=Get_ADC08322(); // 读取光照强度 sd=Get_ADC0832(); sd=sd/2.5; light=light/2.5; // 缩小光照检测结果(在0-99) if(light>99) // 如果大于99 light=99; // 则依然保持99 LcdGotoXY(1,14); // 光标定位 LcdPrintNum(light); // 显示光照强度 LcdGotoXY(1,9); // 光标定位 LcdPrintNum(sd); // 显示湿度 KeyScanf1(); // 按键扫描(时间的设置) KeyScanf2(); // 按键扫描(阈值的设置) KeyScanf3(); // 按键扫描(模式切换) /*土壤湿度控制模式*/ if(gMode==1) { if(sd<X_sd) //湿度小于阈值开启 Open(); else Close(); } /*时间控制模式*/ if(gMode==2) { if((TimeBuff[4]==CloseHour)&&(TimeBuff[5]==CloseMinute)&&(TimeBuff[6]==0)) // 如果到了关的时间 { Close(); } if((TimeBuff[4]==OpenHour)&&(TimeBuff[5]==OpenMinute)&&(TimeBuff[6]==0)) // 如果到了开的时间 { Open(); } } if(light<gLight) // 当前光线小于设置的阈值 { led2=0;//开灯 }else{ led2=1; } if(wd<wDu || light<gLight) // 当前温度小于设置的阈值 { bjflag=1; }else{ bjflag=0; } if(bjflag==1){ bjcount++; if(bjcount>5){ bjcount=0; fm=0;DelayMs(100);DelayMs(100);fm=1; } }else{ fm=1; } DelayMs(100); // 延时0.1秒 } } void UART_R ( ) interrupt 4 using 1 //切换寄存器组到1 { RI = 0; //令接收中断标志位为0(软件清零) UART_data = SBUF; //将接收到的数据送入变量 UART_data }
五,相关作品展示
基于Java开发、Python开发、PHP开发、C#开发等相关语言开发的实战项目
基于Nodejs、Vue等前端技术开发的前端实战项目
基于微信小程序和安卓APP应用开发的相关作品
基于51单片机等嵌入式物联网开发应用
基于各类算法实现的AI智能应用
基于大数据实现的各类数据管理和推荐系统
编辑
编辑编辑
编辑
编辑编辑
编辑
编辑