功能:
0.本系统采用STC89C52作为单片机
1.LCD1602液晶实时显示水位、水质百分比
2.按键设置水位水质阈值并通过液晶显示
3.具备4个LED分别作为水位水质的上下限指示灯
4.具备声光报警功能
5.设置的阈值数据掉电不丢失
6.两组继电器可外接进水和出水设备,当水位超过上下限时对应的继电器会切换状态
7.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include <stdio.h>
#include <reg52.h>
#include "tlc0832.h"
#include "lcd1602.h"
#include "eepom52.h"
#include "delay.h"
sbit KEY_ENTER = P3^5; //自动手动模式切换按键
sbit KEY_SET = P3^3; //设置按键
sbit KEY_ADD = P3^4; //加按键
sbit KEY_SUB = P3^6; //减按键
sbit LED_WATER_DEPTH_UP = P1^3; //水位上限指示灯
sbit LED_WATER_DEPTH_LOW = P1^4; //水位下限指示灯
sbit LED_WATER_QUALITY_UP = P1^5; //水质上限指示灯
sbit LED_WATER_QUALITY_LOW = P1^6; //水质上限指示灯
sbit BUZZER = P2^2; //蜂鸣器
sbit RELAY1 = P2^0; //继电器1 进水
sbit RELAY2 = P2^1; //继电器2 出水
void UpdataWaterValue(); //更新当前水深到LCD1602
void UpdataMinMaxWaterValue(); //更新最大最小水深到LCD1602
void UpdateEEPROM(); //更新eeprom存储的数据
void InitEEPROM(); //初始化eeprom
void Check(); //水位检测比较报警函数
bit refreshFlag = 1;
unsigned char curWaterDepth = 0; //当前水深
unsigned char maxWaterDepth = 70; //最大水深
unsigned char minWaterDepth = 0; //最小水深
unsigned char setFlag = 0; //设置按键标志位
bit alarmFlag = 0; //报警标志位
unsigned char curWaterQuality = 0; //当前水质
unsigned char maxWaterQuality = 70; //最大浊度
unsigned char minWaterQuality = 0; //最小浊度
void KeyScan(void)
{
if (KEY_SET == 0) //设置按键按下
{
DelayMs(2);
if (KEY_SET == 0)
{
setFlag++;
if (setFlag >= 5)
{
setFlag = 1;
}
switch(setFlag)
{
case 0: LCD_DispOneChar( 5, 0, ' ' ); LCD_DispOneChar( 11, 0, ' ' ); LCD_DispOneChar( 5, 1, ' ' ); LCD_DispOneChar( 11, 1, ' ' ); break;
case 1: LCD_DispOneChar( 5, 0, '>' ); LCD_DispOneChar( 11, 0, ' ' ); LCD_DispOneChar( 5, 1, ' ' ); LCD_DispOneChar( 11, 1, ' ' ); break;
case 2: LCD_DispOneChar( 5, 0, ' ' ); LCD_DispOneChar( 11, 0, '>' ); LCD_DispOneChar( 5, 1, ' ' ); LCD_DispOneChar( 11, 1, ' ' ); break;
case 3: LCD_DispOneChar( 5, 0, ' ' ); LCD_DispOneChar( 11, 0, ' ' ); LCD_DispOneChar( 5, 1, '>' ); LCD_DispOneChar( 11, 1, ' ' ); break;
case 4: LCD_DispOneChar( 5, 0, ' ' ); LCD_DispOneChar( 11, 0, ' ' ); LCD_DispOneChar( 5, 1, ' ' ); LCD_DispOneChar( 11, 1, '>' ); break;
}
while (KEY_SET == 0);
UpdateEEPROM();
}
}
if (KEY_ADD == 0 && setFlag != 0) //加键按下
{
DelayMs(180);
if (KEY_ADD == 0 && setFlag != 0)
{
switch (setFlag)
{
case 0:
break;
case 1:
if (maxWaterDepth < 100)
maxWaterDepth++;
break;
case 2:
if (minWaterDepth < maxWaterDepth)
minWaterDepth++;
break;
case 3:
if (maxWaterQuality < 100)
maxWaterQuality++;
break;
case 4:
if (minWaterQuality < maxWaterQuality)
minWaterQuality++;
break;
}
UpdataMinMaxWaterValue();
//while (KEY_ADD == 0);
UpdateEEPROM();
}
}
if (KEY_SUB == 0 && setFlag != 0) //减键按下
{
DelayMs(180);
if (KEY_SUB == 0 && setFlag != 0)
{
switch (setFlag)
{
case 0:
break;
case 1:
if (maxWaterDepth > minWaterDepth)
maxWaterDepth--;
break;
case 2:
if (minWaterDepth > 0)
minWaterDepth--;
break;
case 3:
if (maxWaterQuality > minWaterQuality)
maxWaterQuality--;
break;
case 4:
if (minWaterQuality > 0)
minWaterQuality--;
break;
}
UpdataMinMaxWaterValue();
//while (KEY_SUB == 0);
UpdateEEPROM();
}
}
if (KEY_ENTER == 0) //确认键按下
{
DelayMs(2);
if (KEY_ENTER == 0)
{
setFlag = 6;
LCD_DispOneChar(5, 0, ' ');
LCD_DispOneChar(11, 0, ' ');
LCD_DispOneChar(5, 1, ' ');
LCD_DispOneChar(11, 1, ' ');
while (KEY_ENTER == 0)
;
}
}
}
/************************* 定时器0初始化 *************************/
void Timer0_Init(void)
{
TMOD &= 0xF0;
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH0 = (65536 - 9216) / 256; //重新赋值 10ms
TL0 = (65536 - 9216) % 256;
EA = 1; //总中断打开
ET0 = 1; //定时器中断打开
TR0 = 1; //定时器计数打开
// PT0 = 1; //高优先级
}
//主函数
void main()
{
Timer0_Init();
InitEEPROM(); //初始化eeprom
LCD_Init(); //初始化1602
LCD_Clear();
LCD_DispStr(0, 0, "W: H: L: ");
LCD_DispStr(0, 1, "Z: H: L: ");
UpdataWaterValue(); //更新当前水深到LCD1602
UpdataMinMaxWaterValue(); //更新最大最小水深到LCD1602
BUZZER = 1; //关闭蜂鸣器
LED_WATER_DEPTH_UP = 1;
LED_WATER_DEPTH_LOW = 1;
while (1)
{
if (refreshFlag == 1)
{
refreshFlag = 0;
UpdataWaterValue();
UpdataMinMaxWaterValue();
Check(); //水位检测比较报警函数
}
KeyScan();
}
}
//更新当前水深到LCD1602
void UpdataWaterValue()
{
unsigned char lcd1602_data[4] = {0};
curWaterDepth = ReadADC(AIN1_GND);
curWaterDepth = curWaterDepth * 100 / 255;
if (curWaterDepth > 99)
{
curWaterDepth = 99;
}
lcd1602_data[0] = curWaterDepth % 100 / 10 + 48;
lcd1602_data[1] = curWaterDepth % 10 + 48;
LCD_DispStr(2, 0, lcd1602_data);
DelayMs(10);
curWaterQuality = ReadADC(AIN0_GND);
curWaterQuality = 100 * (255 - curWaterQuality) / 255;
if (curWaterQuality > 99)
{
curWaterQuality = 99;
}
lcd1602_data[0] = curWaterQuality % 100 / 10 + 48;
lcd1602_data[1] = curWaterQuality % 10 + 48;
LCD_DispStr(2, 1, lcd1602_data);
DelayMs(10);
}
//更新最大最小水深到LCD1602
void UpdataMinMaxWaterValue()
{
unsigned char lcd1602_data[4] = {0};
if (maxWaterDepth > 99)
{
maxWaterDepth = 99;
}
lcd1602_data[0] = maxWaterDepth % 100 / 10 + 48;
lcd1602_data[1] = maxWaterDepth % 10 + 48;
LCD_DispStr(8, 0, lcd1602_data);
if (minWaterDepth > 99)
{
minWaterDepth = 99;
}
lcd1602_data[0] = minWaterDepth % 100 / 10 + 48;
lcd1602_data[1] = minWaterDepth % 10 + 48;
LCD_DispStr(14, 0, lcd1602_data);
if (maxWaterQuality > 99)
{
maxWaterQuality = 99;
}
lcd1602_data[0] = maxWaterQuality % 100 / 10 + 48;
lcd1602_data[1] = maxWaterQuality % 10 + 48;
LCD_DispStr(8, 1, lcd1602_data);
if (minWaterQuality > 99)
{
minWaterQuality = 99;
}
lcd1602_data[0] = minWaterQuality % 100 / 10 + 48;
lcd1602_data[1] = minWaterQuality % 10 + 48;
LCD_DispStr(14, 1, lcd1602_data);
}
//初始化eeprom
void InitEEPROM()
{
unsigned char is_first_init = ReadByte(0x2020);
if (is_first_init == 1)
{
maxWaterDepth = ReadByte(0x2000);
minWaterDepth = ReadByte(0x2001);
maxWaterQuality = ReadByte(0x2002);
minWaterQuality = ReadByte(0x2003);
}
else
{
EraseSector(0x2000);
WriteByte(0x2000, maxWaterDepth);
WriteByte(0x2001, minWaterDepth);
WriteByte(0x2002, maxWaterQuality);
WriteByte(0x2003, minWaterQuality);
WriteByte(0x2020, 1);
}
}
//更新eeprom存储的数据
void UpdateEEPROM()
{
EraseSector(0x2000);
WriteByte(0x2000, maxWaterDepth);
WriteByte(0x2001, minWaterDepth);
WriteByte(0x2002, maxWaterQuality);
WriteByte(0x2003, minWaterQuality);
WriteByte(0x2020, 1);
}
//水位检测比较报警函数
void Check()
{
if( curWaterDepth < minWaterDepth || curWaterDepth > maxWaterDepth || curWaterQuality > maxWaterQuality || curWaterQuality < minWaterQuality )
{
alarmFlag = 1;
}
else
{
alarmFlag = 0;
}
if(curWaterDepth < minWaterDepth)
{
LED_WATER_DEPTH_UP = 1;
LED_WATER_DEPTH_LOW = 0;
}
else if(curWaterDepth > maxWaterDepth)
{
LED_WATER_DEPTH_UP = 0;
LED_WATER_DEPTH_LOW = 1;
}
else
{
LED_WATER_DEPTH_UP = 1;
LED_WATER_DEPTH_LOW = 1;
}
if(curWaterQuality < minWaterQuality)
{
LED_WATER_QUALITY_UP = 1;
LED_WATER_QUALITY_LOW = 0;
}
else if(curWaterQuality > maxWaterQuality)
{
LED_WATER_QUALITY_UP = 0;
LED_WATER_QUALITY_LOW = 1;
}
else
{
LED_WATER_QUALITY_UP = 1;
LED_WATER_QUALITY_LOW = 1;
}
if(curWaterDepth < minWaterDepth)
{
RELAY1 = 0;
RELAY2 = 1;
}
else if(curWaterDepth >= maxWaterDepth)
{
RELAY2 = 0;
RELAY1 = 1;
}
else
{
RELAY2 = 1;
RELAY1 = 1;
}
}
/************************* 定时器0中断处理 *************************/
void Timer0_Interrupt(void) interrupt 1
{
static unsigned int time10ms = 0;
TH0 = (65536 - 9216) / 256; //重新赋值 10ms
TL0 = (65536 - 9216) % 256;
time10ms++;
if (time10ms > 50)
{
time10ms = 0;
refreshFlag = 1; //刷新标志
if (alarmFlag == 1)
{
BUZZER = !BUZZER;
}
else
{
BUZZER = 1;
}
}
}