基于51单片机超声波液位仪测距温度补偿

该系统采用AT89C51单片机,结合DS18B20温度传感器和HC-SR04超声波模块,实现温度和水位的精确测量。LCD1602用于显示参数,多个功能键用于设置和控制。系统还包含LED和蜂鸣器的报警电路,确保在超出预设阈值时能发出警告。
摘要由CSDN通过智能技术生成

仿真图:

在这里插入图片描述

功能简介:

单片机采用AT89C51,最小系统由晶振和复位电路组成
液晶显示采用LCD1602用于显示该项目的参数信息
具有多个功能按键,分别是设置、加、减和切换以及归零等功能
采用DS18B20作为该项目的温度传感器,超声波模块采用的是HCSR04用于测量水位值
具有LED和蜂鸣器组成的声光报警电路,

芯片/模块的特点:

DS18B20特点:

单总线接口:DS18B20使用单总线接口进行通信,只需要一个引脚就可以连接多个传感器,简化了电路设计和连接。

数字输出:DS18B20以数字形式输出温度值,不需要额外的模数转换器。它使用12位的分辨率来表示温度值,可以实现高精度的温度测量。

高精度:DS18B20可以提供从-55°C到+125°C的温度测量范围,并具有±0.5°C的温度精度。因此,在许多应用中,它可以提供可靠和准确的温度测量结果。

多功能性:除了测量温度,DS18B20还可以执行其他功能,如温度报警功能。它可以设置上下限温度阈值,并在温度超过或低于这些阈值时触发报警。

低功耗:DS18B20采用低功耗设计,工作电流极低,只需要很少的能量来进行温度测量和通信。

耐用性:DS18B20具有良好的耐用性和可靠性,其封装材料和结构设计使其适用于各种环境条件下的应用。

HC-SR04特点:

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

主程序:


#include "config.h"
#include "Lcd1602.h"
#include "Ultrasonic.h"
#include <reg52.h>

uint8 flag;   //定义定时标志
uint16 set_s;  //设定值
uint16 lv_0;   //零位
uint16 length;
uint16 lv_n;

bit flag1s = 0;          //1s定时标志
bit fusu = 0;          //1s定时标志
bit setflag= 0;          //进入设置模式标志
bit changewei=0;
unsigned char T0RH = 0;  //T0重载值的高字节
unsigned char T0RL = 0;  //T0重载值的低字节
//
void ConfigTimer0(unsigned int ms);
unsigned char IntToString(unsigned char *str, int dat);
extern bit Start18B20();
extern bit Get18B20Temp(int *temp);

sbit led=P1^1;
sbit bz=P1^0;
sbit k3=P3^5;	 //更换十位和百位
sbit k1=P3^4;	 //加
sbit k2=P3^6;	 //减
sbit k4=P3^7;	 //设置
void ShowDistance();
void ShowSets();
void delayms(unsigned int ms);

/* 主函数 */
void main()
{	
   	bit res;
		
    int temp;        //读取到的当前温度值
    int intT, decT;  //温度值的整数和小数部分
    unsigned char len;
    unsigned char str[12];
    set_s=50;//mm
	lv_0=150;//mm
    EA = 1;            //开启总中断
    TMOD &= 0Xf0;
    TMOD |= 0X01;      //设置T0为方式1
    TH0 = 0xFC;        //为T0赋初值0xFC67,定时1ms
    TL0 = 0x67;
    ET0 = 1;           //使能T0中断
    TR0 = 1;           //启动T0
	IT0=1;	//设置外部中断0的触发方式为下降沿
	EX0=1;	//开启外部中断
    InitUltrasonic();  //超声波模块初始化
    InitLcd1602();     //1602初始化
	Start18B20();      //启动DS18B20
	LcdShowStr(0, 0,"TL:");  //显示阈值
	LcdShowStr(0, 1,"SW:");  //显示距离单位
	LcdShowStr(10, 1,"T:");  //显示距离单位
	k1=1;

    while(1)
    {
        if(flag == 1)
        {
            flag = 0;
			ShowSets();
            ShowDistance();
    		if (1)  //每秒更新一次温度
        {
            res = Get18B20Temp(&temp);  //读取当前温度
            if (res)                    //读取成功时,刷新当前温度显示
            {
                intT = temp >> 4;             //分离出温度值整数部分
                decT = temp & 0xF;            //分离出温度值小数部分
                len = IntToString(str, intT); //整数部分转换为字符串
                str[len++] = '.';             //添加小数点
                decT = (decT*10) / 16;        //二进制的小数部分转换为1位十进制位
                str[len++] = decT + '0';      //十进制小数位再转换为ASCII字符
                while (len < 6)               //用空格补齐到6个字符长度
                {
                    str[len++] = ' ';
                }
                str[len] = '\0';              //添加字符串结束符
                LcdShowStr(12, 1, str);        //显示到液晶屏上
            }
            else                        //读取失败时,提示错误信息
            {
                LcdShowStr(12, 1, "error!");
            }
            Start18B20();               //重新启动下一次转换
        }
        }
		while(setflag){//按下设置键,进入设置模式,循环直到再一次按下设置键

			if(k1==0)		  //检测按键K1是否按下
				{	
					delayms(5);   //消除抖动 一般大约10ms
					if(k1==0)	 //再次判断按键是否按下
					{  
						if(changewei==0)set_s++;
						else set_s+=10;
					}
					while(!k1);	 //检测按键是否松开
				}
			if(k2==0)		  //检测按键K1是否按下
				{	
					delayms(5);   //消除抖动 一般大约10ms
					if(k2==0)	 //再次判断按键是否按下
					{
						if(changewei==0)set_s--;
							else set_s-=10;
					}
					while(!k2);	 //检测按键是否松开
				}
			if(k3==0)		  //检测按键K1是否按下
				{	
					delayms(5);   //消除抖动 一般大约10ms
					if(k3==0)	 //再次判断按键是否按下
					{
						changewei=~changewei;
					}
					while(!k3);	 //检测按键是否松开
				}
			if(k4==0)		  //检测按键K1是否按下
				{	
					delayms(5);   //消除抖动 一般大约10ms
					if(k4==0)	 //再次判断按键是否按下
					{
					 lv_0=length;
					}
					while(!k4);	 //检测按键是否松开
				}
				ShowSets();
		}
		if(lv_n>set_s) bz=1;
		else bz=0;
    }
}
unsigned char IntToString(unsigned char *str, int dat)
{
    signed char i = 0;
    unsigned char len = 0;
    unsigned char buf[6];
    
    if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号
    {
        dat = -dat;
        *str++ = '-';
        len++;
    }
    do {          //先转换为低位在前的十进制数组
        buf[i++] = dat % 10;
        dat /= 10;
    } while (dat > 0);
    len += i;     //i最后的值就是有效字符的个数
    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上
    {
        *str++ = buf[i] + '0';
    }
    *str = '\0';  //添加字符串结束符
    
    return len;   //返回字符串长度
}




/* 执行测距并显示结果 */
void ShowDistance()
{   
    uint8 i;
    uint8 buff[4];
	uint8 buff2[5];
    uint16 Distance ;   //暂存距离值
    Distance = GetDistance();
	length = Distance;//mm
	if (Distance < lv_0)
		{
		Distance = lv_0-Distance;
		lv_n= Distance;
		fusu=0;
		}
	else
	 {
		 Distance =Distance- lv_0;
		 lv_n=0;
		 fusu=1;
	 }
	if((Distance<999)&&(fusu==0)){
	    buff[3] = Distance%10 + '0';   //将数据转换为字符形式
	    buff[2] ='.';
	    buff[1] = (Distance/10)%10 + '0';
	    buff[0] = (Distance/100)%10 + '0';
	    for(i = 0; i <= 0; i++)  //整数部分高位的0转换为空白符
	    {
	        if(buff[i] == '0')   //判断是不是字符0
	            buff[i] = ' ';   //将字符0 转换为空格 即不显示
	        else
	            break;
	    }
	    LcdShowStr(3, 1, &buff); //显示距离值
	    LcdShowStr(7, 1, "cm");  //显示距离单位
	}
		if((Distance<99)&&(fusu==1)){
	    buff[3] =' ';   //将数据转换为字符形式
	    buff[2] =Distance%10 + '0'; 
	    buff[1] ='.';
	    buff[0] = (Distance/10)%10 + '0';
//	    for(i = 0; i <= 0; i++)  //整数部分高位的0转换为空白符
//	    {
//	        if(buff[i] == '0')   //判断是不是字符0
//	            buff[i] = ' ';   //将字符0 转换为空格 即不显示
//	        else
//	            break;
//	    }
			LcdShowStr(3, 1, "-");  //显示距离单位
	    LcdShowStr(4, 1, &buff); //显示距离值
	    LcdShowStr(7, 1, "cm");  //显示距离单位
	}
	if(Distance>999||((Distance>99)&&(fusu==1))){
		LcdShowStr(3, 1, "ERROR");  //显示距离单位
//	    else {
//			buff2[4] = Distance%10 + '0';   //将数据转换为字符形式
//		    buff2[3] ='.';
//		    buff2[2] = (Distance/10)%10 + '0';
//		    buff2[1] = (Distance/100)%10 + '0';
//			buff2[0] = (Distance/1000)%10 + '0';
//		    for(i = 0; i <= 3; i++)  //整数部分高位的0转换为空白符
//		    {
//		        if(buff2[i] == '0')   //判断是不是字符0
//		            buff2[i] = ' ';   //将字符0 转换为空格 即不显示
//		        else
//		            break;
//		    }
//		    LcdShowStr(3, 1, &buff2); //显示距离值
//		    LcdShowStr(8, 1, "cm");  //显示距离单位
	//	}
	}
}
void ShowSets()
{   
    uint8 i;
    uint8 buff[4];

	if(set_s>999)set_s=999;
    buff[3] = set_s%10 + '0';   //将数据转换为字符形式
    buff[2] ='.';
    buff[1] = (set_s/10)%10 + '0';
    buff[0] = (set_s/100)%10 + '0';
    for(i = 0; i <= 3; i++)  //整数部分高位的0转换为空白符
    {
        if(buff[i] == '0')   //判断是不是字符0
            buff[i] = ' ';   //将字符0 转换为空格 即不显示
        else
            break;
    }
    LcdShowStr(6, 0, &buff); //显示距离值
    LcdShowStr(10, 0, "cm");  //显示距离单位
}

/* 定时器0中断服务函数 */
void InterruptTimer0() interrupt 1 using 3
{
    static uint16 cnt = 0;   //定义计数变量

    TH0 = 0xFC;      //重新加载初值
    TL0 = 0x67;
    cnt++;
    if(cnt >= 600)   //定时330ms
    {
        cnt = 0;     //清零计数值
        flag = 1;    //设置定时标志为1
    }
}

void delayms(unsigned int ms)
{
	unsigned char i=100,j;
	for(;ms;ms--)
	{
		while(--i)
		{
			j=10;
			while(--j);
		}
	}
}

void EX0_ISR(void) interrupt 0
{
	led=~led;
	setflag=~setflag;
}



设计文件:

链接:https://pan.baidu.com/s/1cV-rEk5RoltmyGim3_XzRw?pwd=fdvd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值