(末尾附文件)
3.1系统的功能分析及体系结构设计
3.1.1系统功能分析
本设计由STC89C52单片机电路+4位共阳数码管显示电路+ADC0832采样电路+水泵控制电路+土壤湿度传感器电路+按键电路+电源电路组成。
1、数码管实时显示土壤湿度传感器测到的湿度。
2、按键说明:从左边第一个起,减键、加键、设置键。可以用按键设置,设置湿度的上、下限值,并具有掉电保存,保存在单片机的内部,上电无需重新设置。
3、当湿低于下限值时,自动打开水泵进行抽水自动灌溉,当湿高于上限值时,断开水泵停止灌溉,
4、当湿度处于上下限之间时处于,手动模式,按减键手动打开水泵,可以按加键手动关闭水泵。
3.1.2系统总体结构
本系统具体框图如下图所示:
水泵控制电路设计
微型水泵(wēi xīn shuǐ bèng,microwater pump或mini water pump)定义:通常把提升液体、输送液体或使液体增加压力,即把原动机的机械能变为液体能量从而达到抽送液体目的的机器统称为水泵。水泵一般组成形式为驱动部分+泵体,泵体上有一进一出两个接口,水从入水口进,排水口出,凡是采用这种形式,且体积小巧、袖珍的水泵,都叫微型水泵,也叫微型抽水泵。
在本系统中,使用5V水泵,用来喷水,由于水泵属于大功率装置,单片机无法直接驱动,故选择三极管9012来实现对水泵的控制,在本电路中通过LED灯来指示水泵是否工作,如果水泵工作,则LED灯亮,否则,LED灯不亮。与LED灯串联的电阻为限流电阻,限流作用,以保护LED灯,防止烧坏。当单片机的相关控制引脚为低电平时,三极管导通,水泵正常工作;否则,水泵不工作。电解电容作用是滤波,来滤除水泵供电电源中的低频参量,让水泵更稳定的工作。
TRSD土壤湿度传感器模块电路设计
在本设计中选择土壤湿度传感器来检测土壤的湿度,通过电位器调节土壤湿度控制阀值,可以自动对菜园、花园以及花盆土壤湿度进行检测控制,从而实现自动浇水。
本土壤湿度传感器表面采用镀镍处理,有加宽传感器感应面积、提高导电性能、防止接触土壤使传感器容易生锈、延长传感器使用寿命等作用。
一、接线说明(3线制)
(1)VCC 外接3.3V-5V
(2)GND 外接GND
(3)DO 小板数字量输出接口(0和1)
(4)AO 小板电压模拟量输出
二、模块使用说明:
(1)本传感器适用于土壤的湿度检测;
(2)本传感器可以宽范围控制土壤的湿度,通过电位器调节控制相应阀值,湿度低于设定值时,DO输出高电平;高于设定值时,DO输出低电平。数字量输出DO可以与单片机直接相连,哦通过单片机来检测高低电平,由此来检测土壤湿度。模块中蓝色的电位器是用于土壤湿度的阀值调节,顺时针调节,控制的湿度会越大,逆时针越小。
(3)模块也有模拟接口,可以检测出土壤湿度的模拟信号。传感器的模拟量输出接口AO引脚可以与AD模块相连,通过AD转换,可以获得更精确的土壤湿度数值。
土壤湿度传感器模块内部电路图如下图所示,其中R1电阻为分压电阻,将土壤湿度传感器检测到的土壤湿度信息转化为模拟电压信号即AO,模拟量信号接入LM393比较器后,即可与LM393比较器芯片2号引脚所接的电位器分压后的模拟电压进行比较,进而得出DO数字信号(即高低电平信号)。C1、C2为滤波电容,C1电容对电源进行滤波,让电源输出更稳定。C2电容对模拟信号进行滤波,保证模拟信号输出的稳定性。R2、R3均为限流电阻,来保护LED灯,防止LED灯烧坏,LED灯均为低电平有效。R4为上拉电阻,上拉就是将不确定的信号通过一个电阻钳位在高电平,同时起限流作用。保证LM393比较器输出的高低电平信号在与单片机引脚连接时电平信号的读取更加稳定。
ADC0832A/D转换电路设计
ADC0832是美国国家半导体公司生产的一种 8 位分辨率、双通道 A/D 转换芯片。由于它体积小,兼容性强,性价比高而深受单片机爱好者及企业欢迎,
其目前已经有很高的普及率。学习并使用 ADC0832 可是使我们了解 A/D 转换器的原理,有助于我们单片机技术水平的提高。
一、ADC0832 具有以下特点:
(1)8 位分辨率;
(2)双通道 A/D 转换;
(3)输入输出电平与 TTL/CMOS 相兼容;
(4)5V 电源供电时输入电压在 0~5V 之间;
(5)工作频率为 250KHZ,转换时间为 32μS;
(6)一般功耗仅为 15mW;
(7)8P、14P—DIP(双列直插)、PICC 多种封装;
(8)商用级芯片温宽为0°C to +70°C,工业级芯片温宽为−40°C to +85°C;
ADC0832 为 8 位分辨率 A/D 转换芯片,其最高分辨可达 256 级,可以适应一般的模拟量转换要求。其内部电源输入与参考电压的复用,使得芯片的模拟电压输入在 0~5V 之间。芯片转换时间仅为 32μS,据有双数据输出可作为数据校验,以减少数据误差,转换速度快且稳定性能强。独立的芯片使能输入,使多器件挂接和处理器控制变的更加方便。通过 DI 数据输入端,可以轻易的实现通道功能的选择。再本设计中ADC0832的功能是将粉尘传感器输出的模拟信号转化为数字信号,然后将信号送入单片机进行处理,试验证明,本电路满足本设计要求。在本设计中,ADC0832选择模拟输入通道0即CH0作为信号的采集端口。
4位共阳数码管驱动电路设计
数码管,也称作辉光管,是一种可以显示数字和其他信息的电子设备。玻璃管中包括一个金属丝网制成的阳极和多个阴极。大部分数码管阴极的形状为数字。管中充以低压气体,通常大部分为氖加上一些汞和/或氩。给某一个阴极充电,数码管就会发出颜色光,视乎管内的气体而定,一般都是橙色或绿色。
led数码管(LED Segment Displays)由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表示。当数码管特定的段加上电压后,这些特定的段就会发亮,以形成我们眼睛看到的字样了。常用LED数码管显示的数字和字符是0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。本设计中选择4位共阳数码管来显示数据。4位共阳数码管一共12个引脚,4个位选,8个段选。1、2、3、4、5、7、10、11为段选,6、8、9、12为四个数码管的位选。每个位选通过三极管进行驱动,在本设计中,Q1-Q5三极管均为驱动电路。R3-R5均为限流电阻,保护三极管。当单片机控制位选的引脚为低电平时,则相关位的数码管可以亮,否则,相关位的数码管不亮。单片机控制段选的引脚通过高低电平的组合即可显示不同的数据信息。其具体电路原理图如下图所示。
#include //调用单片机头文件
#include "eeprom.h"
#define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
#define uint unsigned int //无符号整型 宏定义 变量范围0~65535
#include
//数码管段选定义 0 1 2 3 4 5 6 7 8 9
uchar code smg_du[]={0x14,0x77,0x4c,0x45,0x27,0x85,0x84,0x57,0x04,0x05,
// A B C D E F 不显示
0x06,0xa4,0x9c,0x64,0x8c,0x8e,0xff}; //断码
//数码管位选定义
sbit smg_we1 = P2^0; //数码管位选定义
sbit smg_we2 = P2^2;
sbit smg_we3 = P2^4;
sbit smg_we4 = P2^6;
uchar dis_smg[8] = {0x14,0x77,0x4c,0x45,0x27,0x85,0x84}; //数码管显示
sbit SCL=P1^2; //SCL定义为P1口的第3位脚,连接ADC0832SCL脚
sbit DO=P1^3; //DO定义为P1口的第4位脚,连接ADC0832DO脚
sbit CS=P1^0; //CS定义为P1口的第4位脚,连接ADC0832CS脚
uchar shidu; //湿度等级
uchar s_high = 70,s_low = 25; //湿度报警参数
sbit dianji = P3^5; //电机IO定义
/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i= 4)
i = 0;
P0 = 0xff; //消隐
smg_we_switch(i); //位选
P0 = dis_smg[i]; //段选
// delay_1ms(1);
}
/***********读数模转换数据********************************************************/
//请先了解ADC0832模数转换的串行协议,再来读本函数,主要是对应时序图来理解,本函数是模拟0832的串行协议进行的
// 1 1 0 通道
// 1 1 1 通道
unsigned char ad0832read(bit SGL,bit ODD)
{
unsigned char i=0,value=0,value1=0;
SCL=0;
DO=1;
CS=0; //开始
SCL=1; //第一个上升沿
SCL=0;
DO=SGL;
SCL=1; //第二个上升沿
SCL=0;
DO=ODD;
SCL=1; //第三个上升沿
SCL=0; //第三个下降沿
DO=1;
for(i=0;i<8;i++)
{
SCL=1;
SCL=0; //开始从第四个下降沿接收数据
value=value<<1;
if(DO)
value++;
}
for(i=0;i<8;i++)
{ //接收校验数据
value1>>=1;
if(DO)
value1+=0x80;
SCL=1;
SCL=0;
}
SCL=1;
DO=1;
CS=1;
if(value==value1) //与校验数据比较,正确就返回数据,否则返回0
return value;
return 0;
}
/********************独立按键程序*****************/
uchar key_can; //按键值
void key() //独立按键程序
{
static uchar key_new;
key_can = 20; //按键值还原
P1 |= 0xf0;
if((P1 & 0xf0) != 0xf0) //按键按下
{
delay_1ms(1); //按键消抖动
if(((P1 & 0xf0) != 0xf0) && (key_new == 1))
{ //确认是按键按下
key_new = 0;
switch(P1 & 0xf0)
{
case 0x70: key_can = 1; break; //得到k2键值
case 0xb0: key_can = 2; break; //得到k3键值
case 0xd0: key_can = 3; break; //得到k4键值
}
}
}
else
key_new = 1;
}
/****************按键处理显示函数***************/
void key_with()
{
if(menu_1 == 0)
{
if((shidu > s_low)&&(shidu < s_high))
{
if(key_can == 3) //手动打开电机
dianji = 0; //打开电机
if(key_can == 2)
dianji = 1; //关闭电机
}
}
if(key_can == 1) //设置键
{
menu_1 ++;
if(menu_1 >= 3)
{
menu_1 = 0;
}
}
if(menu_1 == 1) //设置湿度上限
{
if(key_can == 2)
{
s_high ++ ; //湿度上限值加1
if(s_high > 99)
s_high = 99;
}
if(key_can == 3)
{
s_high -- ; //湿度上限值减1
if(s_high <= s_low)
s_high = s_low + 1 ;
}
dis_smg[0] = smg_du[s_high % 10]; //取个位显示
dis_smg[1] = smg_du[s_high / 10 % 10]; //取十位显示
dis_smg[2] = 0xef;
dis_smg[3] = 0x26; //H 0010 0110
}
if(menu_1 == 2) //设置湿度下限
{
if(key_can == 2)
{
s_low ++ ; //湿度下限值加1
if(s_low >= s_high)
s_low = s_high - 1;
}
if(key_can == 3)
{
s_low --; //湿度下限值减1
if(s_low <= 1)
s_low = 1;
}
dis_smg[0] = smg_du[s_low % 10]; //取个位显示
dis_smg[1] = smg_du[s_low / 10 % 10]; //取十位显示
dis_smg[2] = 0xef;
dis_smg[3] = 0xBC; //L
}
}
/****************电机控制函数***************/
void dianji_kongzi()
{
static uchar value,value1;
if(shidu <= s_low)
{
value ++;
if(value >= 2)
{
value = 10;
dianji = 0; //关机电机
}
}
else
value = 0;
if(shidu >= s_high)
{
value1 ++;
if(value1 >= 2)
{
value1 = 10;
dianji = 1; //打开电机
}
}else
value1 = 0;
}
unsigned char initFlagData; //初始化数据存读取
/******************把数据保存到单片机内部eepom中******************/
void write_eeprom()
{
SectorErase(0x2000); //擦除整个扇区 注意整个扇区数据都擦出了
byte_write(0x2000, s_low ); //重新写入值
byte_write(0x2001, s_high );
byte_write(0x2055, initFlagData);
}
/******************把数据从单片机内部eepom中读出来*****************/
void read_eeprom()
{
s_low = byte_read(0x2000); //读取高字节
s_high = byte_read(0x2001); //读取低字节 并合并
initFlagData = byte_read(0x2055); //数据初始化读取
}
/**************开机初始化保存的数据*****************/
void init_eeprom()
{
read_eeprom(); //先读
if(initFlagData != 0x55) //新的单片机初始单片机内问eeprom 如果不是0x55重新写入
{
s_low = 25; //初始化参数
s_high = 70;
initFlagData = 0x55; //修改值
write_eeprom(); //保存数据
}
}
/***************主函数*****************/
void main()
{
delay_1ms(100);
init_eeprom(); //开机初始化保存的数据
P0 = P1 = P2 = P3 = 0xff; //初始化IO口
while(1)
{
key(); //独立按键程序
if(key_can < 10)
{
key_with(); //按键按下要执行的程序
write_eeprom();//把数据保存到单片机内部eepom中
}
flag_200ms ++;
if(flag_200ms >= 200)
{
flag_200ms = 0;
P0 = 0xff; //消隐
if(menu_1 == 0)
{
shidu = ad0832read(1,0); //读出湿度
shidu =99-shidu * 99 / 255;
dis_smg[0] = 0xff; //
dis_smg[1] = smg_du[shidu % 10]; //取湿度的个位显示
dis_smg[2] = smg_du[shidu / 10 % 10] ; //取湿度的十位显示
dis_smg[3] = 0XFF; //
dianji_kongzi(); //电机控制函数
}
}
display(); //数码管显示函数
delay_1ms(1);
}
}
.
链接:https://pan.baidu.com/s/1jp-8lyrN3A3UatBSeXCQnQ
提取码:jtno
.