功能介绍:
0.本系统采用STC89C52作为单片机
1.液晶实时显示当前检测到的温度/浊度/电导率/PH信息,同时蓝牙串口上报
2.系统实时监测水箱水位和水箱盖状态(假设水箱最大深度1m)
3.当浊度/电导率超过设定阈值时,启动水泵排水,直至低于最低水位,停止排水,并启动抽水,抽水至最高水位停止
4.当浊度/电导率/PH值超过设定范围,蜂鸣器报警
5.当水箱盖打开蜂鸣器报警
6.可通过蓝牙发送*CS#命令抽水,*PS#命令排水
7.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include "main.h"
/*******************变量定义*********************/
enum _MODE_DF_ dispMode;
bit modeFlag = AUTO; //模式标记
uchar setIndex = 0;
bit dispFlag = 0;
bit sendFlag = 0;
char dis[17];
float temperature; //温度
float distance = 0;//水位距离
int distance_H = 500;//水位上限
int distance_L = 50;//水位下限
float PH_Value = 0;//PH
int PH_Value_Max = 9;//PH上限
int PH_Value_Min = 6;//PH下限
int turbidity_Value = 0;//浊度
int turbidity_Value_Max = 20;//浊度上限
float TDS_Value = 0;//TDS
int TDS_Value_Max = 100;//TDS上限
bit drainFlag1 = 0; //排水标志1
bit drainFlag2 = 0; //排水标志2
bit drawFlag1 = 0; //抽水标志1
bit drawFlag2 = 0; //抽水标志2
bit buzzerFlag1 = 0; //蜂鸣器标志1
bit buzzerFlag2 = 0; //蜂鸣器标志2
bit buzzerFlag3 = 0; //蜂鸣器标志3
/********************************************************
函数名称:void mian()
函数作用:主函数
参数说明:
********************************************************/
void main()
{
TRIG = 0;
Timer0_Init();
Timer1_Init(); //初始化定时器0
UART_Init(); //初始化串口
LCD_Init(); //初始化液晶
DelayMs(200); //延时有助于稳定
LCD_DispStr(4, 0, "Welcome!");
DelayS(1);
LCD_Clear(); //清屏
while (1) //死循环
{
if (dispFlag == 1)
{
dispFlag = 0;
if (dispMode == NORMAL) //正常显示模式
{
Measuring(&distance);
DispNormal();
}
}
if (sendFlag == 1)
{
sendFlag = 0;
SendData();
}
if (turbidity_Value > turbidity_Value_Max || TDS_Value > TDS_Value_Max) //浊度超高或TDS超高
{
drainFlag1 = 1; //开启排水
buzzerFlag1 = 1; //蜂鸣器报警标志
}
else
{
buzzerFlag1 = 0; //蜂鸣器报警标志
}
if (PH_Value > PH_Value_Max || PH_Value < PH_Value_Min) //PH值超过设定
{
buzzerFlag2 = 1; //蜂鸣器报警标志
}
else
{
buzzerFlag2 = 0; //蜂鸣器报警标志
}
if (distance > (1050 - distance_L)) //达到水位下限 1050mm的是考虑超声波探头的盲区50mm
{
drainFlag1 = 0; //停止排水
drainFlag2 = 0; //停止排水
drawFlag1 = 1; //开启抽水
}
else if (distance < (1050 - distance_H)) //达到水位上限
{
drawFlag1 = 0; //停止抽水
drawFlag2 = 0; //停止抽水
}
if (LID == 1) //水箱盖打开
{
buzzerFlag3 = 1;
}
else
{
buzzerFlag3 = 0;
}
if (buzzerFlag1 || buzzerFlag2 || buzzerFlag3) //蜂鸣器报警
{
BUZZER = ON;
}
else
{
BUZZER = OFF;
}
if (drainFlag1 || drainFlag2) //排水
{
RELAY_DRAIN_WATER = ON;
}
else
{
RELAY_DRAIN_WATER = OFF;
}
if (drawFlag1 || drawFlag2) //抽水
{
RELAY_DRAW_WATER = ON;
}
else
{
RELAY_DRAW_WATER = OFF;
}
KeyProcess();
}
}
/************************* 定时器0初始化 *************************/
void Timer0_Init(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
// TH0 = (65536 - 9216) / 256; //重新赋值 10ms
// TL0 = (65536 - 9216) % 256;
TH0 = 0;
TL0 = 0;
EA = 1; //总中断打开
ET0 = 1; //定时器中断打开
TR0 = 0; //定时器开关打开
}
/************************* 定时器0中断 *************************/
void Timer0_Interrupt(void) interrupt 1
{
// static unsigned int time10ms = 0;
// TH0 = (65536 - 9216) / 256; //重新赋值 10ms
// TL0 = (65536 - 9216) % 256;
}
/************************* 定时器1初始化 *************************/
void Timer1_Init(void)
{
TMOD |= 0x10; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH1 = (65536 - 9216) / 256; //重新赋值 10ms
TL1 = (65536 - 9216) % 256;
EA = 1; //总中断打开
ET1 = 1; //定时器中断打开
TR1 = 1; //定时器开关打开
}
/************************* 定时器1中断 *************************/
void Timer1_Interrupt(void) interrupt 3
{
static unsigned int time10ms = 0;
TH1 = (65536 - 9216) / 256; //重新赋值 10ms
TL1 = (65536 - 9216) % 256;
time10ms++;
if (time10ms % 50 == 0)
{
dispFlag = 1; //显示标志
}
if (time10ms > 500)
{
time10ms = 0;
sendFlag = 1; //发送信息标志
}
}
/************************* 蓝牙串口发送数据 *************************/
void SendData(void)
{
sprintf(dis, "T:%5.1f'C PH:%2d\r\n", temperature, (int)PH_Value);
UART_SendStr(dis, 17); //发送数据
DelayMs(10);
sprintf(dis, "ZD:%2d%% TDS:%4d\r\n", turbidity_Value, (int)TDS_Value);
UART_SendStr(dis, 17); //发送数据
DelayMs(10);
sprintf(dis, "SW:%7.2fmm \r\n", (1050-distance));
UART_SendStr(dis, 17); //发送数据
}
/************************* 超声波测距 *************************/
void Measuring(float *distance)
{
static long cnt = 0; //定时器计数
TR1 = 0;
TRIG = 1; //启动一次模块 //不可以使用其他终端 容易造成死循环
DelayUs10x(1);
TRIG = 0;
while (!ECHO)
; //当RX为零时等待
TR0 = 1; //开启计数
while (ECHO)
; //当RX为1计数并等待
TR0 = 0;
cnt = (long)(TH0 * 256 + TL0);
TH0 = 0;
TL0 = 0;
*distance = (float)cnt * 17 / 100.0 * 1.102; //算出来是mm (g_cnt * 340 / 2) / 1000.0 * 1.102;系数
cnt = 0;
TR1 = 1;
if (*distance > 1050)
{
*distance = 1050;
}
// sprintf(dis, " %7.2fmm ", *distance);
// LCD_DispStr(0, 1, dis);
}
/************************* 正常显示模式 *************************/
void DispNormal(void)
{
static char cnt = 0;
int tempBuf;
/************************* 18b20数据读取显示 *************************/
DS18B20_Start();
DS18B20_GetTemp(&tempBuf);
temperature = tempBuf * 0.0625;
sprintf(dis, "T:%5.1f", temperature);
LCD_DispStr(0, 0, dis);
LCD_DispOneChar(7, 0, 0xdf);
LCD_DispOneChar(8, 0, 'C');
/************************* PH读取显示 *************************/
PH_Value = 5 * (float)ReadADC_1(AIN0_GND) / 255; //读取PH
PH_Value = -5.7541 * PH_Value + 16.654;
if (PH_Value < 0)
{
PH_Value = 0;
}
sprintf(dis, " PH:%2d", (int)PH_Value);
LCD_DispStr(9, 0, dis);
/************************* 浊度读取显示 *************************/
turbidity_Value = 100 - 100 * ReadADC(AIN0_GND) / 255; //读取浊度
/************************* TDS读取显示 *************************/
TDS_Value = 5 * ReadADC(AIN1_GND) / 255; //读取TDS电压
TDS_Value = 66.71*TDS_Value*TDS_Value*TDS_Value - 127.93*TDS_Value*TDS_Value + 428.7*TDS_Value; //计算TDS
cnt++;
if (cnt <5) //循环显示
{
sprintf(dis, "ZD:%2d%% TDS:%4d", turbidity_Value, (int)TDS_Value);
LCD_DispStr(0, 1, dis);
}
else if (cnt < 10)
{
sprintf(dis, "SW:%7.2fmm ", (1050-distance));
LCD_DispStr(0, 1, dis);
}
else
{
cnt = 0;
}
}
/************************* 设置水位阈值 *************************/
void DispSetWater(unsigned char setIndex)
{
LCD_DispStr(0, 0, " Set Water ");
sprintf(dis, " H:%4d L:%4d ", distance_H, distance_L);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(6, 1, 1); break;
case 2: LCD_SetCursor(14, 1, 1); break;
default:;
}
}
/************************* 设置PH阈值 *************************/
void DispSetPH(unsigned char setIndex)
{
LCD_DispStr(0, 0, " Set PH Limit ");
sprintf(dis, " H:%3d L:%3d ", PH_Value_Max, PH_Value_Min);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(6, 1, 1); break;
case 2: LCD_SetCursor(13, 1, 1); break;
default:;
}
}
/************************* 设置浊度阈值 *************************/
void DispSetTurbidity(unsigned char setIndex)
{
LCD_DispStr(0, 0, " Set Turbidity ");
sprintf(dis, " Max:%3d ", turbidity_Value_Max);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(10, 1, 1); break;
default:;
}
}
/************************* 设置TDS阈值 *************************/
void DispSetTDS(unsigned char setIndex)
{
LCD_DispStr(0, 0, " Set TDS Limit ");
sprintf(dis, " Max:%4d ", TDS_Value_Max);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(11, 1, 1); break;
default:;
}
}
/************************* 串口配置 *************************/
void UART_Init(void)
{
SCON = 0x50;
TH2 = 0xFF;
TL2 = 0xDC;
RCAP2H = 0xFF; //(65536-(FOSC/32/BAUD)) BAUD = 9600 FOSC = 11059200
RCAP2L = 0xDC;
/*****************/
TCLK = 1;
RCLK = 1;
C_T2 = 0;
EXEN2 = 0;
/*****************/
TR2 = 1;
ES = 1; //打开串口中断
EA = 1; //打开总中断
}
/************************* 串口发送字节 *************************/
void UART_SendByte(unsigned char dat) //串口发送单字节数据
{
unsigned char time_out;
time_out = 0;
SBUF = dat; //将数据放入SBUF中
while ((!TI) && (time_out < 100)) //检测是否发送出去
{
time_out++;
DelayUs10x(2);
} //未发送出去 进行短暂延时
TI = 0; //清除ti标志
}
/************************* 串口发送字符串 *************************/
void UART_SendStr(unsigned char *s, unsigned char length)
{
unsigned char num;
num = 0x00;
while (num < length) //发送长度对比
{
UART_SendByte(*s); //放松单字节数据
s++; //指针++
num++; //下一个++
}
}
/************************* 串口中断 *************************/
void UART_Interrupt(void) interrupt 4 //串行中断服务程序
{
static unsigned char i = 0;
static unsigned char firstBit = 0;
static unsigned char R_buf[4];
if (RI)//判断是接收中断产生
{
RI = 0; //标志位清零
if (SBUF == '*')
{
firstBit = 1; //接收标志成功
i = 0;
R_buf[1] = 0;
R_buf[2] = 0;
R_buf[3] = 0;
}
if (firstBit == 1)
{
R_buf[i] = SBUF;
SBUF = SBUF;
i++;
if (i == 4)
{
i = 0;
if (R_buf[0] == '*' && R_buf[3] == '#')
{
if (R_buf[1] == 'C' && R_buf[2] == 'S') //抽水
{
drawFlag2 = 1;
}
else if (R_buf[1] == 'P' && R_buf[2] == 'S') //排水
{
drainFlag2 = 1;
}
}
firstBit = 0;
}
}
}
}