打印
[51单片机]

为什么STC12C5A60S2超声波测距输出高电平计时过长?

[复制链接]
5210|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xiaoliping1945|  楼主 | 2013-8-21 22:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 xiaoliping1945 于 2013-8-22 09:07 编辑

下面是用STC12C5A60s2用查询法测距代码,请教下大神们,为什么测出来的距离不对,有时候还在while()处执行不下去,这是什么原因啊?超声波模块式好的,而且超声波输出的高电平与距离的比例是对的,就是输入单片机以后就不行了。测出来有问题。求指点,谢谢!
#include<stc12c5a60s2.h>
#include<intrins.h>
#include"lcd_1602.h"

#define first 0x00            //1602第1行
#define second  0x40   //1602第2行

sbit RX=P3^7;         //echo        接收端
sbit TX=P1^0;         //trig         发送端

uint distance=0,time;


uchar  code  table[]="0123456789";
uchar   juli[]="000.0cm";
/************函数声明**************/
void    Delay20us();
void    init(void);   //初始化
void    chuli(uint range);//数据处理
uint     sonic();    //超声波测距
void    send();    //发送20us高电平脉冲
void    Clr_timer();//定时器清零
void main()
{
           init();        //初始化
          init_lcd();
           while(1)
                   {                                            
                 distance=sonic();
                 chuli(distance);
                lcd_1602(first,0,juli);
                             delay(500);                //0.5秒测一次                              
                               }
}
void init(void)
{        
     TMOD = 0x01;         // 超声用定时器
     EA = 1;
     ET0 = 1;
           TR0=0;
         TF0=0;
         RX=1;                 //置1,作为输入端
         TX=0;
}
void send()                //发送端TRI发送20us高电平
{
    TX = 0;
        Delay20us();
    TX=1;
        Delay20us();
   TX=0;
}
void Clr_timer()
{
    TH0=0;
    TL0=0;
    TF0=0;
}
uint  sonic()
{
                unsigned int ceju1;
             Clr_timer();//定时器清零
             Delay20us();
                 send();//发送20us的高电平                             
             while(!RX) ;   //等待接收端变为高电平
                 TR0=1;                //启动计数
             while(RX);   //等待接收端变为低电平
                     TR0=0;           //停止计数
             if(TF0)
                ceju1=9999;//溢出,距离过长,放弃,置为无效数据
             else
                     {
                       time=TH0*256+TL0; //得到距离所用时间   TH1=0;TL1=0;             //定时器清零
                        ceju1=time*0.172+0.5; //放大10倍,取一位小数
                      }
             if(ceju1>5000)                  //大于5米,超出测距范围,置为无效数据
                           ceju1=9999;  
        return   ceju1;
}
void chuli(uint range)//数据处理
{
        juli[0]=table[range/1000];
        juli[1]=table[range%1000/100];
        juli[2]=table[range%100/10];
        juli[4]=table[range%10];         
                delay(10);
}
void Delay20us()                //@12MHz
{
        unsigned char i;
        i = 7;
        while (--i);
}

相关帖子

沙发
kkzz| | 2013-8-21 23:16 | 只看该作者
  while(!RX) ;   //等待接收端变为高电平
                 TR0=1;                //启动计数
             while(RX);   //等待接收端变为低电平
                     TR0=0;           //停止计数

使用特权

评论回复
板凳
kkzz| | 2013-8-21 23:16 | 只看该作者
你的超出延时判断可以在这里判断的。

使用特权

评论回复
地板
hudi008| | 2013-8-21 23:31 | 只看该作者
你的定时器分频计算进去了么?

使用特权

评论回复
5
hudi008| | 2013-8-21 23:32 | 只看该作者
时间是需要除以二的。

使用特权

评论回复
6
xiaoliping1945|  楼主 | 2013-8-22 08:44 | 只看该作者
hudi008 发表于 2013-8-21 23:32
时间是需要除以二的。

除了的,在计算距离的地方已经除过2

使用特权

