基于51单片机的水塔水位超声波监测

仿真图:

在这里插入图片描述

芯片/模块的特点:

AT89C52简介:
AT89C52是一款经典的8位单片机,是意法半导体(STMicroelectronics)公司生产的一系列单片机之一。它基于8051内核,并具有许多与其兼容的特性。

AT89C52的主要特点如下:

内部存储器:AT89C52具有8KB的闪存(Flash)存储器,可用于存储用户程序和数据。这些存储器的内容可以通过编程器进行编程和擦除。

RAM存储器:AT89C52配备了256字节的随机存取存储器(RAM),用于暂存数据和程序的变量。

外部扩展性:AT89C52支持多种外部扩展设备的连接,包括外部存储器(如RAM、EEPROM)和外设(如ADC、LCD、UART等),通过外部硬件连接,可以扩展单片机的功能和应用。

通用I/O引脚:AT89C52拥有32个可编程的通用输入/输出引脚,可用于连接外部设备和与其他芯片进行通信。

定时器/计数器:AT89C52内置了3个16位定时器/计数器和一个可编程的串行定时器/计数器。这些计时器/计数器可用于实现定时功能、生成脉冲信号、测量时间间隔等。0

串行通信:AT89C52支持串行通信接口,包括UART(串行异步通信)和SPI(串行外设接口),便于与其他设备进行数据通信和交互。

低功耗模式:AT89C52具有多种低功耗模式,如空闲模式和电源下模式,在不需要执行任务的时候可以将CPU进入低功耗状态以节省能量。

宽电源电压范围:AT89C52的工作电压范围通常为4.0V至5.5V,可以满足大多数应用需求。

HC-SR04特点:

  1. 非接触式测距:HC-SR04利用超声波技术进行测距,可以在不接触测量目标物的情况下获取距离信息。这种非接触式的特性使得它在许多应用中非常有用。
  2. 宽测量范围:HC-SR04可以测量的距离范围较广,通常为2厘米到400厘米。这使得它可以满足许多测量需求,从近距离到远距离的测量都可以应对。
  3. 高精度:HC-SR04测量距离的精度相对较高,可以达到3毫米左右。这对于需要较精确距离测量的应用是非常有益的。
  4. 易于使用:HC-SR04的使用非常简单,只需要提供一个触发信号,然后等待接收到回波信号,并通过计算来确定距离。它使用简单的电平触发和回波检测机制。
  5. 快速测量响应:HC-SR04可以快速地对目标进行测量并提供准确的结果。它的测量响应时间通常在几十毫秒的范围内。
  6. 低功耗:HC-SR04的功耗相对较低,适合在需要长时间运行或使用电池供电的应用中使用。

DS1302特点:
高精度时间计数:DS1302能够提供高精度的实时时钟计数,可以记录年、月、日、星期、小时、分钟和秒等时间信息。它内部集成了晶体振荡器,提供稳定的时钟信号。

低功耗设计:DS1302采用低功耗设计,可以在低功耗模式下运行,有效延长电池寿命。即使在停电情况下,它也能保持时间数据,并通过外部连接电池继续提供计时功能。

串行接口:DS1302通过串行实时时钟接口(SPI)进行通信和控制。使用少数几个引脚,可以与主控器件进行数据交换和时钟同步。

容易集成:DS1302集成了时钟计数和RAM存储器功能,并具有简单的接口和命令,容易与各种微控制器和单片机集成。它不需要复杂的控制信号,可以通过简单的读写命令进行操作。

可编程控制功能:DS1302具有可编程的控制功能,可以设置闹钟、写保护等特殊功能。它还支持多种时间格式的选择,例如24小时制或12小时制。

温度补偿:DS1302内置温度补偿功能,可以校正温度对时钟频率的影响,提高时钟计数的准确性。

高稳定性和抗震动能力:DS1302具有高稳定性和抗震动能力,适用于各种工业和消费类应用场景。

主程序:

#include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>
#include "lcd1602.h"
#include "ds1302.h"
#include "delay.h"
#include "math.h"

//管脚定义
sbit KEY_SET = P3^7;
sbit KEY_ADD = P3^5;
sbit KEY_SUB = P3^6;
sbit KEY_ENTER = P3^4;

sbit ECHO = P1^1; //超声波引脚定义
sbit TRIP = P1^0;

