为什么我的超声波模块,测出的距离大了10倍

2019-07-15 15:10发布

本帖最后由 mhx321 于 2016-1-10 18:10 编辑

为什么我的超声波模块,测出的距离大10倍了,实测过,刚好是大了10倍,程序哪里出问题了,贴来,各位帮忙分析一下
/********************************************************/
/*项目名称:单片机避障小车                              */
/*单片机:STC89C52RC                                     */
/*晶振频率:12MHz                                        */
/********************************************************/
#include <reg51.h>
#include <intrins.h>
#include <LCD1602.h>
#define uchar unsigned char
#define uint  unsigned int
#define  ulong  unsigned  long
/************STC单片机特殊功能寄存器定义*****************/
sfr T2CON=0xC8;          //定时器2控制寄存器
sbit TF2=T2CON^7;
sbit TR2=T2CON^2;
sbit ET2=IE^5;         //定时器2中断控制位
sfr T2MOD=0xC9;
sfr RCAP2L=0xCA;
sfr RCAP2H=0xCB;
sfr TL2=0xCC;
sfr TH2=0xCD;
sfr IPH=0xB7;  //中断优先级控制寄存器高         定时器2优先中断IPH=0x20   IP=0x20
/*************端口定义**********************************/
sbit Sevro_moto_pwm=P3^5;  //接舵机信号端输入PWM信号调节速度
sbit Trig=P3^1;            //超声波控制端
sbit Echo=P3^2;            //超声波接收端
sbit IN1=P1^0;                           //左边电机驱动口
sbit IN2=P1^1;                           //左边电机驱动口
sbit IN3=P1^2;                           //右边电机驱动口
sbit IN4=P1^3;             //右边电机驱动口
sbit INA=P1^4;             //左边电机使能端
sbit INB=P1^5;             //右边电机使能端
sbit IR1=P3^6;             //左边红外距离检测
sbit IR2=P3^7;             //右边红外距离检测
/********************************************************/
/*************寄存器定义*********************************/
#define Left_moto_go      {IN1=1,IN2=0;}    //左边电机向前走
#define Left_moto_back    {IN1=0,IN2=1;}    //左边电机向后走
#define Left_moto_Stop    {IN1=0,IN2=0;}    //左边电机停转
#define Right_moto_go     {IN3=1,IN4=0;}    //右边电机向前走
#define Right_moto_back   {IN3=0,IN4=1;}    //右边电机向后走
#define Right_moto_Stop   {IN3=0,IN4=0;}    //右边电机停转

//测距相关寄存器定义
bit time_Up;  //溢出标志
uint time;  //时间
ulong S=0; //距离
ulong S1=0;
ulong S2=0;
ulong S3=0;
ulong S4=0;
bit busy_flag=0;    //测距中标志
bit succeed_flag=0;  //测量成功标志
bit Error_flag=0;    //测距出错标志
delay_flag=0;  //延时标志
delay_cnt=0;  //延时计数器
//舵机
uint  timer=0;                        //延时基准变量
uchar pwm_val_left  = 0;//变量定义
uchar push_val_left =14;//舵机归中,产生约,1.5MS 信号
/********************************************************/
/*********延时函数***************************************/
void Delay1ms(uint i)    //1ms延时程序
{
        uchar j;
        while(i--)
        {
                for(j=0;j<125;j++)
                { ; }
        }
}
void delay(unsigned int k)          //延时函数
{   
     unsigned int x,y;
           for(x=0;x<k;x++)
             for(y=0;y<2000;y++);
}
/********************************************************/
void Delay20us()                //@12.000MHz
{
        unsigned char i;

        _nop_();
        i = 7;
        while (--i);
}

