基于51单片机智能小车(超声波+舵机)

基于stc89c52单片机避障+舵机两驱三轮智能小车

前期准备:学会使用Keil4,学好51单片机基本知识,学会控制IO的输入与输出,内容学到外部中断,定时器,(串口通信,可以实现蓝牙控制)

准备材料:stc89c52最小系统,超声波模块,L298N电机驱动模块,智能小车两驱底盘套件,18650电池(12V)

源代码:

#include "reg52.h"
#include "intrins.h"

//重定义数据类型
typedef unsigned char u8;
typedef unsigned int u16;


//定义电机控制管脚
sbit MOTOA=P1^0;
sbit MOTOB=P1^1; //右侧电机
sbit MOTOC=P1^2;
sbit MOTOD=P1^3; //左侧电机

//定义超声波模块控制管脚
//TRIG 为控制端
sbit TRIG = P1^6; //超声波的 TRIG端  插在了P1.6口
//ECHO 为接收端
sbit ECHO = P1^7; //超声波的 ECHO端  插在了P1.7口	

//定义舵机控制管脚
sbit PWM=P3^2;	 //舵机橙线(信号线)插在p3.7口

u8 count=0;
u8 timer1;

u8 lFlag;  
u8 rFlag;  	  //判断左右是否有障碍物的标志

/*延时程序*/

void delay1s(void)   //误差 0us
{
    u8 a,b,c;
    for(c=167;c>0;c--)
        for(b=171;b>0;b--)
            for(a=16;a>0;a--);
    _nop_(); 
}

void delay(u8 time)	  //定义一个延迟函数
{
	u8 i;
	for(;time>0;time--)
	{
		for(i=0;i<255;i++)
		{
		
		}
	}
}
void run(void)//前进
{
	MOTOA=1;
	MOTOB=0;
	MOTOC=1;
	MOTOD=0;	
}
void backrun(void)//后退
{
	MOTOA=0;
	MOTOB=1;
	MOTOC=0;
	MOTOD=1;	
}
void leftrun(void)//左转
{
	MOTOA=1;
	MOTOB=0;
	MOTOC=0;
	MOTOD=0;	
}
void rightrun(void)//右转
{
	MOTOA=0;
	MOTOB=0;
	MOTOC=1;
	MOTOD=0;	
}
void stoprun(void)//停止
{
	MOTOA=0;
	MOTOB=0;
	MOTOC=0;
	MOTOD=0;	
}

//超声波模块
u8 overflow_flag=0;	 //标志定时器是否溢出
void delay_20us(void) //延时20us
{
    _nop_();_nop_();_nop_();_nop_();_nop_(); 
    _nop_();_nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();_nop_();
    _nop_();_nop_();_nop_();_nop_();_nop_();
}

/*定时器T0初始化*/
void Timer0Init(void)
{
	TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

	TH0=0;	
	TL0=0;	//给定时器赋初值

	ET0=1;  //打开定时器0中断允许
	EA=1;   //打开总中断
	TR0=0;	//关闭定时器0		
}

void Timer0_Init() interrupt 1
{
	overflow_flag=1;//溢出标志位置1		
}

u16 Get_Distance(void) 
{
		u16 distance_data,out_TH0,out_TL0;

		TRIG=0;   // 先给控制端初始化为0

		Timer0Init();   //初始化定时器
		
		overflow_flag=0;   //置溢出标志位为0
	
    	TRIG=1;    
    	delay_20us();
    	TRIG=0;   //等待接收端出现高电平
  			
    	while(!ECHO);
		TR0=1; //启动计时器 开始计时
    	while(ECHO); //等待高电平结束
   		TR0=0; //关闭低电平
	
		out_TH0=TH0; //取定时器的值
    	out_TL0=TL0;
    	out_TH0<<=8;  //左移8位 
    	distance_data=out_TH0|out_TL0; //合并为16位的值  
    	distance_data/=58; // 微秒/58 = 厘米

		if(overflow_flag)
		{
		   distance_data=999;
		}
	
		return distance_data;  //返回
} 


/*定时器T1初始化*/
void Timer1Init()           
{
	TMOD&=0x00;
    TMOD|=0x10; //定时器T1设置成方式1
 
    TH1=0xff;   
    TL1=0xa4;	//定时常数 0.1ms 晶振为11.0592MHz
 
    ET1=1;   //打开定时器1中断允许   
    TR1=1; 	 //打开定时器1
	EA=1;    //打开总中断
}

void Timer1_Init() interrupt 3 
{
	TR1=0; 	  //关闭定时器1
	TH1=0xff; 
	TL1=0xa4;  // 0.1ms 产生舵机产生转动所需要的pwm信号 
	
	if(count<=timer1)
	{ 
		PWM=1;  //输出高电平
	}
	else 
	{ 
		PWM=0; 	  //输出低电平
	}
	count++;
	if (count>=200)   //T = 20ms清零
	{ 
		count=0; 
	}
	TR1=1; //打开定时器T1
}

u16 cnt=25,num=440;
//主函数
void main()
{
	Timer0Init();
	Timer1Init();		//引入定时器0和定时器1
	
	timer1=6;  //控制舵机使超声波正对前方
	count=0;  //让定时器重新计数
	delay1s();
		
	while(1)
	{
		if(Get_Distance()>=cnt)
		{
			run();
			delay(8);
			stoprun();
			delay(5);  //主要是为了控制小车速度,可以根据自身改变
		}
		else
		{
			stoprun();
			delay(50);
			
			timer1=12;  //使舵机左转
			count=0;   //让定时器1重新计数
			delay1s();
			
			lFlag=Get_Distance();  //测量左侧距离
		

			timer1=6;  //使舵机正对前方
			count=0;   //让定时器1重新计数
			delay1s();				   //可能可以去掉,待测试
		
					
			timer1=2;	 //使舵机右转
			count=0;	 //让定时器1重新计数
			delay1s();

			rFlag=Get_Distance();	 //测量右侧距离
		

			timer1=6;  //使舵机正对前方
			count=0;   //让定时器1重新计数
			delay1s();				   //可能可以去掉,待测试
		

			backrun();
			delay(num);
	
			if(lFlagcnt)
			{
				rightrun();
			   delay(num);
			   
			}
			else if(lFlag>cnt&&rFlagcnt&&rFlag>cnt)
			{
				rightrun();
				delay(num);
			
			}
			else if(lFlag

你可能感兴趣的:(51智能小车,51单片机)