您的位置:首页 > 编程语言

基于STC89C52RC单片机的蓝牙遥控与超声波避障程序代码

2018-05-27 19:27 453 查看
#include<reg52.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int  uint;
typedef unsigned long  ulong;

sbit Sevro_moto_pwm = P1^5;	   //接舵机信号端输入PWM信号调节速度
sbit  ECHO= P3^3;				   //超声波接口定义
sbit  TRIG= P3^2;				   //超声波接口定义
sbit ENB = P2^5;	  //左电机高电平
sbit ENA = P2^4;	  //右电机高电平
sbit IN1 = P2^0;
sbit IN2 = P2^1;	  //右电机
sbit IN3 = P2^2;
sbit IN4 = P2^3;	  //左电机
sbit P1_4=P1^4; 	  //LED
//sbit A1 = P1^4;		  //左红外避障模块
//sbit A2 = P2^7;		  //右红外避障模块
//sbit A3 = P1^2;		  //左红外寻迹模块
//sbit A4 = P1^3;		  //右红外寻迹模块
sbit K1 = P1^0;		  //功能转换按键
sbit K2 = P1^1;		  //加速键
sbit K3 = P1^2;	  //减速键
uchar connt;			  //调速周期
uchar PWM_time;			  //高电平时间
uchar flag1=0,flag2=0;			  //标志位
uchar COM;
uchar pwm_val_left  = 0;//变量定义
uchar push_val_left ;//舵机归中,产生约,1.5MS 信号
uchar non=0,t=0;
ulong S=0;			//距离变量定义
ulong S1=0;
ulong S2=0;
ulong S3=0;
ulong S4=0;
uint time=0;		    //时间变量
uint timer=0;			//延时基准变量

/************************************************************************/
void delay(uint k)	  //延时函数
{
uint x,y;
for(x=0;x<k;x++)
for(y=0;y<2000;y++);
}
void delay1(uint j)	  //延时函数
{
uint x,y;
for(x=0;x<j;x++)
for(y=0;y<120;y++);
}
void shansuo()
{
P1_4=1;
delay(1);
P1_4=0;
delay(1);
}
/************************************************************************/
void keyspeed(void)
{

if(K2==0)					   // 加速
{
delay1(10);
if(K2==0)
{

PWM_time--;
}
while(!K2);			   //松键检测
}
if(K3==0)					   //减速
{
delay1(10);
if(K3==0)
{

PWM_time++;
}
while(!K3);
}
}
void stop()				//刹车
{
IN1 = 0;
IN2 = 0;
IN3 = 0;
IN4 = 0;
}
void go()				//前进
{
IN1 = 1;
IN2 = 0;
IN3 = 1;
IN4 = 0;
}
void back()				//后退
{
IN1 = 0;
IN2 = 1;
IN3 = 0;
IN4 = 1;
}
void leftgo()				//左大转
{
IN1 = 0;
IN2 = 1;
IN3 = 1;
IN4 = 0;
}

void rightgo()				//右大转
{
IN1 = 1;
IN2 = 0;
IN3 = 0;
IN4 = 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_();
TRIG=0;

}

void InitUART(void)		 //串口中断初始化函数
{
SCON=0x50;			//设置为工作方式1
TMOD=0x20;			//设置计数器工作方式2
PCON=0x00;			//波特率不加倍
TH1=0xfd;				//计数器初始值设置,注意波特率是9600的
TL1=0xfd;
ES=1;						//打开接收中断
EA=1;						//打开总中断
TR1=1;					//打开计数器

}
/***************************************************/
void Conut(void)		   //计算距离
{
while(!ECHO);		       //当RX为零时等待
TR1=1;			       //开启计数
while(ECHO);			   //当RX为1计数并等待
TR1=0;				   //关闭计数
time=TH1*256+TL1;		   //读取脉宽长度
TH1=0;
TL1=0;
S=(time*1.7)/100;        //算出来是CM

}

