stc89c52---循------车代码


//******************   说明:必看------仅仅提供给本实验室217-2使用,代码不成熟,不要外传。不要外传。
/*
1、本程序是用stc89C52RC或者stc89C51类普通的12T的单片机;如果用stc15系列增强版单片机,
需要调节波特率的函数以及定时的初值的计算;
2、本程序,利用定时器0产生PWM,以及延时使用;利用定时器1,产生蓝牙小车的波特率9600;定时器1不能挪作它用,已经使用了。
3、本程序,可以在定时器0里面,添加代码,比如定时1s,然后设置一个标记位,计算外部中断的次数,从而计算电机的速度或者行程
(这个部分自己添加);显示数据部分,自己学习我的视频,LCD1602的内容,完成;
4、本程序,利用四个循迹传感器,四个传感器一定要和实际的比赛场地,进行合理布局,建议中间两个夹着黑线,外面的和中间的稍微疏远
一点,不要等间距,自己调试过之后,进行合理布局;
5、四个循迹传感器,必须要在实际的场地进行调试一下,不同光照情况,碰到黑线、白线的表现都不一样,需要用螺丝刀调节一个个调试
可以将循迹传感器,划过黑线,划过白线,对比指示灯,进行调试;
6、每个人的车上的负载不一样,因此电机速度也不一样,需要根据自己的小车进行多次调试;
比如直走,左转弯,右转弯,大转弯,调头等等;
转弯的时候,可以采取速度差的方法,或者一边后退,一边前进的方法,具体速度自己调试。在0-200范围内就可以。
7、调头的动作,调头是采取一边后退,一边前进的方法,然后延时一定时间,实现。这个时间需要根据设定的速度进行多次调试,
保证可以实现180度调头;
8、如果两边电机的方向不一样,需要根据实际情况进行更改线,或者更改对换程序的接口,一般改线不方便,那么就改程序的接口,对调。
如,如果下面的接线不对,
sbit IN1 = P1^4;   //为0左轮反转   
sbit IN2= P1^3;   //为0左轮正转
可以更改为
sbit IN1 = P1^3;   //为0左轮反转   
sbit IN2= P1^4;   //为0左轮正转

右轮也一样。

9、蓝牙模块和下载器,都用同一个串口,因此,如果想下载程序,需要把蓝牙模块的电源拔掉断掉,不然不能下载程序;
下载程序之后,再插上蓝牙模块的电源线;
10、实验室黄色的TT电机,最大电压只能调节到6.5V,黑色电机,最大可以到7.4V。不要超过电压。
本例子使用的是7.4V黑色电机,电机传动比是1:48;给电机的电压是7.4V;其他地形需要自己调试电压和转弯的速度差等数据;

11、蓝牙模块控制命令
首先,最好是用HC05模块,不用BLE蓝牙模块。
利用实验室网上的资料软件,编辑界面(实验室自编讲义有介绍);
命令
发送3个字符,0和9是帧头和帧尾,是为了保证数据的有效性,接收三个数据,头和尾巴都相等,才判断第二个功能码。
0f9,前进
0l9,左转,这个l是小写的L;
0r9是,右转;
0b9是后退;
0x9是循迹模式

*/


#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit ENA = P1^2;   //左电机使能PWM
sbit IN1 = P1^4;   //左轮   
sbit IN2= P1^3;   //左轮
sbit IN3 = P1^5;   //右电机PMM
sbit IN4= P1^6;   //右轮
sbit ENB = P1^7;   //
//sbit BEEP=P1^0;
sbit KEY_Start=P3^7;
//left1,left2,right1,right2
//P20	P21 P22		P23
//四路循迹模块 接线
sbit left1 = P2^0;
sbit left2 = P2^1;
sbit right1 = P2^2;
sbit right2 = P2^3;

u8 PWMCnt1 = 0;//占空比的动态点,一个定时周期加1,小于设定值,就PWM=1,高电平时间,决定占空比;当大于设定值且小于200那么就PWMIO口=0,输出低电平
u8 PWMCnt2 = 0;//占空比的动态点,一个定时周期加1,小于设定值,就PWM=1,高电平时间,决定占空比;当大于设定值且小于200那么就PWMIO口=0,输出低电平
u8 cntPWM1 = 0;//PWM的设定值,程序修改,完成占空比的设置,完成电机速度的控制
u8 cntPWM2 = 0;//PWM的设定值,程序修改,完成占空比的设置,完成电机速度的控制

u8 timeflag=0;//定时时间标记位,不用的时候是0,使用的时候,等待定时程序中定时时间到,就等于1,后面记得手动程序清0
u8 XunJiFlag=0;//循迹标记位,通按键或者蓝牙进行置1或者清0使用,=1,就是循迹模式。

//定时器0产生PWM,并且测速,测位移,定时器1,产生波特率
void Timer0Init();//定时器0产生PWM
void XunJi();
void TurnRight1()	;	   //右转,左轮速度快,速度差这里设置70-55
void TurnRight2()	;	   //右转
void TurnLeft1();				//左转
void TurnLeft2();				//左转
void Backward();				 //后退
void Stop();					  //停止
void Forward();


