注册 登录
编程论坛 单片机编程

急需请帮助--修改程序---51智能小车超声波避障数码管显示距离PWM调速--谢谢

BBOY愿愿 发布于 2016-06-26 14:20, 9295 次点击
因新手,所以我对于中断,定时,计数器等程序不知道怎么弄有点晕,如果能把这程序优化一下 再请帮加个PWM调速 就完美感谢了
 然后那个PWM就更不懂了   所以请各位帮我一下  谢谢

//晶振:11。0592
//接线:模块TRIG控制 接 P1.2        ECH0接收 接P1.1
//数码管:共阳数码管P0接数据口,P2.2 P2.1 P2.0 //P0.0 P0.1 接选通数码管
/***********************************************************************************************************/        
#include <reg52.h>        //器件配置文件
#include <intrins.h>
#include <math.h>
#define  uint  unsigned int
#define  uchar unsigned char
#define  RX  P1_1   
#define  TX  P1_2   
sbit P1_1 = P1^1;    //超声波接收IO   ECHO
sbit P1_2 = P1^2;       //超声波控制IO   TRIG

sbit in1 = P3^0;  //电机输入
sbit in2 = P3^1;
sbit in3 = P3^2;
sbit in4 = P3^3;  //直流电机     
uint  time=0;
uint  timer=0;
uchar posit=0;
unsigned long S=0;
bit      flag =0;
unsigned char code discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff/*-*/};
unsigned char code positon[3]={ 0xfe,0xfd,0xfb};
unsigned char disbuff[4]       ={ 0,0,0,0,};
uchar n,count,angle,left,right;//距离标志位,0.5ms次数,角度标识
void DelayMs(uchar t);
void DelayUs2x(uchar t);
void go();//前进
void turnleft();//左转
void turnright();//右转
void stop();//停车
void back();//后退
void chaoshengbo();
void Display(void);
void Conut(void);
/********************************************************/
    void Display(void)                 //扫描数码管
    {
     while(posit<2)
     {
      P0=discode[disbuff[posit]];
      P2=positon[posit];
      ++posit;
      DelayMs(3);
      }
      posit=0;
    }
/********************************************************/
void Conut(void)
    {
     time=TH0*256+TL0;
     TH0=0;
     TL0=0;
   
     S=(time*1.7)/100;     //算出来是CM
     if((S>=100)||flag==1) //超出测量范围显示“-”
     {     
      flag=0;
      disbuff[0]=10;       //“-”
      disbuff[1]=10;       //“-”
     }
     else
     {
      disbuff[0]=S%100/10;
      disbuff[1]=S%100%10;
     }      
    if(S>=30)
    {   
        go();//前进
    }
    else if(S<30 && S>20)
    {     
        turnright();
    }
    else if(S<=20)
    {
         stop();//停车
         back();//后退
    }
    TH1=0;
    TL1=0;//清除定时器0寄存器中的值*/
}        

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

void  main(  void  )  /////////////////////////////////////////////////////

{  
    TMOD=0x11;           //设T0为方式1,GATE=1//门控位;
    TH0=0;
    TL0=0;         
    TH1=0xf8;           //2MS定时
    TL1=0x30;
    ET0=1;             //允许T0中断
    ET1=1;               //允许T1中断
    TR1=1;               //开启定时器
    EA=1;               //开启总中断

    while(1)
    {
     chaoshengbo();
     Conut();            //计算     
     Display();                    //调用函数   数码管显示
    }
                 
}
     
void DelayUs2x(uchar t)
{   
    while(--t);
}
void DelayMs(uchar t)
{
    while(t--)
    {
        //大致延时1mS   
        DelayUs2x(245);
        DelayUs2x(245);
    }
}

void go()//前进
{
      in1=1;
      in2=0;
      in3=1;
      in4=0;
      DelayMs(10);//pwm调速
}

void back()//后退
{
    in1=0;
    in2=1;
    in3=0;
    in4=1;
}