评论回复
7
xiaoliping1945|  楼主 | 2013-8-22 08:45 | 只看该作者
hudi008 发表于 2013-8-21 23:31
你的定时器分频计算进去了么?

内部定时器默认是12分频,也就是1M,1us计数一次,最大计数65.536ms

使用特权

评论回复
8
xiaoliping1945|  楼主 | 2013-8-22 08:49 | 只看该作者
kkzz 发表于 2013-8-21 23:16
你的超出延时判断可以在这里判断的。

测出的数据部稳定,而且相当不对,过一会就卡住,在while()处执行部下去,也就是IO口的电平变化查询不到了。求解,求参考程序,谢谢!

使用特权

评论回复
9
trumpxp| | 2013-8-22 19:48 | 只看该作者
超声波测距这一块   了解的不多   楼主   这一块没能帮上你的忙   对不住啊

使用特权

评论回复
10
hudi008| | 2013-8-22 21:50 | 只看该作者
xiaoliping1945 发表于 2013-8-22 08:44
除了的,在计算距离的地方已经除过2

那应该不会计算出错的。

使用特权

评论回复
11
hudi008| | 2013-8-22 21:51 | 只看该作者
xiaoliping1945 发表于 2013-8-22 08:44
除了的,在计算距离的地方已经除过2

你的超市判断做过了么?

使用特权

评论回复
12
hudi008| | 2013-8-22 21:52 | 只看该作者
13
xiaoliping1945|  楼主 | 2013-8-22 22:09 | 只看该作者
hudi008 发表于 2013-8-22 21:52
http://wenku.baidu.com/view/f767196faf1ffc4ffe47ac66.html

问题已解决,不过还是谢谢各位

使用特权

评论回复
14
xiaoliping1945|  楼主 | 2013-8-22 22:11 | 只看该作者
trumpxp 发表于 2013-8-22 19:48
超声波测距这一块   了解的不多   楼主   这一块没能帮上你的忙   对不住啊

问题已解决,感谢,就是上面的程序,发帖上来发对了,自己电脑上的还回值弄错了,呵呵!看了好久才看出来

使用特权

评论回复
15
hudi008| | 2013-8-22 22:29 | 只看该作者
xiaoliping1945 发表于 2013-8-22 22:09
问题已解决,不过还是谢谢各位

不客气的,能解决就好的。

使用特权

评论回复
16
kkzz| | 2013-8-27 14:31 | 只看该作者
xiaoliping1945 发表于 2013-8-22 08:49
测出的数据部稳定,而且相当不对,过一会就卡住,在while()处执行部下去,也就是IO口的电平变化查询不到 ...

以前修改过百度文库上程序,你可以搜搜看的。

使用特权

评论回复
17
cjhk| | 2013-8-27 18:36 | 只看该作者
这一块   不是很了解啊    楼主   帮你顶一个   看看别人的意见   行吗  

使用特权

评论回复
18
xiaoliping1945|  楼主 | 2013-8-31 21:13 | 只看该作者
cjhk 发表于 2013-8-27 18:36
这一块   不是很了解啊    楼主   帮你顶一个   看看别人的意见   行吗

已经解决,就是上面的程序,对的!

使用特权

评论回复
19
cdma008| | 2013-11-15 00:52 | 只看该作者
楼主,有问题请教啊,最近我也在做这个,用的stc15系列,晶振30MHZ。不知道为何总是显示001。我用的是NOKIA5110。
我的部分程序,求助啊,谢谢啦:sbit  RX=P0^1;
sbit  TX=P0^2;
unsigned int  time=0;
unsigned long S=0;
bit      flag =0;
unsigned char disbuff[4] ={ 2,2,2,2,};


/*--------------------------------------------------------------*/
void delay1s(void)   //误差 -0.00000000006us
{
    unsigned char a,b,c,n;
    for(c=165;c>0;c--)
        for(b=218;b>0;b--)
            for(a=207;a>0;a--);
    for(n=8;n>0;n--);
    _nop_();  //if Keil,require use intrins.h
}

