带温度补偿超声波测距(AT89S51)

 DS18B20+超声波模块+AT89S51,DS18B20中间脚接P22,超声波模块的echo接P1.0,trig接P1.1

原理图如下:

 


程序如下

#include <reg51.h>         //STC89C52头文件
#define uchar unsigned char    
#define uint unsigned int
unsigned int  time=0;
unsigned int  timer=0;
unsigned long S=0;         //距离变量
bit  flag =0;                 //超声波模块量程溢出标志(>5米时置1)
sbit echo=P1^0;               //超声波模块的回响信号输出
sbit trig=P1^1;               //超声波模块的触发测距
sbit ds=P2^2;                //DS18B20的信号线
sbit P24=P2^4;
sbit P25=P2^5; 
sbit P26=P2^6;            
sbit P27=P2^7; 
sbit P07=P0^7;             
int temp;    
//八位共阳极
unsigned char code shuzu[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
/*********************************************************/
//共阴
//uchar code shuzu[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//毫秒级延时
void delayms(unsigned char z)  
{
       unsigned char a,b;
       for(a=z; a>0; a--)
                for(b=110; b>0; b--);
}
/*********************************************************/
/*********************************************************/
//微秒级延时
void delayus(unsigned char z)  
{
       while(z)
         z--;
}
/********************************************************/
void delay_ms(unsigned int ms)  //1ms延时
{
    uchar a;
    while(ms--)
 for(a=123;a>0;a--);
}
/*********************************************************/
//DS18B20初始化
void ds18b20init()
{
           ds=0;
           delayus(80);                //延时480-960us
           ds=1;
           delayus(4);                 //等待应答
}
/*********************************************************/
//DS18B20读命令子程序(读一字节)
uchar dushuju()
{
     uchar i,dat,m;
     for(i=8;i>0;i--)
     {
           ds=0;
           delayus(1);
           ds=1;
           delayus(2);
           m=ds;
           dat=(m<<7)|(dat>>1);   //读出的数据最低位在最前面,刚好一个字节在dat里
           delayus(8);
      }
    return dat;
}
/*********************************************************/
//DS18B20写命令子程序(写一字节)
void xiemingling(uint shuju)
{
       uint i;
       bit m;
       for(i=8;i>0;i--)
       {
          m=shuju&0x01;
          shuju=shuju>>1;
          if(m)                           //写1
          {
                   ds=0;
                   delayus(2);
                   ds=1;
                   delayus(8);
          }
          else                     //写0
          {
                   ds=0;
                   delayus(8);
                   ds=1;
                   delayus(2);
          }
       }
}


/*********************************************************/  
//DS18B20开始获取温度并转换
void zhuanhuan()
{
           ds18b20init();
           delayms(1);
           xiemingling(0xcc);        //写跳过读ROM指令
           xiemingling(0x44);       //写温度转换命令
}
/*********************************************************/
//DS18B20读寄存器中存储的温度数据
int duwendu()
{
           uint a,b;
           ds18b20init();
           delayms(1);
           xiemingling(0xcc);                     //跳过ROM,忽略64位ROM地址
           xiemingling(0xbe);                    //读内部RAM中的9字节的温度数据
           a=dushuju();                            //读低8位
           b=dushuju();                           //读高8位
           b=b<<8;                                //高8位左移8位
           temp=b|a;                             // 高8位和低8位组合为1个字
           temp=temp*0.0625;              //温度在寄存器中位12位,分辨率为0.0625度
           return temp;
}


/*********************************************************/
//显示子程序
void xianshi(unsigned long num)
{
          unsigned char bai,shi,ge;
          bai=num/100;                        //分离三位距离数据
          shi=num%100/10;                     
          ge=num%10;                         
P24=0;
P0=shuzu[ge];
delay_ms(1);
P24=1;


P25=0;
P0=shuzu[shi];
P07=1;
delay_ms(1);
P25=1;


P26=0;
P0=shuzu[bai];
delay_ms(1);
P26=1;


//P27=0;
//P0=shuzu[bai];
  //  P07=1;
//delay_ms(1);
   //P27=1;


}


/*********************************************************/ 


//计算距离子程序
void Conut()
{
        float a;
        time=TH0*256+TL0;             //这是最后计算到的时间,但应该再乘以12/11.092
                                                   //时间应该是time*12/11.0592
        TH0=0;                                   //定时器0的初始值位0           
        TL0=0;
        a=(331.5+0.607*temp);    //声速与温度的函数关系:声速=331.5+0.607*温度
        S=(time*a/200)/100;        //算出来是cm     
        if (S>=500)                     //最大距离为5m,即500cm
        S=888;
        if (flag==1)                     //判断是否溢出
        {
          S=888;
          flag=0;
          TH0=0;
          TL0=0;
       }
}


/********************************************************/
//初始化定时器0和定时器1
void T0_init()
{
           TMOD=0x11;    // 0001 0001 方式1 16位 65535
           TH0=0;            
           TL0=0;          
           TH1=0xf8;        //定时器1赋初值,应该是2ms
           TL1=0x30;
           ET0=1;            
           ET1=1;     
           TR1=1;      
           EA=1;
}
void  main( )
{  
     unsigned int i;
     T0_init();    
     while(1)
     {
         duwendu();                               //获取温度后计算相应声速,从而计算距离
         while(!echo);                            //当echo为0时等待 
         TR0=1;                                    //开启定时器0
         while(echo);                            //当echo为1计数并等待
         TR0=0;                                   //关闭定时器0
         Conut();                                  //计算距离
         for(i=150;i>0;i--)              
        {
                  xianshi(S);                      //数码管显示
         }
     }
}
/********************************************************/
void zd0() interrupt 1   
{
    flag=1;                                            //中断溢出标志
}                       
/********************************************************/
void  zd3()  interrupt 3    
{                                
      TH1=0xf8;                    
      TL1=0x30;
      timer++;
      if(timer>=100)                                //每隔800ms启动超声波模块
      {
         timer=0;
         xianshi(S);
         trig=1;             
         delayms(30);                              //一次超声波信号时长30ms
         trig=0;
      }


}
/*********************************************************/

效果如下:



版权声明:本文为weiguishan原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。