/*****转换显示三位数*************************************/
void LCD_dis_3BIT(uchar x,uchar y,ulong dis_dat)  //列,行,转换显示三位十进制数
{
    GotoXY(x,y);
        LCD1602_Write(LCD1602_data,dis_dat%1000/100+0x30); //百位
        LCD1602_Write(LCD1602_data,dis_dat%1000%100/10+0x30); //十位
        LCD1602_Write(LCD1602_data,dis_dat%1000%10%10+0x30); //个位
}
/**********测距初始化程序********************************/
void  SR04_init()
{
        TMOD = 0x11;//超声波就用定时器0
        EA = 1;     //开总中断
        ET0 = 0;    //如果ET0=1计数器中断可以记录中断次数,也就是扩展计数器位数,
                    //计数为 0-需要大(>65535用中断再计数)如果ET0=0计数器,计数为 0-65535               
        TR0 = 0;
        TF0 = 0;
        EX0 = 0;
        IT0 = 0;    //低电平触发
}
/************************启动测距************************/
void  StartModule()                       //启动测距信号
{
        Trig=1;                                       
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        Trig=0;  
        while(!Echo);                       //当RX为零时等待
        succeed_flag=0;  //测量成功标志
        EX0 = 1;
        TR0=1;                               //开启计数
}
/********************************************************/
void Conut(void)                   //计算距离
{   
        time=TH0*256+TL0;                   //读取脉宽长度
        TF0=0;
        TH0=0;
        TL0=0;
        S=(time*1.7)/100;          //算出来是CM
        if(S>=400)
        {
                S=400;
        }
        LCD_dis_3BIT(6,1,S);//显示距离           

}
/*************************************************/
/************外部中断0服务程序********************/
void Int0(void) interrupt 0
{
        TR0 = 0;//关闭定时器
    succeed_flag = 1;//至成功测量的标志
        EX0 = 0;//关闭外部中断        
}
/************************************************************************/
//前速前进
void  run(void)
{                                   
         Left_moto_go ;     //左电机往前走
         Right_moto_go ;    //右电机往前走
}
/************************************************************************/
//前速后退
void  backrun(void)
{
         Left_moto_back ;   //左电机往后走
         Right_moto_back ;  //右电机往后走
}
/************************************************************************/
//左转
void  leftrun(void)
{
         Left_moto_back ;   //左电机往后走
          Right_moto_go ;   //右电机往前走
}
/************************************************************************/
//右转
void  rightrun(void)
{
         Left_moto_go ;     //左电机往前走
         Right_moto_back ;  //右电机往后走
}
/************************************************************************/
//STOP
void  stoprun(void)
{
         Left_moto_Stop ;   //左电机停走
         Right_moto_Stop ;  //右电机停走
}
/************************************************************************/
/******************舵机控制**********************************************/
void  COMM( void )         //方向函数              
{         
        push_val_left=55;          //舵机向左转90度        5
        timer=0;
        while(timer<=4000); //延时400MS让舵机转到其位置                 4000
        StartModule();          //启动超声波测距
        Conut();                           //计算距离
        S2=S;  
        
        push_val_left=14;          //舵机向右转90度 23
        timer=0;
        while(timer<=4000); //延时400MS让舵机转到其位置
        StartModule();          //启动超声波测距
        Conut();                          //计算距离
        S4=S;         
        push_val_left=33;          //舵机归中 14
        timer=0;
        while(timer<=4000); //延时400MS让舵机转到其位置
        
        StartModule();          //启动超声波测距
        Conut();                          //计算距离
        S1=S;         
        
        if((S2<20)||(S4<20)) //只要左右各有距离小于,20CM小车后退
        {
                backrun();                   //后退
                timer=0;
                while(timer<=4000);
        }
        
        if(S2>S4)                 
        {
                rightrun();          //车的左边比车的右边距离小        右转        
                timer=0;
                while(timer<=4000);
        }                                      
        else
        {
                leftrun();                //车的左边比车的右边距离大        左转
                timer=0;
                while(timer<=4000);
        }
                                             

}
/***************舵机PWM初始化程序******************************************/
void Servo_PWM_init(void)                  //定时器2为16位自动重载模式
{
        T2MOD = 0;                //初始化模式寄存器
        T2CON = 0;                //初始化控制寄存器
        TL2=RCAP2L=(65536-100)%256;  //设置定时初值和定时重载值
        TH2=RCAP2H=(65536-100)/256;
//        IPH=0x20; //定时器2为最高优先级
//        IP=0x20;
        ET2=1;          //定时器2中断开
        TR2 = 1;                //定时器2开始计时
        EA=1;
}
/************************************************************************/
/*                    PWM调制舵机转速                                   */
/************************************************************************/
/*调节push_val_left的值改变舵机转速,占空比            */
void pwm_Servomoto(void)
{  

    if(pwm_val_left<=push_val_left)
               Sevro_moto_pwm=1;
        else
               Sevro_moto_pwm=0;
        if(pwm_val_left>=200)
        pwm_val_left=0;

}
/***************************************************/
///*定时器2中断服务子函数产生PWM信号*/
void timer2() interrupt 5
{        
     timer++;                                  //定时器100US为准。在这个基础上延时
         pwm_val_left++;
         pwm_Servomoto();                  //舵机转向调整
}
/***************************************************/
/************主程序**************************************/
void main()
{
    LCD1602_init();  //初始化程序
        GotoXY(0,0);  
        Print("current distance");
    GotoXY(0,1);
        Print("         cm     ");
        Servo_PWM_init();  //舵机初始化程序
        push_val_left=33;  //中间为33  左边        55  右边14

        while(1)
        {
                if(timer>=1000)          //100MS检测启动检测一次         1000
                {
                   timer=0;
                   if(busy_flag==0)    //测距中标志
                   {
                       busy_flag=1;    //测距中标志
                           StartModule(); //启动检测
                   }
                   if(succeed_flag==1)  //测量成功标志
                   {
                       succeed_flag=0;  //测量成功标志
                           Conut();                  //计算距离
                           if(S<20)                  //距离小于20CM
                           {
                                   stoprun();          //小车停止
//                                   COMM();                   //方向函数
                           }
                           else
                           if(S>30)                  //距离大于,30CM往前走
                           run();
                           busy_flag=0;    //测距中标志
                   }
                }                 
        }
}
/********************************************************/
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
10条回答
零tot
2019-07-16 05:39
我也是菜鸟,我提供一下我的思路,遇到这种问题的话,一般我的话先看一下是否可以避免中断的影响,如果是超声脉冲计时有问题的是否可以在进行pwm控制中断程序是进去暂停结束后在开始超声脉冲的计时,还有一种的话测量需要,pwm也一直需要,是否可以将处理放到中断里(处理的周期比较长,造成的影响应该就小多了),主函数跑pwm;

一周热门 更多>