void turnleft()//左转
{
    in1=0;
    in2=1;
    in3=1;
    in4=0;
}

void turnright()//右转
{
    in1=1;
    in2=0;
    in3=0;
    in4=1;
}

void stop()//停车
{
    in1=0;
    in2=0;
    in3=0;
    in4=0;
}

void chaoshengbo()
{   
         TX=1;//触发信号是高电平脉冲,宽度大于10us
         DelayUs2x(10);
         TX=0;
         while(!RX);         //当RX=P1_1  接收   为零时等待
         TR0=1;                //开启计数
         while(RX);            //当RX=P1_1  接收   为1计数并等待
         TR0=0;                //关闭计数

}
/********************************************************/
void zd0() interrupt 1          //T0中断用来计数器溢出,超过测距范围
  {
    flag=1;
    RX=0;
                                 //中断溢出标志
  }
/********************************************************/
   void  zd3()  interrupt 3          //T1中断用来扫描数码管和计800MS启动模块
  {
     TH1=0xf8;     //1111 1000        //2MS定时
     TL1=0x30;    // 0011 0000

     timer++;
     if(timer>=400)
     {
      timer=0;
      TX = 1;        //P1_2                    //800MS  启动一次模块
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      TX = 0;             //P1_2
     }
  }

19 回复
#2
BBOY愿愿2016-06-27 10:05
没人能解决吗
#3
hu9jj2016-06-27 20:27
以下是引用BBOY愿愿在2016-6-27 10:05:49的发言:

没人能解决吗

不同的开发板使用的端口和配置是不一样的,别人最多是给你思路,除非有与你相同的开发板。
#4
BBOY愿愿2016-06-27 20:29
回复 3楼 hu9jj
我用的是STC89C52   
#5
BBOY愿愿2016-06-27 20:31
回复 4楼 BBOY愿愿
就是思路比较混乱 找不到方向的那种感觉   如果思路清晰的话 我就能编程
#6
BBOY愿愿2016-06-27 20:33
只有本站会员才能查看附件,请 登录



这是STC89C52的原理图
#7
BBOY愿愿2016-06-28 15:16
有没有人懂软件延时的   能说下思路吗
#8
BBOY愿愿2016-06-28 22:05
自己改了一下   PWM实在搞不来    想用软件延时来实现  调速   


请求各位能帮我改下吗    外部中断0  和定时器1   我晕的
#9
BBOY愿愿2016-06-28 22:05
#include <reg52.h>        //器件配置文件
#include <intrins.h>
#include <math.h>
#define  uint  unsigned int
#define  uchar unsigned char
#define  RX  ECHO
#define  TX  TRIG

sbit ECHO = P3^1;     
sbit TRIG = P3^2;

sbit in1 = P0^0;
sbit in2 = P0^1;
sbit in3 = P0^2;
sbit in4 = P0^3;
unsigned long S=0;     
uint  time=0;
uint  timer=0;
uchar posit=0;
uint flag =0;
uchar code discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff/*-*/};
uchar code positon[3]={ 0xfe,0xfd,0xfb};
uchar disbuff[4]       ={ 0,0,0,0,};
void DelayMs(uchar t);
void DelayUs2x(uchar t);
void go();//前进
void turnleft();//左转
void turnright();//右转
void stop();//停车
void back();//后退
void delay(uint z);  //延时函数,调节电机转速
void chaoshengbo();
void Display();
void Conut();
/********************************************************/
    void Display()                 //扫描数码管
    {
     while(posit<2)
     {
      P0=discode[disbuff[posit]];
      P2=positon[posit];
      ++posit;
      DelayMs(3);
      }
      posit=0;
    }

void delay(uint z)  //延时函数,调节电机转速
{
    uint i,j;
    for(i=2;i>0;i--)
    for(j=z;j>0;j--);   
}
/********************************************************/
void Conut()
    {
     time=TH0*256+TL0;
     S=S/58;     //算出来是CM
     if(S>=100) //超出测量范围显示“-”
     {     
      flag=0;
      disbuff[0]=10;       //“-”
      disbuff[1]=10;       //“-”
     }
     else
     {
      disbuff[0]=S%100/10;
      disbuff[1]=S%100%10;
     }      
    if(S>=30)
    {   
       flag=0;             //前进
    }
    else if(S<30 && S>20)
    {     
         flag=3;          //左转
    }
    else if(S<=20)         
    {
         flag=4;          //停止
         flag=1;          //后退
    }
    TH1=0;
    TL1=0;//清除定时器0寄存器中的值
}        

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

void  main()  /////////////////////////////////////////////////////

{  
    TMOD=0x11;             //设T0为方式1,GATE=1//门控位;
    TH0=0;
    TL0=0;         
    TH1=0xf8;             //2MS定时
    TL1=0x30;
    EX0=1;               //允许INT0外部中断           ///////外部中断0///  
    ET1=1;                 //允许T1中断
    IT0=0;               //外部中断0   电平触发方式
    TR1=1;                 //启动定时器1                 /////////定时器1//////////
    EA=1;                 //启动总中断

    while(1)
    {
       switch(flag)
       {
    case 0:
            while(1)
            {
                go();
                if(flag!=0)                 //前进
                break;
            }
    case 1:
            while(1)
            {
                back();
                if(flag!=1)                 //后退
                break;
            }
    case 2:
            while(1)
            {
                turnleft();
                if(flag!=2)                 //左转
                break;
            }
    case 3:
             while(1)
            {
                turnright();
                if(flag!=3)                  //右转
                break;
            }
    case 4:
            while(1)
            {
                stop();
                if(flag!=4)                  //停车
                break;
            }
       }

    }
                 
}

     
void DelayUs2x(uchar t)
{   
    while(--t);
}
void DelayMs(uchar t)
{
    while(t--)
    {
        //大致延时1mS   
        DelayUs2x(245);
        DelayUs2x(245);
    }
}

void go()                //前进        0
{
      in1=1;
      in2=0;
      delay(10-3);         //PWM软件延时
      in3=1;
      in4=0;
}

void back()              //后退        1
{
    in1=0;
    in2=1;
    delay(10-1);
    in3=0;
    in4=1;
}

void turnleft()          //左转        2
{
    in1=0;
    in2=1;
    delay(10-1);
    in3=1;
    in4=0;
}

void turnright()         //右转        3
{
    in1=1;
    in2=0;
    delay(10-1);
    in3=0;
    in4=1;
}

void stop()              //停车        4
{
    in1=0;
    in2=0;
    in3=0;
    in4=0;
}

void chaoshengbo()
{   
         TX=1;               //发送控制位        触发信号是高电平脉冲,宽度大于10us
         DelayUs2x(10);
         TX=0;
         while(!RX);         //当RX=P1_1  接收   为零时等待
         TR1=1;                 //开启计数
         while(RX);            //当RX=P1_1  接收   为1计数并等待
         TR1=0;                //关闭计数

}
/********************************************************/
void timer0() /*interrupt 3 */         //T1中断    计数器1    溢出,超过测距范围
  {
     timer++;
     if(timer>=400)                       //800MS计时
     {
      chaoshengbo();
      timer=0;
      TX = 1;                               //800MS  启动一次模块
      TX = 0;                               //P1_2   发送控制位
     }                                        //中断溢出标志
      flag=1;
      RX=0;
  }
