51寻迹小车

集成了红外通信,超声波停车,寻迹,斑马线,迷宫的51单片机智能小车

小车可以通过红外实现小车最基本的前进、倒车、左右转向以及调速
、进入寻迹、迷宫、斑马线、超声波模式

如果接线或者调试方面有问题请联系作者

#include"reg51.h"
#include "intrins.h"
typedef  unsigned int  u16;
typedef  unsigned char u8;
 typedef unsigned long u32;
 
sbit QIN1=P1^0;//  P1.0输出pwm
sbit QIN2=P1^1;//  P1.1输出pwm
sbit QIN3=P1^2;//  P1.2输出pwm
sbit QIN4=P1^3;//  P1.3输出pwm
sbit HIN1=P1^4;//  P1.4输出pwm
sbit HIN2=P1^5;//  P1.5输出pwm
sbit HIN3=P1^6;//  P1.6输出pwm
sbit HIN4=P1^7;//  P1.7输出pwm

sbit IRIN=P3^2;  // 红外口为3.2 中断0


sbit k1=P2^0;    //寻迹模块k1位
sbit k2=P2^1;    //寻迹模块k2位
sbit k3=P2^2;    //寻迹模块k3位
sbit k4=P2^4;    //寻迹模块k4位
sbit k5=P2^5;    //寻迹模块k5位

sbit Echo = P3^0;  //超声波发射端
sbit Trig = P3^1;  //超声波接受端
  u8 i;  // 定义占空比的变量
u16 count,count2,count3,count4;  //pwm占空比(速度大小)
 u16 read1,read2;
u8 Time;
 u8 IrValue[6];    //红外接收数组
 u8 m=0,n=2,z=0,x=0;
 u8 d=0,b=0,c=0;
u16 tme = 0;  //超声波时间变量
u16 s = 0;    //超声波测距后的距离
u16 flg = 0;   


void StartModule(); 
void t0();
void Conut();

/********基本延时函数*******/
void delay(int u)
{
   while(u--);
}
/****小车转向需要的一些延时函数****/
void delayk2(int i)
{
 while(i){
 i--;
 if((k2==0)||(k3==0)||(k4==0))
 i=0; }
}
 void delayk3(int p)
{
 while(p){
 p--;
 if(k3==0)
 p=0; }
}
void delayk4(int o)
{
 while(o){
 o--;
 if((k4==0)||(k3==0)||(k2==0))
 o=0; }
}

void delayk5(int j)
{
 while(j){
 j--;
 if(k3==0||k4==0)
 j=0; }
}

void delayk6(int l)
{
 while(l){
 l--;
 if(k3==0||k2==0)
 l=0; }
}
void delayk7(int y)
{
 while(y){
 y--;
 if(k1==0||k4==0||k3==0||k5==0||k2==0)
 y=0; }
}





/********小车运行状态*******/
void fast_run()  //直行
{
   count=30;
count2=30;
count3=0;
count4=0;
}
  
void run()    //高速直行
{
    count=70;
count2=70;
count3=0;
count4=0;

} 
void srun()  //中速直行
{
    count=50;
count2=50;
count3=0;
count4=0;

}   
/****调试后需要的一些特殊转向状态****/
void bit_left()
{
count=30;
count2=0;
count3=0;
count4=45;
}
void bit_right()
{
count=0;
count2=30;
count3=45;
count4=0;
}
void middle_left()
{
count=35;
count2=0;
count3=0;
count4=45;
}
void middle_right()
{
count=0;
count2=35;
count3=45;
count4=0;
}
void left()
{
count=50;
count2=0;
count3=0;
count4=40;
}
void right()
{
count=0;
count2=50;
count3=40;
count4=0;
}
void behind_left()
{
count=40;
count2=0;
count3=0;
count4=50;
}
void behind_right()
{
count=0;
count2=40;
count3=50;
count4=0;
}


void back()   //倒退
{
 count=0;
count2=0;
count3=30;
count4=30;
}
 void zdt()    //从左面掉头
{
 count=50;
 count2=0;
 count3=0;
 count4=50;
}
void dt()    //从右面掉头
{
 count=0;
 count2=50;
 count3=50;
 count4=0;
}
void stop()   //停车
{
count=0;
count2=0;
count3=0;
count4=0;
}
/******走寻迹的函数****/
void xunji()
{  u8 flag;	  
 if((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1))    //没检测到,先直行再判断,flag=9时back;
{  z++;  
  	if(z>=80)
	{  if(x==1)
	   {flag=13;
	   x=0;}
	   if(x==2)
	  { flag=14;
	   x=0;	}
	   if(x==0);
  		flag=8;
		}
		else
		flag=0;
   }
 if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))  //中间感应到,直行
{ flag=0;	 z=0; }
 if((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1))	 //直行发生偏转,微调
 {flag=1;		 z=0;}
 if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1))	 //直行发生偏转,微调
 	{ flag=2;	 	 z=0;}			
 if((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1))	 //大幅度左转
	   {flag=9;	  z=0;	  }
	     if ((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0))			//大幅度右转
		 {flag=10;	  z=0;}


  if(((k1==1)&&(k2==0)&&(k3==0)&&(k4==0)&&(k5==1))||((k1==1)&&(k2==0)&&(k3==1)&&(k4==0)&&(k5==1))||	((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0))||	((k1==0)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1))||	((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==0))||	((k1==1)&&(k2==0)&&(k3==0)&&(k4==1)&&(k5==1))||	((k1==1)&&(k2==1)&&(k3==0)&&(k4==0)&&(k5==1)))   //意外情况,往前一点

  flag=5;

 if((k1==0)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1))    //behind左转
 flag=6;
  if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==0))    //behind右转
 flag=7;
  	 

  if((k1==0)&&(k3==0)&&(k4==1)&&(k5==1))	   //直角转向,左转
  {if(k2==0)
 flag=3;
 else
 flag=11; x=1;}
 if((k1==1)&&(k2==1)&&(k3==0)&&(k5==0)) //直角转向,右转
{ if(k4==0)
 flag=4;
 else
 flag=12;x=2; }
	

  switch(flag)
{	  
case(0):{fast_run();break;}
case(1):{bit_left();delayk3(500);break;}
case(2):{bit_right();delayk3(500);break;}
case(3):{delay(350);middle_left();delay(4);delayk2(3000);stop();delay(5);break;}
case(4):{delay(350);middle_right();delay(400);delayk4(3000);stop();delay(5);break;}
case(5):{fast_run();break;  }
case(6):{middle_left();delayk3(500);break;}
case(7):{middle_right();delayk3(500);break;}
case(8):{back();  delayk3(3000);delay(100);break;}
case(9):{middle_left();delayk5(500);break;}
case(10):{middle_right();delayk6(500);break;}
case(11):{delay(500);while(!k3);behind_left();delayk6(2000);break;}
case(12):{delay(500);while(!k3);behind_right();delayk5(2000);break;}
case(13):{back();delayk3(300);delay(100);zdt();delayk6();stop();delay(5);}
case(14):{back();delayk3(300);delay(100);dt();delayk5();stop();delay(5);}
default:{run();delay(50);stop();delay(50);break;}  	  
}
}









/*****斑马线函数*****/
void xuxian()
{  u8 flag;	  
 if((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1))    //没检测到,先直行再判断,flag=9时back;
{  z++;  
  	if(z>=80)
	flag=8;
		else
		flag=0;
   }
 if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))  //中间感应到,直行
{ flag=0;	 z=0; }
 if((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1))	 //直行发生偏转,微调
 {flag=1;		 z=0;}
 if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1))	 //直行发生偏转,微调
 	{ flag=2;	 	 z=0;}			
 if((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1))	 //大幅度左转
	   {flag=9;	  z=0;	  }
	     if ((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0))			//大幅度右转
		 {flag=10;	  z=0;}


  if(((k1==1)&&(k2==0)&&(k3==0)&&(k4==0)&&(k5==1))||((k1==1)&&(k2==0)&&(k3==1)&&(k4==0)&&(k5==1))||	((k1==0)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==0))||	((k1==0)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1))||	((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==0))||	((k1==1)&&(k2==0)&&(k3==0)&&(k4==1)&&(k5==1))||	((k1==1)&&(k2==1)&&(k3==0)&&(k4==0)&&(k5==1)))   //意外情况,往前一点

  flag=5;

 if((k1==0)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1))    //behind左转
 flag=6;
  if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==0))    //behind右转
 flag=7;
  	 

  if((k1==0)&&(k3==0)&&(k4==1)&&(k5==1))	   //直角转向,左转
  {if(k2==0)
 flag=3;
 else
 flag=11; }
 if((k1==1)&&(k2==1)&&(k3==0)&&(k5==0)) //直角转向,右转
{ if(k4==0)
 flag=4;
 else
 flag=12; }
	

  switch(flag)
{	  
case(0):{run();break;}
case(1):{bit_left();delayk5(500);break;}
case(2):{bit_right();delayk6(500);break;}
case(3):{delay(150);left();delay(200);delayk2(3000);stop();delay(5);break;}
case(4):{delay(150);right();delay(200);delayk4(3000);stop();delay(5);break;}
case(5):{fast_run();break;  }
case(6):{middle_left();delayk3(500);break;}
case(7):{middle_right();delayk3(500);break;}
case(8):{back();  delayk7(3000);delay(100);break;}
case(9):{middle_left();delayk5(1000);break;}
case(10):{middle_right();delayk6(1000);break;}
case(11):{delay(200);left();delay(200);delayk2(3000);stop();delay(5);break;}
case(12):{delay(200);right();delay(200);delayk4(3000);stop();delay(5);break;}
default:{run();delay(50);stop();delay(50);break;}  	  
}
}

/******迷宫函数****/
void migong()
{	  u8 cun,s=0;
	if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))
		{	cun=0;	z=0;  }
	if((k1==1)&&(k2==0)&&(k3==1)&&(k4==1)&&(k5==1))
		{	cun=8;		z=0;  }
	if((k1==1)&&(k2==1)&&(k3==1)&&(k4==0)&&(k5==1))
		{	cun=9;  	z=0; }
			if((k1==1)&&(k2==1)&&(k3==1)&&(k4==1)&&(k5==1))    //没检测到,先直行再判断,flag=9时back;
{  z++;  
  	if(z>=30)
  		cun=10;
		else
		cun=0;
   }
	if((k1==0)&&(k2==0)&&(k3==0)&&(k4==0)&&(k5==0))
	{
		while(!((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1)))
		{s++;}
	    if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))
			cun=2;
     else if((d==1)&&(b==0))
	{cun=2;  d=0;   b=0;	}
	 else if((d==0)&&(b==1))
	{cun=3;  d=0; 	 b=0;	}
     else 
		    cun=2; 
	}
	if((k1==0)&&(k2==0)&&(k3==0)&&(k4==1)&&(k5==1))
	{
			delay(200);
		if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))
		{  cun=4;  d++;}
		else { cun=5;	d=0;	b=0;	}
    }
	if((k1==1)&&(k2==1)&&(k3==0)&&(k4==0)&&(k5==0))
	{
			delay(200);
        if((k1==1)&&(k2==1)&&(k3==0)&&(k4==1)&&(k5==1))
		{  cun=6;	b++;}	 
	    else { cun=7;  d=0;	b=0;	}
    }	

switch(cun)
{
case(0):{fast_run();break;}
case(1):{middle_right();delay(400);delayk5(2000);stop();delay(5);break;}
case(2):{middle_left();delay(600);delayk2(2000);stop();delay(5);break;}
case(3):{middle_right();delay(600);delayk2(2000);stop();delay(5);break;}
case(4):{delay(50);middle_left();delay(500);delayk6(2000);stop();delay(5);break;}
case(5):{delay(150);middle_left();delay(400);delayk2(2000);stop();delay(5);break;}
case(6):{delay(50);middle_right();delay(500);delayk5(2000);stop();delay(5);break;}
case(7):{delay(150);middle_right();delay(400);delayk2(2000);stop();delay(5);break;}
case(8):{bit_left();delayk3(500);break;}
case(9):{bit_right();delayk3(500);break;}
case(10):{dt();break;}



default:{run();delay(50);stop();delay(50);break;}  	  
}

}






/*******************
* 功能:打开需要用到的中断
* 用到的中断:定时器0、1 工作方式1 16位定时器模式
* 外部终端0
*********************/
void timer()
{
 TMOD=0x11;//定时器0工作方式1
	TH0=0xff;//(65536-10)/256;//赋初值定时
	TL0=0xf7;//(65536-10)%256;//0.01ms
	TH1=0;
	TL1=0;
	EA=1;//开总中断
	ET0=1;//开定时器0中断
	ET1=1;
	TR0=1;//启动定时器0 
	IT0=1;
    EX0=1;
    IRIN=1;
}

/*********************************
*功能:接收红外信号并改为小车的运行状态
*输入:外部中断0  
*********************************/


void readjs()
{if(IrValue[2]!=0)	  
{read1=(IrValue[2]/16);
  read2=(IrValue[2]%16);	 
	 
	 if((read1==4)&&(read2==0))
	{ count+=10; count2+=10;n=2;   count3=0;count4=0;
	  if(count>=100)
	  count=100;
	    if(count2>=100)
	  count2=100;
	  }
		
		
	 if((read1==1)&&(read2==9))
	 {  if(count==0||count2==0)
		 {n=2;
}
else{
	count -= 10;count2 -= 10;n = 1;	  count3 = 0;count4 = 0;n = 2;
	  if(count<=9)
	  count=0;
	   if(count2<=9)
	  count2=0;
	  }}

		
	   if((read1==0)&&(read2==9))
	 {count3=40;count=0;count4=0;count2=40;n=2;
	  	 
	
	  }
		
		
	   if((read1==0)&&(read2==7))
	 {count=40;count4=40;count2=0;count3=0;n=2;
	 	
	
	  }


		 if((read1==1)&&(read2==12))
	 {count=100;count2=100;count3=0;count4=0;n=2;
	 	
	
	  }

		
		if((read1==1)&&(read2==8))
		{
      m=0;n=2; count=40;count2=40;count3=0;count4=0;
	}
	
		if((read1==5)&&(read2==2))
		{
      m=1;n=2;count3=50;count4=50;count=0;count2=0;
	}
	

	  if((read1==1)&&(read2==5))
	  {count=0;count2=0;count3=0;count4=0;  n=2;}
		
		
	if((read1==4)&&(read2==4))
	{
      n=0;
}	
 if((read1==4)&&(read2==7))
	{
      n=1;
}
 if((read1==4)&&(read2==3))
	{
      n=3;count=30;count2=30;count3=0;count4=0;
}
	if((read1==4)&&(read2==2))
	{
      n=4;
}
	  IrValue[2]=0;
		
						}
}



/*******主函数****/
void main()
{		
 	 timer();   //调用中断打开函数

while(1)
{
readjs();    /调用红外函数,注:要放在循环中不然无法使用
switch(n)
{
case(0):{xunji();break;}
case(1):{migong();break;}
case(3):{StartModule();
	     while(!Echo);		//当RX为零时等待
	     TR1=1;			    //开启
	     while(Echo);		//当RX为定时并等待
	     TR1=0;				//关闭
         Conut();
		 break;}			//计算
case(4):{xuxian();break;}
default:{break;}
}
}
}
 


/****定时器0溢出利用pwm调4个电机的速度***/
void tim0() interrupt 1
{
	//TR0=0;//赋初值时,关闭定时器
	TH0=0xff;//(65536-10)/256;//赋初值定时
	TL0=0xf7;//(65536-10)%256;//0.01ms,因为一个周期1us
	//TR0=1;//打开定时器
	i++;
	if(i>=100)  //1khz
	  i=0; 

	
	if(i<=count)   //占空比%30,可改
	  {QIN2=0; 
	   HIN4=0;
	   }  
	else {
	   QIN2=1;   
	   HIN4=1;
	}
		if(i<=count2)   //占空比%30,可改
	  {
	   QIN4=0; 
	   HIN2=0; 
	   }  
	else { 
	   QIN4=1;
	   HIN2=1;
	}

	
	
	
if(i<=count3)   //占空比%30,可改
	  {QIN1=0; 
	   HIN3=0;
	   }  
	else {
	   QIN1=1;   
	   HIN3=1;
	}
	
		if(i<=count4)   //占空比%30,可改
	  {
	   QIN3=0; 
	   HIN1=0; 
	   }  
	else { 
	   QIN3=1;
	   HIN1=1;
	}


	
	
	
	
	
	
   
}
/******超声波启动(发射超声波)*****/
 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_(); _nop_(); _nop_(); _nop_();
	  Trig=0;
}
void t0() interrupt 3 //T0中断用来计数器溢出,超过测距范围
{
    flg=1;			//中断溢出标志
}
/*****计算小车前端到障碍物的距离*****/
 void Conut()
{
	 tme=TH1*0x100+TL1;
	 TH1=0;
	 TL1=0;
	
	 s=(tme/58.0/100.0)*1000;     
	 if((s>=4000)||flg==1) //超出测量范围显示“-”
	 {	 
	  flg=0;
	 }
	 else if(s<=1000)
	 {
	  count=0;
	  count2=0;
	  count3=0;
	  count4=0;
	 }
}



/***红外接收函数***/
 void ReadIr() interrupt 0
{
	u8 j,k;
	u16 err;
	Time=0;					 
	delay(700);	//7ms
	if(IRIN==0)		//确认是否真的接收到正确的信号
	{	 
		
		err=1000;				//1000*10us=10ms,超过说明接收到错误的信号
		/*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
		侯,程序死在这里*/	
		while((IRIN==0)&&(err>0))	//等待前面9ms的低电平过去  		
		{			
			delay(1);
			err--;
		} 
		
		if(IRIN==1)			//如果正确等到9ms低电平
		{
			err=500;
			while((IRIN==1)&&(err>0))		 //等待4.5ms的起始高电平过去
			{
				delay(1);
				err--;
			}
			for(k=0;k<4;k++)		//共有4组数据
			{				
				for(j=0;j<8;j++)	//接收一组数据
				{

					err=60;		
					while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
					{
						delay(1);
						err--;
					}
					err=500;
					while((IRIN==1)&&(err>0))	 //计算高电平的时间长度。
					{
						delay(10);	 //0.1ms
						Time++;
						err--;
						if(Time>30)
						{
							return;
						}
					}
					IrValue[k]>>=1;	 //k表示第几组数据
					if(Time>=8)			//如果高电平出现大于565us,那么是1
					{
						IrValue[k]|=0x80;
					}
					Time=0;		//用完时间要重新赋值							
				}
			}
		}
		if(IrValue[2]!=~IrValue[3])
		{
			return;
		}
	}			
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老尚嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值