sbit LED_GREEN = P1^6; //引脚定义
sbit LED_RED = P1^5;
sbit BUZZER = P1^7;

//变量定义
unsigned char dis[16] = "Distance:     mm";	 //显示数组
unsigned char disTime[16] = "   /  /     :   ";
float f_distance;		 //距离
long g_cnt = 0; //定时器计数
unsigned char g_setLocation = 0;
bit g_setTimeFlag = 0;
bit g_dispFlag = 0;
bit g_refreshFlag = 0;
unsigned char cnt = 0;

//函数声明
void DispTime();
void DispDis();
void SetTime();
void KeyScan();
void Timer1_Init();

void main(void)
{
	unsigned char testTime = 0;
	float f_distanceBuf = 0;
    
    TRIP = 0;
	TMOD |= 0x01; //设T0为方式1,GATE=1;
	TH0 = 0;
	TL0 = 0;
	//	ET0=1;             //允许T0中断
	EA = 1; //开启总中断

	Timer1_Init();
	DS1302_Init();
	LCD_Init();	 //初始化液晶
	DelayMs(20); //延时有助于稳定
	LCD_Clear();

	while (1) //主循环
	{
		if (g_refreshFlag == 1)
		{
			g_refreshFlag = 0;
			if (testTime >= 10)
			{
				testTime = 0;
				f_distance = f_distanceBuf / 10; //计算5次平均值
				f_distanceBuf = 0;
			}
			else
			{
				TR1 = 0;
				TRIP = 1; //启动一次模块		//不可以使用其他终端 容易造成死循环
				DelayUs10x(1);
				TRIP = 0;
				while (!ECHO)
					;	 //当RX为零时等待
				TR0 = 1; //开启计数
				while (ECHO)
					; //当RX为1计数并等待
				TR0 = 0;
				TR1 = 1;
				g_cnt = (long)(TH0 * 256 + TL0);
				TH0 = 0;
				TL0 = 0;
				f_distanceBuf = f_distanceBuf + (float)(g_cnt * 17) / 100.0 * 1.102; //算出来是mm (g_cnt * 340 / 2) / 1000.0 * 1.102;系数
				testTime++;
			}
		}

		if ((g_cnt > 0) && (f_distance > 0))
		{
			if (f_distance < 500) //距离对比
			{
				BUZZER = 1;
				LED_GREEN = 0;
				LED_RED = 1;
			} //不报警 指示灯正常
			else
			{
				BUZZER = 0;
				LED_GREEN = 1;
				LED_RED = 0;
			} //报警 指示灯异常
		}

		if (g_setTimeFlag == 1) //设置时钟
		{
			SetTime();
		}
		else //读取时钟
		{
			DS1302_Read_Time();
		}

		if (g_dispFlag == 1) //刷新液晶
		{
			TR1 = 0;
			DispTime();
			DispDis();
			TR1 = 1;
			g_dispFlag = 0;
		}

        KeyScan();
	}
}

void DispTime()
{
	disTime[1]  = '0' + timeBufDec[1] / 10;
	disTime[2]  = '0' + timeBufDec[1] % 10;
	disTime[4]  = '0' + timeBufDec[2] / 10;
	disTime[5]  = '0' + timeBufDec[2] % 10;
	disTime[7]  = '0' + timeBufDec[3] / 10;
	disTime[8] = '0' + timeBufDec[3] % 10;
	disTime[10]  = '0' + timeBufDec[4] / 10;
	disTime[11]  = '0' + timeBufDec[4] % 10;
	disTime[13]  = '0' + timeBufDec[5] / 10;
	disTime[14]  = '0' + timeBufDec[5] % 10;

	DispStr(0, 0, disTime);
}

void DispDis()
{
	dis[9]  = '0' + (int)f_distance / 10000;
	dis[10]  = '0' + (int)f_distance / 1000 % 10;
	dis[11]  = '0' + (int)f_distance / 100 % 10;
	dis[12]  = '0' + (int)f_distance / 10 % 10;
	dis[13]  = '0' + (int)f_distance % 10;

	DispStr(0, 1, dis);
}