/********************************************************/
void INT0() interrupt 0          //INT0外部中断    用来扫描数码管和计800MS启动模块
{
     TH1=0xf8;     //1111 1000        //2MS定时
     TL1=0x30;    // 0011 0000
     
     Conut();                        //计算     
     Display();                    //调用函数   数码管显示 */
}
#10
BBOY愿愿2016-06-28 22:18
回复 9楼 BBOY愿愿
编译器说  我重复定义了  INTO   真不懂   急请教
#11
hu9jj2016-06-29 21:06
找到重复定义的行进行修改试试
#12
BBOY愿愿2016-06-30 16:52
#include <reg52.h>        //器件配置文件
#include <intrins.h>
#include <math.h>
#define  uint  unsigned int
#define  uchar unsigned char
sbit RX = P3^1;      //ECHO
sbit TX = P3^2;         //
sbit in1  = P1^0;
sbit in2  = P1^1;
sbit in3  = P1^2;
sbit in4  = P1^3;
unsigned long S=0;     
uint  time =0;
uint  timer=0;
uchar posit=0;
uint  flag =0;
uchar code discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff/*-*/};
uchar code positon[3]={ 0xfe,0xfd,0xfb};
uchar disbuff[4]={ 0,0,0,0,};

/***********************函数声明**************************/
void DelayMs(uchar t);
void DelayUs2x(uchar t);
void go();                 //前进
void turnleft();           //左转
void turnright();          //右转
void stop();               //停车
void back();               //后退
void delay(uint z);        //延时函数,调节电机转速
void chaoshengbo();
void Display();
void Conut();
/********************************************************/
    void Display()                 //扫描数码管
    {
     while(posit<2)
     {
      P0=discode[disbuff[posit]];
      P2=positon[posit];
      ++posit;
      DelayMs(3);
      }
      posit=0;
    }

void delay(uint z)  //延时函数,调节电机转速
{
    uint i,j;
    for(i=2;i>0;i--)
    for(j=z;j>0;j--);   
}
/********************************************************/
void Conut()
    {
     time=TH1*256+TL1;
     TH1=0;
     TL1=0;         //清除定时器1寄存器中的值
     S=time/58;     //算出来是CM
     if(S>=100)     //超出测量范围显示“-”
     {     
      //flag=0;
      disbuff[0]=10;       //“-”
      disbuff[1]=10;       //“-”
     }
     else
     {
      disbuff[0]=S%100/10;
      disbuff[1]=S%100%10;
     }
           
    if(S>=30)
    {   
       flag=0;             //前进
    }
    else if(S<30 && S>20)
    {     
         flag=3;          //左转
    }
    else if(S<=20)         
    {
         flag=1;          //后退
    }
}        

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

void  main()  /////////////////////////////////////////////////////

{  
   
    TMOD=0x11;             //设T0为方式1,GATE=1//门控位;
    TH0=0;
    TL0=0;         
    TH1=0xf8;             //2MS定时
    TL1=0x30;
    EX0=1;               //允许INT0外部中断           ///////外部中断0///  
    IT0=0;               //外部中断INT0               电平触发方式

    ET1=1;                 //允许T1中断
    TR1=1;                 //T1控制位TR1置1时,T1定时器工作;TR1置0时,T1停止工作

    ET0=1;                 //允许T0中断
    TR0=1;                 //T0控制位TR0置1时,T0定时器工作;TR0置0时,T0停止工作

    EA=1;                 //启动总中断
    while(1)
    {
       switch(flag)
       {
    case 0:   
            //stop();
            while(1)
            {
                go();
                if(flag!=0)                 //前进
                break;
            }
            break;
    case 1:
            stop();
            while(1)
            {
                back();
                if(flag!=1)                 //后退
                break;
            }
            break;
    case 2:
            //stop();
            while(1)
            {
                turnleft();
                if(flag!=2)                 //左转
                break;
            }
            break;
    case 3:     
            //stop();
             while(1)
            {
                turnright();
                if(flag!=3)                  //右转
                break;
            }
            break;
    case 4:
            stop();
            while(1)
            {
                if(flag!=4)                  //停车
                break;
            }
    break;
    default:
    break;
       }

    }
                 
}

     
void DelayUs2x(uchar t)
{   
    while(--t);
}
void DelayMs(uchar t)
{
    while(t--)
    {
        //大致延时1mS   
        DelayUs2x(245);
        DelayUs2x(245);
    }
}

void go()                //前进        0
{
      in1=1;
      in2=0;
      in3=1;
      in4=0;
      delay(10-3);         //PWM软件延时
      in1=0;
      in2=0;
      in3=0;
      in4=0;
      delay(3);         //PWM软件延时
}

void back()              //后退        1
{
    in1=0;
    in2=1;
    in3=0;
    in4=1;
    delay(10-3);
    in1=0;
    in2=0;
    in3=0;
    in4=0;
    delay(3);
}

void turnleft()          //左转        2
{
    in1=0;
    in2=1;
    in3=1;
    in4=0;
    delay(10-3);
    in1=0;
    in2=0;
    in3=0;
    in4=0;
    delay(3);
}

void turnright()         //右转        3
{
    in1=1;
    in2=0;
    in3=0;
    in4=1;
    delay(10-3);
    in1=0;
    in2=0;
    in3=0;
    in4=0;
    delay(3);
}

void stop()              //停车        4
{
    in1=0;
    in2=0;
    in3=0;
    in4=0;

}

     //T0中断    计数器0    溢出,超过测距范围
void  time1()  interrupt 3          //T1中断   用来扫描数码管和计800MS启动超声波模块
  {
     TH1=0xf8;                  //1111 1000        //2MS定时
     TL1=0x30;                  // 0011 0000
     timer++;
     if(timer>=400)
     {
      timer=0;
       TX = 1;        //P1_2                    //800MS  启动超声波模块
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      TX = 0;             //P1_2
      while(!RX);            //当echoRX=P1_1  接收   为零时等待
      TR1=1;                //开启计数
      while(RX);            //当RX=P1_1  接收   为1计数并等待
      TR1=0;                //关闭计数
     }
  }
/********************************************************/
void int0() interrupt 0             //INT0外部中断
{
     Conut();                        //计算
     Display();                     //调用函数   数码管显示     
}


/*    void chaoshengbo()
    {
    TX=1;               //TRIG 控制  触发信号是高电平脉冲,宽度大于10us
    DelayUs2x(10);
    TX=0;
    while(!RX);            //当echoRX=P1_1  接收   为零时等待
    TR0=1;                //开启计数
    while(RX);            //当RX=P1_1  接收   为1计数并等待
    TR0=0;                //关闭计数
    }      */
#13
BBOY愿愿2016-06-30 16:54
回复 12楼 BBOY愿愿
这次是改得差不多了    感觉还有点小问题     数码管显示不来 超声波所测的距离   


请教各路朋友
#14
BBOY愿愿2016-06-30 16:57
回复 13楼 BBOY愿愿
还有就是 自己对这个定时器/计数器和中断   



有点晕    懂的前辈 能指点一下吗
#15
hu9jj2016-07-01 06:04
大概是利用定时器/计数器对超声波测距的返回时间进行计数,然后根据返回时间计算出距离。但我没有看到计算距离和显示数值的程序哟。
#16
BBOY愿愿2016-07-02 12:20
回复 15楼 hu9jj
在Conut里面
void Conut()
    {
     time=TH1*256+TL1;
     TH1=0;
     TL1=0;         //清除定时器1寄存器中的值
     S=time/58;     //算出来是CM
     if(S>=100)     //超出测量范围显示“-”
     {     
      //flag=0;
      disbuff[0]=10;       //“-”
      disbuff[1]=10;       //“-”
     }
     else
     {
      disbuff[0]=S%100/10;
      disbuff[1]=S%100%10;
     }
#17
hu9jj2016-07-04 06:34
这段计算距离和转换成显示数据的程序非常简洁,值得借鉴。
#18
BBOY愿愿2016-07-05 14:44
回复 17楼 hu9jj
谢谢   

但是不行的
#19
hu9jj2016-07-07 15:45
检查一下数码管显示的代码看看。
#20
武汉Boy2018-02-12 07:37
一般来说用定时器产生一个占空比可变的方波就行了~

比如1秒输出高,一秒输出低~
1