基于51单片机的超声波避障小车:HC-SR04与SG90舵机配合实现

+

  • 一、HC-SR04超声波模块
  • 二、SG90舵机
  • 三.总程序编写

  • 一、HC-SR04超声波模块

    HC-SR04时序图

    触发信号输入端(Trig)输入一个10微秒以上的高电平信号,超声发送口收到信号自动发送8个40Hz方波,同时启动 定时器 ,待传感器接收到回波则停止 计时 并输出回响信号,回响信号脉冲宽度与所测距离正比。. 根据时间间隔可以计算距离,公式:距离=(高电平时间*声速)/2。【来自
    由于Trig端要输入一个10微秒以上的函数所以要使用 intrins.h中的函数 nop();
    引入函数如下

    #include <intrins.h> 
    

    整体测量距离函数

    void hcsr04_Init()
    {
        Trig=1;//Trig端置1                      
        _nop_(); 
        _nop_(); 
        _nop_(); 
        _nop_(); 
        _nop_();
        _nop_(); 
        _nop_(); 
        _nop_(); 
        _nop_(); 
        _nop_(); 
        _nop_();//等待10us以上                      
        Trig=0;//Trig端置0
        while(!Echo);    //当Echo端为0时等待           
        TR0=1;           //定时器0置1 开始计时              
        while(Echo);     //当Echo为1时 计时并等待                
        TR0=0;           //关闭定时器0 结束计时                
    }
    void distance(void)		//超声波模块计算距离
    {
        time=TH0*256+TL0; //将计时器记录的时间存入time中         
        TH0=0;         //计时器清零
        TL0=0;                                 
        Distance=(time*1.8)/100;//计算距离      
    }
    

    二、SG90舵机


    sg90舵机的三根线买回来是连在一起的可将塑料头拆开方便接入单片机

    SG90舵机时序图

    该舵机的控制信号为周期是20ms 的脉宽调制(PWM)信号,脉冲宽度从0.5ms-2.5ms,相对应舵盘的位置为0—180度。
    如上图可知
    当脉冲宽度为0.5ms舵机旋转0度
    当脉冲宽度为1ms舵机旋转45度
    当脉冲宽度为1.5ms舵机旋转90度
    当脉冲宽度为2ms舵机旋转135度
    当脉冲宽度为2.5ms舵机旋转180度
    接线说明
    红线为vcc端接入单片机5v端
    橙线为pwm信号线参考程序定义接入
    棕线为gnd端接入单片机GND端

    #include <REG51.H>
    typedef unsigned char uchar;   //偷懒 只为少敲些键盘
    typedef unsigned int uint;     
    
    uchar angle;      
    sbit PWM = P3^5;  //pwm信号端也就是舵机的黄色线
    uchar count = 0;	//计算周期
    
    void delay_ms(uint c)   //延迟函数 延迟1ms
    {
        uint a,b;
        for(;c>0;c--)
            for(b=102;b>0;b--)
                for(a=3;a>0;a--);
    }
    
    void Time0_Init()          //定时器初始化
    {
            TMOD = 0x01;           //定时器0工作在方式1
            TH0  = 0xfe;           //装入初值 0.5ms中断一次 
            TL0  = 0x33;
            EA = 1;
            ET0 = 1;            
            TR0=1;                 //定时器置1打开
    }
    
    void main()
    {
        Time0_Init();
    
        while (1)
        {
            count = 0;
            angle = 1; //归零   1--0 2--45 3--90 4--135 5--180
            delay_ms(1000);
            count = 0;
            angle = 2; //旋转45度
            delay_ms(1000);
    		count = 0;
            angle = 3; //旋转90度
            delay_ms(1000);
    		count = 0;
            angle = 4; //旋转135度
            delay_ms(1000);
    		count = 0;
            angle = 5; //旋转180度
            delay_ms(1000);
        }
    }
    
    void timer0() interrupt 1
    {
        TR0 = 0;  //关闭计时器0
        TH0  = 0xfe;
        TL0  = 0x33;                   //11.0592MZ晶振,0.5ms
    
        if(count<=angle)   
        {
            PWM = 1;
        }
        else
        {
            PWM = 0;
        }
        if(count==40)   //一个周期为20ms  
        {
            count = 0; //周期达到20ms 清零重新计时
        }
        count ++;
        TR0 = 1;  //开启计时
    }
    

    三.总程序编写

    #include <reg51.h> 							
    #include <intrins.h>			//用于使用了_nop()_函数
    
    #define uchar unsigned char				
    #define uint	unsigned int			
    
    sbit IN1	=P1^0;
    sbit IN2	=P1^1;
    sbit IN3	=P1^2;
    sbit IN4 	=P1^3;			
    
    sbit Echo = P2^5;				//超声波模块 Echo端接单片机P2.5
    sbit Trig = P2^6;				//超声波模块 Trig端接单片机P2.6
    
    sbit pwm= P2^4;            //舵机信号端定义
    
    void turnleft();
    void turnright();
    void straight();
    void stop();
    void count();
    void run();
    void hcsr04();
    void delayms(uint ms);
    
    uint time = 0;   //测距数据,距离所用时间变量							   
    uint Distance = 0;												//距离
    uchar flag =0;				//定时器0溢出标志
    uchar angle;
    uint counter=0;
    
    
    void  main()
    {  
    	TMOD|=0x11;		   			//定时器0定时器1,工作方式1
    	TH0=0;                   //定时器0用于超声波测距
    	TL0=0;          
    	TH1=0xFE;		   				//定时器1用于控制舵机  0.5ms定时
    	TL1=0x33;
    	ET0=1;            		//定时器0中断使能
    	ET1=1;			   				//定时器1中断使能
    	TR1=1;			   				//定时器1开始计时
    	EA=1;			   					//开启总中断
    	angle = 3;
    	while(1)
    	{
    		hcsr04();						
    		count();					 //计算距离
    		run();
    	}
    }
    
    void delay_ms(uint c)   //延迟函数 延迟1ms
    {
        uint a,b;
        for(;c>0;c--)
            for(b=102;b>0;b--)
                for(a=3;a>0;a--);
    }
    
    void run()  //测定距离为15cm  当大于小于15cm是舵机的转向和小车的前进方向
    {
    	if(angle ==3 && Distance >= 15)
    	{
    		straight();
    		hcsr04();
    		count();
    	}
    	else if(angle ==3 && Distance < 15)
    	{
    		stop();
    		angle = 2;
    		delay_ms(20);
    		hcsr04();
    		count();
    	}
    	if(angle == 2 && Distance >=15)
    	{
    		turnright();
    		delay_ms(50);
    		angle=3;
    		delay_ms(20);
    		hcsr04();
    		count();
    	}
    	else if(angle == 2 && Distance < 15)
    	{
    		angle = 4;
    		delay_ms(20);
    		hcsr04();
    		count();
    	}
    	if(angle == 4 && Distance >=15)
    	{
    		turnleft();
    		delay_ms(50);
    		angle =3;
    		delay_ms(200);
    		hcsr04();
    		count();
    	}
    	else if(angle == 4 && Distance <15)
    	{
    		angle =3;
    		delay_ms(20);
    		hcsr04();
    		count();
    	}
    }
    void straight()	
    {
    	IN1 = 1;
    	IN2 = 0;
    	IN3 = 0;
    	IN4 = 1;
    }
    void turnleft() 
    {
    	IN1 = 1;
    	IN2 = 0;
    	IN3 = 1;
    	IN4 = 0;
    }
    void turnright()	
    {
    	IN1 = 0;
    	IN2 = 1;
    	IN3 = 0;
    	IN4 = 1;
    }
    void hcsr04()
    {
    	Trig=1;			              
    	_nop_(); 
    	_nop_(); 
    	_nop_(); 
    	_nop_(); 
    	_nop_();
    	_nop_(); 
    	_nop_(); 
    	_nop_(); 
    	_nop_(); 
    	_nop_(); 
    	_nop_(); 						//等待大于10us
    	Trig=0;
    	while(!Echo);				//当Echo为零时等待
    	TR0=1;			    			//开启计数
    	while(Echo);					//当Echo为1时,计时并等待
    	TR0=0;								//关闭计时
    }
    void count(void)
    {
    	time=TH0*256+TL0;		//定时器的值放在time中
    	TH0=0;
    	TL0=0;					//清零定时器0
    	Distance=(time*1.8)/100;      //计算距离
    }
    void Tmr0_isr() interrupt 1  //T0中断用来计数器溢出,超过测距范围
    {
    	flag=1;							 			 //中断溢出标志
    }
    
    void Tmr1_isr() interrupt 3 //T1中断用来控制舵机
    {
        TR1 = 0;  //关闭计时器0
        TH1  = 0xfe;
        TL1  = 0x33;                   //11.0592MZ晶振,0.5ms
    
        if(counter<=angle)   
        {
            pwm = 1;
        }
        else
        {
            pwm = 0;
        }
        if(counter==40)   //一个周期为20ms  
        {
            counter = 0; //周期达到20ms 清零重新计时
        }
        counter ++;
        TR1 = 1;  //开启计时
    }  
    

    对于小车方向程序及烧录问题可转【基于51单片机的遥控小车

    --------------------------  END!!!----------------------------
    
  • [√ ] 点赞+收藏
  • 物联沃分享整理
    物联沃-IOTWORD物联网 » 基于51单片机的超声波避障小车:HC-SR04与SG90舵机配合实现

    发表评论