代码:

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit Trig = P1^7; //超声波发送信号
sbit Echo = P3^2; //超声波接收信号
bit timeout_flag = 0; //接收超时标志,距离过长或超声波未响应
sbit DQ = P3^0; //温度传感器
sbit BUZZER = P3^7; //蜂鸣器
sbit Key0 = P3^3; //不加温度补偿自锁开关
sbit Key1 = P3^4; //加温度补偿自锁开关
sbit LED0 = P3^5;
sbit LED1 = P3^6;


void bcd(uint setdata);  
void display(uint setdata);	 //显示距离d(distance)
void delayms(uint t);
void delayus(uint us);

void Get_distance_Data();
uint diatance_Conut();


uint DS18B20_init();
void write_byte(uchar dat);
uchar read_byte();
uint read_temper();
uint temper_change();


float time; //超声波传播时间
float distance = 9999;//显示9999或0(其实达不到2mm,软件仿真最小只有30mm)即为超出范围
float Temperature = 25;
uchar num1[4]; //储存四位数字

uchar code ledval[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar code ledpoint[]={0xf1,0xf2,0xf4,0xf8};

void main()
{
	
	LED0 = 1;
	LED1 = 1;
	BUZZER = 0;

	TMOD = 0X11;

	TH0 = 0;
	TL0 = 0;
	ET0 = 1;	//允许T0中断
	EA = 1;

	DS18B20_init();

	while(1)
	{

		Get_distance_Data();
		distance = diatance_Conut();
	    display((int)distance);	

//		display((int)temper_change());
		
	}

}


void Get_distance_Data()
{ 
	Trig = 1;
 	delayus(22);
  	Trig = 0;
	Trig = 1;
 	delayus(22);
  	Trig = 0;	
  	while(!Echo);
	TR0 = 1;
	while(Echo);
	TR0 = 0;

}


uint diatance_Conut()
{

  uint S;
  time = TH0*256+TL0;
  TH0 = 0;
  TL0 = 0;

  if(Key1 == 1 && Key1 == 1)
  {
  	S = 9999;
  	LED0 = 1;
	LED1 = 1;
	BUZZER = 0;
  }

  if(Key0 == 0 && Key1 == 1)
  {
  	S = (time*0.34)/2.0; //温度补偿前,显示为mm
	LED0 = 0;
	LED1 = 1;
  }
  if(Key1 == 0 && Key0 == 1)
  {
  	Temperature = temper_change();
  	S = (331.45+0.61*Temperature)*time/2000; //温度补偿后,显示为mm
	LED0 = 1;
	LED1 = 0;
  }
	
	if(Key1 == 0 || Key0 == 0)
	{
	  BUZZER = 0;
	
	  if(S>=3000)
	  {
	    S = 9999;
		BUZZER = 1;
	  }
	  if(S<=2)
	  {
	    S = 0;
		BUZZER = 1;
	  }
	  if(timeout_flag == 1)
	  {
	  	S = 9999;
		BUZZER = 1;
	  	timeout_flag = 0;
	  	TH0 = 0;
	  	TL0 = 0;
	  } 
	 }
   
  return S;

}


void timer0mode1() interrupt 1
{
  timeout_flag = 1;
}

void display(uint setdata)
{
	uchar i;
	bcd(setdata);
	for(i=0;i<4;i++)
	{
		P2=ledpoint[i]; //数码管位选
		P0=ledval[num1[i]];	//数码管段选
		delayms(2);
	}
}

void bcd(uint setdata)
{
	num1[0]=setdata/1000;             
	num1[1]=(setdata%1000)/100;     
	num1[2]=((setdata%1000)%100)/10;
	num1[3]=((setdata%1000)%100)%10;
}

//ms级延时
void delayms(uint t)
{
	uchar i;
	while(t--)
	{
		for(i=0;i<120;i++)
		{;}
	}
}

//us级延时
void delayus(uint us)
{
    while(us--);
}

uint DS18B20_init()
{
       uchar i;
	   DQ=1;
       delayus(1);     //稍作延时
       DQ=0;
       delayus(80);    //延时480到960us
       DQ=1;
       i = 0;
       while(DQ)    //等待DS18B20拉低总线
       {
           delayms(1);
           i++;
           if(i>5)//约等待>5MS
           {
           		return 0;//初始化失败
           }    
       }
	   return 1;
}

void write_byte(uchar dat)   //写一个字节
{
   uchar i;
   for(i=0;i<8;i++)
   {
     DQ=0;  //每写入一位数据之前先把总线拉低1us
      _nop_();
     DQ=dat&0x01;    //取最低位写入
     delayus(10);   //延时68us,持续时间最少60us
     DQ=1;   //然后释放总线
     dat=dat>>1;    //从低位开始写
   }
   delayus(10);
}

uchar read_byte()    //读一个字节
{
  uchar i,dat=0, bi;
  for(i=0;i<8;i++)
  {
     DQ=0;  //先将总线拉低1us
     _nop_();
     DQ=1;  //然后释放总线
     _nop_();
	 _nop_();
     _nop_();
	 _nop_();
//     if(DQ) dat=dat|0x80;   //每次读一位
//     dat=dat>>1;       //从最低位开始读
	 bi = DQ;
	 dat = (dat >> 1)|(bi << 7);
     delayus(10);   //读取完之后等待48us再接着读取下一个数
   }
   return dat;
}

uint read_temper()
{    
   uchar a,b;         
   uint t=0;
   DS18B20_init();       
   delayms(1);
   write_byte(0xcc);   //跳过ROM操作命令
   write_byte(0x44);     //发送启动温度转换命令
   DS18B20_init();       
   delayms(1);
   write_byte(0xcc);    //跳过ROM操作命令
   write_byte(0xbe);      //发送读温度寄存器命令
   a=read_byte();    //先读低八位
   b=read_byte();      //再读高八位
   t=b;        
   t<<=8;      //左移八位
   t=t|a;      //t为16位的数,使高八位为b的值,低八位为a的值  
   return t;    //返回温度值
}

uint temper_change()
{
    int temper;
    float tp;
    temper=read_temper();
    if(temper<0)    //考虑负温度的情况
    {
        temper=temper-1;
		temper=~temper;
        tp=temper*0.0625;  //16位温度转换成10进制的温度
        temper=tp+0.5;   //四舍五入
    }
    else
    {
        tp=temper*0.0625;  //16位温度转换成10进制的温度
        temper=tp+0.5;  //四舍五入
    }
    return temper;
}

原理图:
在这里插入图片描述

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