仿真图:
功能简介:
单片机采用AT89C51,最小系统由晶振和复位电路组成
液晶显示采用LCD1602用于显示该项目的参数信息
具有多个功能按键,分别是设置、加、减和切换以及归零等功能
采用DS18B20作为该项目的温度传感器,超声波模块采用的是HCSR04用于测量水位值
具有LED和蜂鸣器组成的声光报警电路,
芯片/模块的特点:
DS18B20特点:
单总线接口:DS18B20使用单总线接口进行通信,只需要一个引脚就可以连接多个传感器,简化了电路设计和连接。
数字输出:DS18B20以数字形式输出温度值,不需要额外的模数转换器。它使用12位的分辨率来表示温度值,可以实现高精度的温度测量。
高精度:DS18B20可以提供从-55°C到+125°C的温度测量范围,并具有±0.5°C的温度精度。因此,在许多应用中,它可以提供可靠和准确的温度测量结果。
多功能性:除了测量温度,DS18B20还可以执行其他功能,如温度报警功能。它可以设置上下限温度阈值,并在温度超过或低于这些阈值时触发报警。
低功耗:DS18B20采用低功耗设计,工作电流极低,只需要很少的能量来进行温度测量和通信。
耐用性:DS18B20具有良好的耐用性和可靠性,其封装材料和结构设计使其适用于各种环境条件下的应用。
HC-SR04特点:
- 非接触式测距:HC-SR04利用超声波技术进行测距,可以在不接触测量目标物的情况下获取距离信息。这种非接触式的特性使得它在许多应用中非常有用。
- 宽测量范围:HC-SR04可以测量的距离范围较广,通常为2厘米到400厘米。这使得它可以满足许多测量需求,从近距离到远距离的测量都可以应对。
- 高精度:HC-SR04测量距离的精度相对较高,可以达到3毫米左右。这对于需要较精确距离测量的应用是非常有益的。
- 易于使用:HC-SR04的使用非常简单,只需要提供一个触发信号,然后等待接收到回波信号,并通过计算来确定距离。它使用简单的电平触发和回波检测机制。
- 快速测量响应:HC-SR04可以快速地对目标进行测量并提供准确的结果。它的测量响应时间通常在几十毫秒的范围内。
- 低功耗: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;
}
设计文件: