基于51单片机的超声波避障小车(HC-SR04,SG90舵机)

+

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


一、HC-SR04超声波模块

基于51单片机的超声波避障小车(HC-SR04,SG90舵机)_第1张图片

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

#include  

整体测量距离函数

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舵机

基于51单片机的超声波避障小车(HC-SR04,SG90舵机)_第3张图片
sg90舵机的三根线买回来是连在一起的可将塑料头拆开方便接入单片机
基于51单片机的超声波避障小车(HC-SR04,SG90舵机)_第4张图片

SG90舵机时序图
基于51单片机的超声波避障小车(HC-SR04,SG90舵机)_第5张图片
该舵机的控制信号为周期是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 
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  							
#include 			//用于使用了_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!!!----------------------------
  • [√ ] 点赞+收藏

你可能感兴趣的:(51单片机,嵌入式硬件,单片机)