void delayms(unsigned int tms)
{
	unsigned int i,j;
	for(i=0;i<100;i++)
	{
		for(j=0;j<tms;j++);

		}
}


/********************************************************/
/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
    SCON  = 0x50;  //配置串口为模式1
    TMOD &= 0x0F;  //清零T1的控制位
    TMOD |= 0x20;  //配置T1为模式2
    TH1 = 256 - (11059200/12/32)/baud;  //计算T1重载值
    TL1 = TH1;     //初值等于重载值
    ET1 = 0;       //禁止T1中断
    ES  = 1;       //使能串口中断
    TR1 = 1;       //启动T1
}
//定时50us
void Timer0Init()
{
	
	TH0 = (65536 - 50)/256;//50us
	TL0 = (65536 - 50)%256;
	TMOD &= 0xF0;
	TMOD |= 0x01;
	
	ET0 = 1;
	TR0 = 1;
}

//**********************************主函数
void main()
{
	Timer0Init();
	ConfigUART(9600);
	EA = 1;
	while(1)
	{
		//用开发板的P37的按键,控制启动,也可以通过蓝牙模块控制启动
		if(KEY_Start==0)
		{
			delayms(10);
			if(KEY_Start==0)
			{
			  if(XunJiFlag==0)
							 {
								  delayms(2000);//按下,等两秒,再启动
							  	XunJiFlag=1;
								 
							 }
							 else  if(XunJiFlag==1)
							 {
							  	XunJiFlag=0;
								 Stop();
								 
							 }
			}
		}
		if(XunJiFlag==1)
		{
		   XunJi();
		}
	}	
}




void TurnRight1()		   //右转,左轮速度快,速度差这里设置70-55
{
	IN1 = 0;	
	IN2 = 1;//
	IN3 = 1;
	IN4 =0;
	cntPWM1 = 150;
	cntPWM2	= 60;
}

void TurnRight2()		   //右转
{
	IN1 = 0;	//
	IN2 = 1;

	IN3 = 1;	//
	IN4 = 0;
	
	cntPWM1 = 195;
	cntPWM2	= 120;
	delayms(10);


}

void TurnLeft1()				//左转
{
	IN1 = 1;
	IN2 = 0;  

	IN3 = 0;
	IN4 = 1;   	
	
	cntPWM1 = 60;
	cntPWM2	= 150;
	
}			  	

void TurnLeft2()				//左转
{
	IN1 =1;
	IN2 =0;   	

	IN3 = 0;
	IN4 = 1;  
	
	cntPWM1 = 120;
	cntPWM2	= 195;
	delayms(10);
	
}	
	
void Forward()				 //前进
{
	IN1 = 0;
	IN2 = 1;   	//右轮正转

	IN3 = 0;   	//左轮正转
	IN4 = 1;

	cntPWM1 = 45;
	cntPWM2	= 45;
}

void Backward()					 //后退
{
	IN1 =1;	//右轮反转
	IN2 =0;

	IN3 = 1;
	IN4 = 0;	//左轮反转
	cntPWM1 = 60;
	cntPWM2	= 60;
}

void Stop()					  //停止
{
	IN1 = 0;
	IN2 = 0;

	IN3 = 0;
	IN4 = 0;
}
void XunJi()
{

  u8 	flag = 0;

	if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //0 0 0 0
		flag = 0;

	else if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1))   //0 0 0 1
		flag = 1;

	else if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0))   //0 0 1 0
		flag = 2;

	else if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0))   //0 1 0 0
		flag = 3;
	
	else if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0))   //1 0 0 0
		flag = 4;	
	else if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1))   //0 0 1 1 zuo转90°  倒7路口
		flag = 5;

	else if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))   //0 1 1 0 //0 0 1 1 倒7路口,右转90°
		flag = 5;
	 else if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 ==0))   //0 1 1 1左转90°
		flag = 6;
   else if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 ==0))   //0 1 1 1左转90°
		flag = 6;
	
	else if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1))    //1 1 1 1 掉头
		flag = 7;

	switch(flag)
	
{
		case 0:
			Forward();
					break;	
		case 1://0001
			TurnRight2();break;	
		case 2:
			TurnRight1();break;	
		case 3:
			TurnLeft1();break;
		case 4:
			TurnLeft2();break;
 		case 5://0011   0111
 				TurnRight2();break;		  
 		break;		
 		case 6://1100 1110
			TurnLeft2();break;
 		break;			
 	 case 7://调头
			Forward();//前进
	 
			while(timeflag==0);
			timeflag=0;//前进一小段时间
	    while(timeflag==0);
			timeflag=0;//前进一小段时间

	   Stop();
	 	 while(timeflag==0);
			timeflag=0;//前进一小段时间
	    while(timeflag==0);
			timeflag=0;//前进一小段时间
	    
	  /// TurnRight2();//右转这么多时间,必须经过多次调试转弯的时间,确保不会大于270度。
			IN1 = 0;	//
			IN2 = 1;

			IN3 = 1;	//
			IN4 = 0;
			
			cntPWM1 = 130;
			cntPWM2	= 130;
	
	  
	 	 while(timeflag==0);
			timeflag=0;//前进一小段时间
	    while(timeflag==0);
			timeflag=0;//前进一小段时间
			 
	 	 while(timeflag==0);
			timeflag=0;//前进一小段时间
			
	 	 while(timeflag==0);
			timeflag=0;//前进一小段时间
 		 	
 		break;	
		default:break;//Stop();
	}
}

