首页 > 分享 > 单片机毕业设计

单片机毕业设计

作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师

主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互助

收藏点赞不迷路  关注作者有好处

文末获取源码 

项目编号:BS-DPJ-006

一,环境介绍

语言环境:C

开发技术:51单片机

二,项目简介

随着时代的发展,电子控制技术在人们的生活中得到了广泛的应用。如何运用现代的电子技术,对农家菜园温度、湿度进行自动监测,并依据相关的数据进行相应的灌溉作业。这对于促进温室作物的增产、节省劳动力都是十分必要的。该系统包括单片机STC89C52,湿度传感器,温度传感器,按键,光照传感器,液晶显示屏,水泵,蓝牙和电源。该系统以STC89C52单片机为核心,以 AltiumDesigner 10为主要硬件,以 Keil为主要开发工具,以 C语言编写。论文首先对系统方案进行了整体的描述,并提出了硬件方面的设计,其中包括控制器的选择,温湿度检测模块的硬件选择,光照强度检测模块的选择,显示模块的选择,水泵灌溉模块的选择,蓝牙模块的设计。软件模块主要包括整个软件流程图、温湿度检测、光强检测等部分流程图,并采用单片机实现对电动机的控制,最后使用 C语言编写了相应的程序。

本系统是基于单片机的农家菜园自动灌溉控制系统设计,以51单片机作为控制核心,实现菜园自动灌溉及智能控制系统的设计,能够实现对土壤温湿度以及光照强度的检测,并且根据设置的阈值及时间进行自动检测与灌溉。具体来说,本文的研究内容如下:

(1)本论文的研究内容为:自动灌溉系统的设计,包括土壤湿度检测、土壤温度检测、光照强度检测、水泵灌溉、定时自动灌溉。LCD显示屏和蓝牙无线接入。本课题的研究内容包括:灌区自动控制系统总体方案设计、硬件电路设计、软件流程设计等。本论文是一项细致而有效的自动化控制工作。其终极目的是实现自动灌溉和智能化控制,可通过设定的温度、湿度和光照强度来自动监测和灌溉。

(2)首先,本文对农户菜园自动灌溉控制系统的整体结构进行了阐述,并提出了硬件方面的设计,其中包括控制器的选择,温湿度检测模块的硬件选择,光照强度检测模块的选择,显示模块的选择,水泵灌溉模块的选择,蓝牙模块的设计。软件模块主要包括整个软件流程图、温湿度检测、光强检测等部分流程图,并采用单片机实现对电动机的控制,最后使用 C语言编写了相应的程序。

(3)根据硬件设计方案,实现了农户菜园自动灌溉控制系统的实际生产,并按“先局部后整体”的原则,对控制器模块、温湿度检测模块、光照强度检测模块、显示模块、水泵灌溉模块和蓝牙模块进行模块测试,并对整个系统进行全面测试,并将有关数据进行记录。通过试验,实现了菜园的自动灌溉和智能控制,可以检测土壤的温度、湿度和光照,并根据设定的阈值和时间,自动检测和灌溉,保证了测量精度和精度。

三,系统展示

四,核心代码展示

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!='')

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智能应用

基于大数据实现的各类数据管理和推荐系统

 

 

相关知识

开题报告 基于单片机智能花卉浇水系统的设计电气工程专业
毕业论文
基于51单片机的新型“花疗”智能花卉养护机设计
毕业设计
市政广场花坛植物景观配置毕业设计.pdf
第七讲:7.物联网土壤湿度远程监控+自动花浇水
如何自制植物生长灯
花棚温湿度自控系统的设计与实现
海南大学教学实验室调整后明细表
花边彩带图片

网址: 单片机毕业设计 https://m.huajiangbk.com/newsview26425.html

所属分类:花卉
上一篇: 自动喷淋浇水系统在庭院花园中的应
下一篇: 水肥一体化智能灌溉系统,发展现代