采用STC89C52作为主控芯片,ADC0804采集模拟信号作为花园土壤湿度,DS18B20采集温度,LCD1602显示温湿度;
当温度低于下限值,启动水泵进行浇水;
当温度高于上限值,停止水泵。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
- #include<intrins.h>
- #include<stdio.h>
- #include "18b20.h"
- #include "delay.h"
- #include "key.h"
- #define uint unsigned int
- #define uchar unsigned char
- #define ZERO 4.5 //湿度传感器放空气中的电压值 对应湿度0%
- #define FULL 0.45 //湿度传感器放水中的电压值 对应湿度100%
- float k,b;//计算湿度用斜率
- sbit RS = P2^5; //定义LCD1602端口
- sbit RW = P2^6;
- sbit EN = P2^7;
- #define DataPort P0
- sbit CS = P2^0; //定义ADC0832端口
- sbit CLK = P2^1;
- sbit DIO = P2^2;
- sbit MOETOR = P3^6;//水泵控制端口
- #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
- float d; //实时湿度值
- int RH=50; //湿度上限
- int RL=20; //湿度下限
- unsigned char KeyValue; //返回按键值
- int temp;
- float temperature; //温度值
- char displaytemp[16];//定义显示区域临时存储数组
- /*------------------------------------------------
- 判忙函数
- ------------------------------------------------*/
- bit LCD_Check_Busy(void)
- {
- unsigned char LCD_Status;
- RS = 0;
- RW = 1;
- EN = 1;
- DelayMs(1);
- LCD_Status = P0;
- EN = 0;
- return LCD_Status;
- }
- /*------------------------------------------------
- 写入命令函数
- ------------------------------------------------*/
- void LCD_Write_Com(unsigned char com)
- {
- while((LCD_Check_Busy()&0x80)==0x80);
- RS = 0;
- RW = 0;
- EN = 0;
- P0 = com;
- EN = 1;
- DelayMs(1);
- EN = 0;
- }
- /*------------------------------------------------
- 写入数据函数
- ------------------------------------------------*/
- void LCD_Write_Data(unsigned char Data)
- {
- while((LCD_Check_Busy()&0x80)==0x80);
- RS = 1;
- RW = 0;
- EN = 0;
- P0 = Data;
- EN = 1;
- DelayMs(1);
- EN = 0;
- }
- /*------------------------------------------------
- 清屏函数
- ------------------------------------------------*/
- 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);
- DelayMs(5);
- //LCD_Write_Com(0x08); /*显示关闭*/
- LCD_Write_Com(0x01); /*显示清屏*/
- DelayMs(5);
- LCD_Write_Com(0x06); /*显示光标移动设置*/
- DelayMs(5);
- LCD_Write_Com(0x0C); /*显示开及光标设置*/
- DelayMs(5);
- }
-
- unsigned char Get_AD_Result() //读取AD值
- {
- uchar i,dat1=0,dat2=0;
- CS = 0;
- CLK = 0;
- DIO = 1; _nop_(); _nop_();
- CLK = 1; _nop_(); _nop_();
- CLK = 0;DIO = 1; _nop_(); _nop_();
- CLK = 1; _nop_(); _nop_();
- CLK = 0;DIO = 1; _nop_(); _nop_();
- CLK = 1;DIO = 1; _nop_(); _nop_();
- CLK = 0;DIO = 1; _nop_(); _nop_();
- for(i=0;i<8;i++)
- {
- CLK = 1; _nop_(); _nop_();
- CLK = 0; _nop_(); _nop_();
- dat1 = dat1 << 1 | DIO;
- }
- for(i=0;i<8;i++)
- {
- dat2 = dat2 << ((uchar)(DIO)<<i);
- CLK = 1; _nop_(); _nop_();
- CLK = 0; _nop_(); _nop_();
- }
- CS = 1;
- return dat1; //== dat2) ? dat1:0;
- }
- /*------------------------------------------------
- 主函数
- ------------------------------------------------*/
- void main(void)
- {
-
- LCD_Init();
- DelayMs(10);
- //Init_Timer0();
- MOETOR =0; //默认水泵关闭
- while (1)
- {
- KeyValue=KeyScan();
- if(KeyValue!=0)//如果有键按下
- {
- Keyprocessing(KeyValue); //键值处理
- }
-
- temp=ReadTemperature(); //读取温度值
- temperature=(float)temp*0.0625;
- sprintf(displaytemp,"T =%3.1f",temperature);//
- LCD_Write_String(0,0,displaytemp);// 显示温度值
- d = Get_AD_Result()*5/255; //计算电压值
- k = 100/(FULL-ZERO); //根据空气中和水中的电压值列函数y=kx+b 计算 k b
- b = 0-ZERO*k;
- d = k*d+b; //计算实际的湿度值
- if(d<0) d=0;
- if(d>100) d=100;
- //d = k*d+b;
- sprintf(displaytemp,"R =%3.1f",d);//
- LCD_Write_String(8,0,displaytemp);// 显示湿度
- sprintf(displaytemp,"RH=%2d",RH);//
- LCD_Write_String(0,1,displaytemp);// 显示湿度上限
- sprintf(displaytemp,"RL=%2d",RL);//
- LCD_Write_String(10,1,displaytemp);// 显示湿度下限
- if(d<RL) MOETOR =1; //低于下限 开水泵
- if(d>RH) MOETOR =0; //高于上限 关水泵
- DelayMs(300);
-
- }
- }
复制代码
所有资料51hei提供下载:
程序.zip
(138.29 KB, 下载次数: 87)
|