void timer0inter() interrupt 1
{
	static unsigned int ttms;
	ttms++;
	if(ttms>=2000)//
	{
		ttms=0;
	  timeflag=1;
	}
	PWMCnt1++;
	PWMCnt2++;
	
	if(PWMCnt1  >= 200)//50us*200=10 000us=10ms
	{
		PWMCnt1 = 0;
	}
	if(PWMCnt1 <= cntPWM1)
	{
		ENA = 1;
	}
	else
	{
		ENA = 0;
	}

	if(PWMCnt2 >= 200)
	{
		PWMCnt2 = 0;
	}
	if(PWMCnt2 <= cntPWM2)
	{
		ENB = 1;
	}
	else
	{
		ENB = 0;
	}

	TH0 = (65536 - 50)/256;//50us
	TL0 = (65536 - 50)%256;

}


/*----------------------------
UART 中断服务程序,蓝牙控制
-----------------------------*/
void Uart1() interrupt 4 using 1
{
	
   static unsigned char RecSbuf[3];
	static unsigned char recNum=0; 
	if (RI) //接收到新字节 
		{ 	
			RI = 0; //清零接收中断标志位,软件清零 
			//接收到的数据保存在 SBUF 里面,只能放一个字节; 
			if(recNum==0)//第一个字节 
				{
					RecSbuf[0]=SBUF;//将数据放在 RecSbuf 中 
					if(RecSbuf[0]=='0')
//接头暗号正确,才进行后续数据的接收判断 
						{
							recNum=1;
						   //LED=!LED;
						}
        }
			else if(recNum==1)//第 2 个字节 
				{ 
					RecSbuf[1]=SBUF;//将数据放在 RecSbuf 中 
				 recNum=2; //接收第3个数据
				}
				else if(recNum==2)
				{
				  RecSbuf[2]=SBUF;//
						recNum=0; //第三个接收到了,就运行接收新的。
					if( RecSbuf[2]=='9')//判断帧尾是不是等于约定的‘9’
					{
												//*******************************************************

							if(RecSbuf[1]=='x') //动作1
						 {
								//LED0=!LED0; 
							 //小车循迹模式 按一次进行循迹,再按一次,就停止循迹
								
							 if(XunJiFlag==0)
							 {
							  	XunJiFlag=1;
								 
							 }
							 else  if(XunJiFlag==1)
							 {
							  	XunJiFlag=0;
								 Stop();
								 
							 }
						 } 
						 						//*******************************************************

						 if(RecSbuf[1]=='f') //动作2
							{  
								//LED1=!LED1; 
								//小车直行模式
											Forward();//前进
							} 
													//*******************************************************

						if(RecSbuf[1]=='l') //动作3
						{
							//LED0=!LED0; 
							//小车转90度,左转
							TurnLeft1();
						
						}
						//*******************************************************
						if(RecSbuf[1]=='r') //动作4
						{
							//LED1=!LED1; 
							//小车转90度,右转
							TurnRight1();
						
						}
												//*******************************************************

							if(RecSbuf[1]=='b') //动作4
						{
													//LED1=!LED1; 
													//小车调头
														Forward();//前进
							 
														while(timeflag==0);
														timeflag=0;//前进一小段时间
														while(timeflag==0);
														timeflag=0;//前进一小段时间

												 
													 Stop();
												 
													 while(timeflag==0);
														timeflag=0;//前进一小段时间
														while(timeflag==0);
														timeflag=0;//前进一小段时间
														
													/// TurnRight2();//右转这么多时间,必须经过多次调试转弯的时间,确保不会大于270度。
														IN1 = 0;	//
														IN2 = 1;

														IN3 = 1;	//
														IN4 = 0;
														
														cntPWM1 = 130;
														cntPWM2	= 130;
												
													
													 while(timeflag==0);
														timeflag=0;//前进一小段时间
														while(timeflag==0);
														timeflag=0;//前进一小段时间
														 
													 while(timeflag==0);
														timeflag=0;//前进一小段时间
														
													 while(timeflag==0);
														timeflag=0;//前进一小段时间
 		  
						
						}
												//*******************************************************

					if(RecSbuf[1]=='s') //停止
						{
										//LED1=!LED1; 
										//停止
											Stop();
				 
						}
						
						if(RecSbuf[1]=='t') //后退
						{
										//LED1=!LED1; 
										//停止
										Backward();			
						}	
						
					}
				
				}	
				
			
				
		} 
		if (TI) //字节发送完毕 
			{ 
				TI = 0; //清零发送中断标志位 
			}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值