找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 959|回复: 0
打印 上一主题 下一主题
收起左侧

单片机超声波测距加温度补偿程序有什么问题吗? 求帮助

[复制链接]
跳转到指定楼层
楼主
有没有大佬给看看有什么问题。

#include <reg51.H>//器件配置文件
#include <intrins.h>

//传感器接口
sbit echo  = P3^2;
sbit trig  = P3^3;
//按键声明
sbit S1  = P1^4;   //切换厚度和温度显示


sbit W1=P1^0;
sbit W2=P1^1;
sbit W3=P1^2;
sbit W4=P1^3;
//蜂鸣器
sbit Feng= P2^0;
sbit ds=P3^7;                //DS18B20的接口


//变量声明
int temp;
int j=0;
unsigned int  time=0;
unsigned int  timer=0;
unsigned char posit=0;
unsigned int S=0;
float S0=0;
float S2=0;
float v=0;
unsigned int h=0;
float h0=0;

//模式 0正常模式 1调整
char Mode=0;
bit  flag=0;
bit flag_KEY=0;
float distance[5]={0,0,0,0,0};
unsigned char const discode[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0xff/*-*/};    //数码管显示码0123456789-和不显示

unsigned char disbuff[4]       ={0,0,0,0};         //数组用于存放距离信息
unsigned char disbuff_wd[4]    ={0,0,0,0};//温度信息
void Display();
//延时20ms(不精确)
void delay(void)
{
    unsigned char a,b,c;
    for(c=2;c>0;c--)
        for(b=38;b>0;b--)
            for(a=60;a>0;a--);
}
/*********************************************************/
//毫秒级延时
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延时
{
    unsigned char a;
    while(ms--)
for(a=123;a>0;a--);
}

/*********************************************************/
//DS18B20初始化
void ds18b20init()
{
           ds=0;
           delayus(80);                //延时480-960us
           ds=1;
           delayus(4);                 //等待应答
}
/*********************************************************/
//DS18B20读命令子程序(读一字节)
unsigned char dushuju()
{
    unsigned char 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(unsigned int shuju)
{
       unsigned int 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()
{
           unsigned int 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 Key_()
{
    if(flag_KEY==0)
    {
        
        //功能
        if(S1==0)        //设置键
        {
            delay();
            if(S1==0)
            {
                Mode++;        //模式加
                flag_KEY=1;
                if(Mode>=2)        //加到2时清零
                {
                    Mode=0;
                }

            }
        }
    }
    if((P1&0x70)==0x70)
    {
        flag_KEY=0;
    }
}
/**********************************************************************************************************/
//扫描数码管
void Display(void)                 
{
if(Mode==0)              //非设置状态时
    {
        if((S2>=4000)||(flag==1)) //超出测量范围显示“-”
        {   
            Feng=0;            //蜂鸣器报警
            flag=0;
            disbuff[0]=10;        
            disbuff[1]=10;       //“-”
            disbuff[2]=10;       //“-”
            disbuff[3]=10;       //“-”
        }
        else
        {
            
            if((S2>100.3)||(S2<99.7))
            {
                Feng=0;    //报警
            }
            else
            {    Feng=1;        //关闭报警   
            
            h0=110-S2;
            h=(int)(h0*10);
            disbuff[0]=h/1000;         //将距离数据拆成单个位赋值
            disbuff[1]=h%1000/100;
            disbuff[2]=h%1000%100/10;
            disbuff[3]=h%1000%100%10;
            }
        }
    }
    else
    {
            Feng=1;

            disbuff_wd[0]=temp/1000;
            disbuff_wd[1]=temp%1000/100;
            disbuff_wd[2]=temp%1000%100/10;
            disbuff_wd[2]=temp%1000%100%10;
    }

    //正常显示
    if(Mode==0)
    {
        P0=0x00;  //关闭显示
     if(posit==2)
        {P0=discode[disbuff[posit]]|0x80;}
        else{
            P0=discode[disbuff[posit]];
        }
        switch(posit)
        {
            case 0 : W1=0;W2=1;W3=1;W4=1; break;
            case 1 : W1=1;W2=0;W3=1;W4=1; break;
            case 2 : W1=1;W2=1;W3=0;W4=1; break;
            case 3 : W1=1;W2=1;W3=1;W4=0; break;
        }
        posit++;
        if(posit>3)        //每进一次显示函数,变量加1
            posit=0;        //加到3时清零
    }
    //温度显示
    else
    {
        P0=0x00;
   
            P0=discode[disbuff_wd[posit]];
        
        switch(posit)
        {
            case 0 : W1=0;W2=1;W3=1;W4=1; break;
            case 1 : W1=1;W2=0;W3=1;W4=1; break;
            case 2 : W1=1;W2=1;W3=0;W4=1; break;
            case 3 : W1=1;W2=1;W3=1;W4=0; break;
        }
        posit++;
        if(posit>3)
            posit=0;
    }
}
/**********************************************************************************************************/
//计算
float Conut(void)
{
    time=(float)(TH0*256+TL0)*1.085;      //读出T0的计时数值
    TH0=0;
    TL0=0;                  //清空计时器
    v=(331.5+0.607*temp);    //声速与温度的函数关系:声速=331.5+0.607*温度
    S0=v*time/20000;          //S0的单位是毫米
    return S0;
}

//定时器0
void zd0() interrupt 1          //T0中断用来计数器溢出,超过测距范围
{
    flag=1;                         //中断溢出标志
}
/**********************************************************************************************************/
//定时器1
void zd3() interrupt 3          //T1中断用来扫描数码管和计800MS启动模块
{
    TH1=0xf8;
    TL1=0x30;                 //定时2ms
    Key_();                    //扫描按键
    Display();                //扫描显示
    timer++;                //变量加
    if(timer>=400)            //400次就是800ms
    {
        timer=0;
        trig=1;                      //800MS  启动一次模块
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        trig=0;
    }
}
/**********************************************************************************************************/
//主函数
void main(void)
{  
    TMOD=0x11;           //设T0为方式1
    TH0=0;
    TL0=0;         
    TH1=0xf8;           //2MS定时
    TL1=0x30;
    ET0=1;                //允许T0中断
    ET1=1;               //允许T1中断
    TR1=1;               //开启定时器
    EA=1;                    //开启总中断
  j=0;   
   
   
    while(1)
    {
      duwendu();
      while(j!=5)
      {
      
        
                                      
          while(!echo);        //当上次接收完波后,RX引脚是低电平,取反就是1,此while成立,反复判断echo状态。当echo没有接收到返回波时是高电平,取反就是0,此while不成立,跳出
          TR0=1;            //开启计数
          while(echo);        //当echo没有接收到返回波,此while成立,程序停在这里一直判断echo状态。当RX接收到返回波,RX引脚变为低电平,此while不成立,跳出
          TR0=0;            //停止计数
          distance[j]=Conut();            //计算
            S2=S2+distance[j];
            j=j+1;
       }
         S2=S2/5;
         Display();
        
    }
}
                          
超声波测距.7z (147.51 KB, 下载次数: 3)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表