基于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(lFlag<cnt&&rFlag>cnt)
			{
				rightrun();
			   delay(num);
			   
			}
			else if(lFlag>cnt&&rFlag<cnt)
			{
				leftrun();
				delay(num);
				
			}
			else if(lFlag>cnt&&rFlag>cnt)
			{
				rightrun();
				delay(num);
			
			}
			else if(lFlag<cnt&&rFlag<cnt)
			{
				backrun();
				delay(num);
			}			   
		}
	}	
}

源代码可根据自身情况进行修改,该项目适合学习51单片机中断之后进一步巩固。
PS:第一次写文章,如有错误,望读者指征

版权声明:本文为CSDN博主「.柒.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_60928755/article/details/120814977

生成海报
点赞 0

.柒.

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

用51单片机做宿舍门禁系统(1)--1602显示

由于时间紧迫,还有其他考试,所以目前只能抽时间慢慢做慢慢更新了,本身就是一个练手项目。 1602显示 所谓的智能系统,没有显示是万万不能的,所以有一个显示的东西是很必要的

郭天祥的10天学会51单片机_第九节

开发板上的蜂鸣器下面是温度传感器DS18B20 DA转换器的下面是SPI总线(RFR、IOUT、DI0和GND) I2C总线和SPI总线用的多。 I2C总线仲裁:具有 C总线接口的设备都接在总线上

基于AT89C51的蓝牙循迹避障小车

基于AT89C51的蓝牙循迹避障小车 对标题的解读: AT89C51:在下使用的是STC89C52这款芯片,c51和c52在新手入门阶段是一样的,所以不必纠结于到底是哪个名字&#xff

51单片机+ LCD1602+PCF8574转IIC接口+DHT11数据显示

51单片机+ LCD1602+PCF8574转IIC接口+DHT11数据显示 在做这个实验的时候又一次被自己的不注意,掉坑里面去了,调试了好久都不出数据,结果在延时函数和引脚定义上被自己坑了一把。希望大家在写代码的时候多加注意。 LCD1602