void SetTime()
{
	TR1 = 0;
	LcdWriteCommand(0x0F, 0);
    switch (g_setLocation)
    {
        case 1: LcdWriteCommand(0x80 + 2, 0); break;
        case 2: LcdWriteCommand(0x80 + 5, 0); break;
        case 3: LcdWriteCommand(0x80 + 8, 0); break;
        case 4: LcdWriteCommand(0x80 + 11, 0); break;
        case 5: LcdWriteCommand(0x80 + 14, 0); break;
        case 6: LcdWriteCommand(0x0C, 0); DelayMs(5); LCD_Clear(); DS1302_Write_Time(); g_setLocation = 0; g_setTimeFlag = 0; break;
		default: ;
    }
	TR1 = 1;
}

void KeyScan()
{
    if (!KEY_SET) 
	{
		DelayMs(5);
		if (!KEY_SET)
		{
			if (g_setTimeFlag)
            {
                g_setLocation++;
            }
			else
            {
                g_setTimeFlag = 1;
                g_setLocation = 1;
            }
			
		}
		while (!KEY_SET);
	}

	if (!KEY_ADD)
	{
		DelayMs(5);
		if (!KEY_ADD)
		{
            if (g_setTimeFlag)
            {
                switch (g_setLocation)
				{
					case 1: 
					{
						timeBufDec[1]++;
						if (timeBufDec[1] > 99)
						{
							timeBufDec[1] = 0;
						}
						break;
					}
					case 2: 
					{
						timeBufDec[2]++;
						if (timeBufDec[2] > 12)
						{
							timeBufDec[2] = 1;
						}
						break;
					}
					case 3: 
					{
						timeBufDec[3]++;
						if (timeBufDec[3] > YDay(timeBufDec[1], timeBufDec[2]))
						{
							timeBufDec[3] = 1;
						}
						break;
					}
					case 4: 
					{
						timeBufDec[4]++;
						if (timeBufDec[4] > 23)
						{
							timeBufDec[4] = 0;
						}
						break;
					}
					case 5: 
					{
						timeBufDec[5]++;
						if (timeBufDec[5] > 59)
						{
							timeBufDec[5] = 0;
						}
						break;
					}
				}
            }
		}
		while (!KEY_ADD);
	}

	if (!KEY_SUB)
	{
		DelayMs(5);
		if (!KEY_SUB)
		{
            if (g_setTimeFlag)
            {
                switch (g_setLocation)
                {
                case 1:
                {
                    if (timeBufDec[1] == 0)
                    {
                        timeBufDec[1] = 100;
                    }
                    timeBufDec[1]--;
                    break;
                }
                case 2:
                {
                    timeBufDec[2]--;
                    if (timeBufDec[2] < 1)
                    {
                        timeBufDec[2] = 12;
                    }
                    break;
                }
                case 3:
                {
                    timeBufDec[3]--;
                    if (timeBufDec[3] < 1)
                    {
                        timeBufDec[3] = YDay(timeBufDec[1], timeBufDec[2]);
                    }
                    break;
                }
                case 4:
                {
                    if (timeBufDec[4] == 0)
                    {
                        timeBufDec[4] = 24;
                    }
                    timeBufDec[4]--;
                    break;
                }
                case 5:
                {
                    if (timeBufDec[5] == 0)
                    {
                        timeBufDec[5] = 60;
                    }
                    timeBufDec[5]--;
                    break;
                }
                }
            }
        }    
		while (!KEY_SUB);
	}

    if (!KEY_ENTER)
    {
        DelayMs(5);
        if (!KEY_ENTER)
        {
            if (g_setTimeFlag)
            {
                g_setLocation = 6;
            }
        }
        while (!KEY_ENTER);
    }
}

void Timer1_Init()
{
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TH1 = (65536 - 18432) / 256; //20ms定时
	TL1 = (65536 - 18432) % 256; //20ms定时
	TR1 = 1;
	ET1 = 1;
	EA = 1;
}

void Timer1_INT() interrupt 3
{

	TH1 = (65536 - 18432) / 256; //20ms定时
	TL1 = (65536 - 18432) % 256;

	if (cnt >= 25)
	{
		g_dispFlag = 1;
		cnt = 0;
	}
	else
	{
		cnt++;
	}

	if (cnt % 5 == 0)
	{
		g_refreshFlag = 1;
	}
}

设计文件:
链接:https://pan.baidu.com/s/1NaYJr8MPGddAGhCu5ixeEA?pwd=g27n

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值