/*--------------------------------------------------------------*/


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

/********************************************************/
void Conut(void)                  //计算
        {
         int i,w;
         time=TH0*256+TL0;
         TH0=0;
         TL0=0;
       
         S=((time*1.7)/100)+1;     //算出来是CM                          
         if((S>=450)||flag==1) //超出测量范围显示“-”
         {         
          flag=0;
/*          disbuff[0]=9;           //“-”
          disbuff[1]=8;           //“-”
          disbuff[2]=7;           //“-”
          for(i=0;i<3;i++)
          {       
            w=disbuff[i];
            switch(w)
                {
                case 0:{LCD_prints(i+3,2,"0");}break;
                case 1:{LCD_prints(i+3,2,"1");}break;
                case 2:{LCD_prints(i+3,2,"2");}break;
                case 3:{LCD_prints(i+3,2,"3");}break;
                case 4:{LCD_prints(i+3,2,"4");}break;
                case 5:{LCD_prints(i+3,2,"5");}break;
                case 6:{LCD_prints(i+3,2,"6");}break;
                case 7:{LCD_prints(i+3,2,"7");}break;
                case 8:{LCD_prints(i+3,2,"8");}break;
                case 9:{LCD_prints(i+3,2,"9");}break;
                default : break;
                }
         }                */
         }
         else
         {
          disbuff[0]=S%1000/100;
          disbuff[1]=S%1000%100/10;
          disbuff[2]=(S%1000%10 %10);
          for(i=0;i<3;i++)
          {       
            w=disbuff[i];
            switch(w)
                {
                case 0:{LCD_prints(i+3,2,"0");}break;
                case 1:{LCD_prints(i+3,2,"1");}break;
                case 2:{LCD_prints(i+3,2,"2");}break;
                case 3:{LCD_prints(i+3,2,"3");}break;
                case 4:{LCD_prints(i+3,2,"4");}break;
                case 5:{LCD_prints(i+3,2,"5");}break;
                case 6:{LCD_prints(i+3,2,"6");}break;
                case 7:{LCD_prints(i+3,2,"7");}break;
                case 8:{LCD_prints(i+3,2,"8");}break;
                case 9:{LCD_prints(i+3,2,"9");}break;
                default : break;
                }
         }
         delay1s();delay1s();
         }
        }
/********************************************************/
     void zd0() interrupt 1                  //T0中断用来计数器溢出,超过测距范围
  {
    flag=1;                                                         //中断溢出标志
  }
/********************************************************/
   void  stmo()
  {         
             unsigned char a,b,c;
          TX=1;                                        //400MS  启动一次模块        从TX=1到TX=0有20us时间。                    
      for(c=1;c>0;c--)
        for(b=118;b>0;b--)
            for(a=1;a>0;a--);
      _nop_();  
          TX=0;
         
  }
/*********************************************************/

//主函数
void main(void)
{       
        unsigned char LCD_contrast = 0xc8;        //此值对比度合适

       

        LCD5510_Init();

        LCD_write_cmd(0x21);//工作模式, 水平寻址, 扩展指令
        LCD_write_cmd(0xbe);//对比度调节
        LCD_write_cmd(0x20);//工作模式, 水平寻址, 常规指令       

       
       

        while(1)
        {
        TMOD=0x01;                   //设T0为方式1
        TH0=0;
        TL0=0;         
        ET0=1;             //允许T0中断
        EA=1;                           //开启总中断                               
         LCD_prints(0,0,"Distant");
         stmo();                        //使能
         while(!RX);                //当RX为零时等待
         TR0=1;                            //开启计数0
         while(RX);                        //当RX为1计数并等待
         TR0=0;                                //关闭计数
     Conut();                        //计算
        }
       
}

使用特权

评论回复
20
angerbird| | 2013-11-16 21:34 | 只看该作者
看下你的计时部分的,计时器溢出的也会造成即使不准确的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

74

帖子

3

粉丝