/************************************************************************/
void  COMM( void )
{

push_val_left=23;	  //舵机向左转90度
timer=0;
while(timer<=4000); //延时400MS让舵机转到其位置		 4000
StartModule();	  //启动超声波测距
Conut();	 		  //计算距离
S2=S;

push_val_left=5;	  //舵机向右转90度
timer=0;
while(timer<=4000); //延时400MS让舵机转到其位置
StartModule();	  //启动超声波测距
Conut();			  //计算距离
S4=S;

push_val_left=14;	  //舵机归中
timer=0;
while(timer<=4000); //延时400MS让舵机转到其位置

StartModule();	  //启动超声波测距
Conut();			  //计算距离
S1=S;

if((S2<50)||(S4<50)||(S1<50)) //只要左右各有距离小于,20CM小车后退
{
back();		   //后退
timer=0;
while(timer<=4000);
}
if((S2<50)&&(S4<50)&&(S1<50)) //只要左右各有距离小于,20CM小车后退
{
back();		   //后退
timer=0;
while(timer<=4000);
}

if(S2>S4)
{
rightgo();  	//车的左边比车的右边距离小	右转
timer=0;
while(timer<=4000);
}
else
{
leftgo();		//车的左边比车的右边距离大	左转
timer=0;
while(timer<=4000);
}

}

/************************************************************************/
/*                    PWM调制舵机转速                                   */
/************************************************************************/
/*                    舵机调速                                        */
/*调节push_val_left的值改变电机转速,占空比            */
void pwm_Servomoto(void)
{

if(pwm_val_left <= push_val_left)
Sevro_moto_pwm=1;
else
Sevro_moto_pwm=0;
if(pwm_val_left>=100)
pwm_val_left=0;

}
void keychange()				  //按钮控制功能转换
{
COM=0;
if(K1==0)
{
delay1(10);
if(K1==0)
{
COM++;
}
while(!K1);
}
if(COM==4)
COM=0;

}

/***************************************************/
///*TIMER1中断服务子函数产生PWM信号*/
void time0()interrupt 1
{

TH0=(65536-100)/256;	  //100US定时
TL0=(65536-100)%256;
timer++;				  //定时器100US为准。在这个基础上延时
pwm_val_left++;
pwm_Servomoto();

t++;
if(t==5)						 //PWM调制左右电机速度
{
t=0;
non++;
}
if( non == PWM_time )
{
ENA = 1;
ENB = 1;
}
if( non == connt )
{
non = 0;
if( PWM_time != 0)
{
ENA = 0;
ENB = 0;
}
}
}

void bizhang()						//避障功能
{
if(timer>=1000)	  //100MS检测启动检测一次	 1000
{
timer=0;
StartModule(); //启动检测
Conut();		  //计算距离
if(S<=25)		  //距离小于30CM
{
stop();	  //小车停止
COMM(); 		  //方向函数
}
else
if(S>25)		  //距离大于,30CM往前走
go();
//		   if(!A1)
//		   {
//		       SC();
//			   delay1(20);
//			   HT();
//			   delay1(300);
//			   SC();
//			   COMM();
//		   }
//		   if(!A2)
//		   {
//		       SC();
//			   delay1(20);
//			   HT();
//			   delay1(300);
//			   SC();
//			   COMM();
//		   }
}

}
/***************************************************/
///*TIMER0中断服务子函数产生PWM信号*/
void timer1()interrupt 3
{

}

/***************************************************/
void UARTInterrupt(void) interrupt 4			 //串口中断函数
{
unsigned char com;
if(flag1==1)								//判断能否执行
{
if(RI==1)
com = SBUF;                   //暂存接收到的数据
RI=0;
}

switch(com)						 //接收到字符并要执行的功能
{
case 0: go();break;
case 1: stop();break;
case 2: leftgo();break;
case 3: rightgo();break;
case 4: back();break;
case 5:	PWM_time--;break;
case 6:	PWM_time++;break;
}

}

void main(void)
{

IP=0x10;
TMOD=0X11;
TH0=(65536-100)/256;	  //100US定时
TL0=(65536-100)%256;
TR0= 1;
ET0= 1;
EA = 1;
connt = 20;						 //PWM的一个周期
PWM_time = 16;					 //调速,数值越大速度越慢
delay(100);
push_val_left=14;
while(1)		       /*无限循环*/
{
shansuo();
keyspeed();
keychange();
switch(COM)						 //接收到字符并要执行的功能
{
case 0:TH1=0;TL1=0;ET1= 1; bizhang();break;
case 1:stop();InitUART();ET1= 0;flag1=1;while(1);break;
default:break;
}
}
}
有关问题请在下方评论,看到时会给予回复。
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