0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

自动避障小车仿真

Harmony&嵌入式学习 来源:Harmony&嵌入式学习 作者:Harmony&嵌入式学 2023-07-17 09:28 次阅读

课题的技术要求:本次课题最终要求小车能在无人操作的条件下实现自动避障,避障基于超声波测距的原理实现的,当超声波检测到小车与障碍物的距离大于设定值时,小车按照原先设定的速度正常行驶;当超声波检测到小车和障碍物的距离小于设定值时,单片机控制蜂鸣器发声同时控制小车停止。因为本次设计的小车时两轮驱动的小车,也没有安装舵机,所以小车的转弯通过控制两个车轮间的转速差实现。
课题研究的主要内容:本次设计以超声波避障为研究对象,以自动避障为核心控制功能。要研究内容包括:以STC89C52为控制核心的智能系统的平台搭建、各个模块的选型、多传感器的组合应用、PWM控制电机驱动的相应动作、外置储存器的选型、测距系统的选择与搭建、报警与显示系统的选择与搭建等。

wKgaomSzwd-AeUulAABMh2oW4eg474.png

系统总体流程图

wKgaomSzwfSAQQB9AAAsS8T4vYo292.png

STC89C52单片机接通电源后开始运行,首先对LCD1602的寄存器发送数据进行初始化,完成最基本的屏幕显示配置,然后在界面上显示主界面的框架,接下来在While循环中不断采集超声波发送的数据,进行转换后变为整数字节型显示在LCD1602屏幕上,若采集的数值大于设定值即报警。

键盘程序流程图

wKgZomSzwh2AJ08bAAA0k8-XoV8106.png

在键盘处理函数中,分别判断按下的为哪个按键,若按下设定值增加按键,则设定值的数值增加10;若按下设定值减少按键,设定值的数字减少10,并在变动后均存入外部储存器。

wKgaomSzwiqABh9dAAGZunv_pXw635.png
#include "reg51.h"
#include < intrins.h >
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^6;
sbit LCD1602_RS=P2^5;
sbit Trig = P1^1;
sbit Echo = P1^0;
sbit BEEP = P2^4;
sbit MotorA_1 = P2^0;
sbit MotorA_2 = P2^1;
sbit MotorB_1 = P2^2;
sbit MotorB_2 = P2^3;
sbit I2C_SDA =      P1^2;  		
sbit I2C_SCL =      P1^3; 
unsigned char Set_dis = 80;
unsigned char code ASCII[15] =    {'0','1','2','3','4','5','6','7','8','9','.','-','M'};
static unsigned char DisNum = 0; //显示用指针				  
unsigned int  time=0;
unsigned long S=0;
bit      flag =0;
unsigned char disbuff[4]	   ={ 0,0,0,0,};
unsigned int DIstance;



void D_10()
{
	uchar a, b;
	for(b=1; b>0; b--)
	{
		for(a=2; a>0; a--);
	}
}

void IIC_S()
{
	I2C_SDA = 1;
	D_10();
	I2C_SCL = 1;
	D_10();
	I2C_SDA = 0;
	D_10();
	I2C_SCL = 0;			
	D_10();		
}

void IIC_ST()
{
	I2C_SDA = 0;
	D_10();
	I2C_SCL = 1;
	D_10();
	I2C_SDA = 1;
	D_10();		
}

uchar WD_SB(uchar dat, uchar ack)
{
	uchar a = 0,b = 0;
			
	for(a=0; a< 8; a++)
	{
		I2C_SDA = dat >> 7;
		dat = dat < < 1;
		D_10();
		I2C_SCL = 1;
		D_10();
		I2C_SCL = 0;
		D_10();
	}

	I2C_SDA = 1;
	D_10();
	I2C_SCL = 1;
	while(I2C_SDA && (ack == 1))
	{
		b++;
		if(b > 200)
		{
			I2C_SCL = 0;
			D_10();
			return 0;
		}
	}

	I2C_SCL = 0;
	D_10();
 	return 1;		
}

uchar WD_RB() 
{
	uchar a = 0,dat = 0;
	I2C_SDA = 1;
	D_10();
	for(a=0; a< 8; a++)
	{
		I2C_SCL = 1;
		D_10();
		dat < <= 1;
		dat |= I2C_SDA;
		D_10();
		I2C_SCL = 0;
		D_10();
	}
	return dat;		
}
void CC_WR(uchar addr,uchar dat)
{
	IIC_S();
	WD_SB(0xa0, 1);
	WD_SB(addr, 1);
	WD_SB(dat, 0);
	IIC_ST();
}


uchar CC_RD(uchar addr)
{
	uchar num;
	IIC_S();
	WD_SB(0xa0, 1);
	WD_SB(addr, 1);
	IIC_S();
	WD_SB(0xa1, 1);
	num=WD_RB();
	IIC_ST();
	return num;	
}
void RUN_UP()
{
	MotorA_1 = 1;
	MotorA_2 = 0;
	MotorB_1 = 1;
	MotorB_2 = 0;
}

void RUN_DOWN()
{
	MotorA_1 = 0;
	MotorA_2 = 0;
	MotorB_1 = 0;
	MotorB_2 = 0;
}

void RUN_RIGHT()
{
	MotorA_1 = 1;
	MotorA_2 = 0;
	MotorB_1 = 0;
	MotorB_2 = 1;
}

/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能		   : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar a,b;
	for (; c >0; c--)
	{
		 for (b=199;b>0;b--)
		 {
		  	for(a=1;a>0;a--);
		 }      
	}
    	
}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能		   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	
	LCD1602_DATAPINS = com;     //放入命令
	Lcd1602_Delay1ms(1);		//等待数据稳定

	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(5);	  //保持时间
	LCD1602_E = 0;
}
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能		   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/		   	   
void LcdWriteData(uchar dat)			//写入数据
{
	LCD1602_E = 0;	//使能清零
	LCD1602_RS = 1;	//选择输入数据
	LCD1602_RW = 0;	//选择写入

	LCD1602_DATAPINS = dat; //写入数据
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;   //写入时序
	Lcd1602_Delay1ms(5);   //保持时间
	LCD1602_E = 0;
}


/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能		 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/		   
void LcdInit()						  //LCD初始化子程序
{
 	LcdWriteCom(0x38);  //开显示
	LcdWriteCom(0x0c);  //开显示不显示光标
	LcdWriteCom(0x06);  //写一个指针加1
	LcdWriteCom(0x01);  //清屏
	LcdWriteCom(0x80);  //设置数据指针起点
}




//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
 Y &= 0x1;
 X &= 0xF; //限制X不能大于15,Y不能大于1
 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
 X |= 0x80; // 算出指令码
 LcdWriteCom(X); //这里不检测忙信号,发送地址码
 LcdWriteData(DData);
}
//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
 unsigned char ListLength;

  ListLength = 0;
 Y &= 0x1;
 X &= 0xF; //限制X不能大于15,Y不能大于1
 while (DData[ListLength]>=0x20) //若到达字串尾则退出
  {
   if (X <= 0xF) //X坐标应小于0xF
    {
     DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
     ListLength++;
     X++;
    }
  }
}

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;
}

/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Conut(void)
	{
	 time=TH0*256+TL0;
	 TH0=0;
	 TL0=0;
	
	 S=(time*1.7)/100;     //算出来是CM
	 DIstance = S;
	 if((S >=700)||flag==1) //超出测量范围显示“-”
	 {	 
	  flag=0;
	 
	  DisplayOneChar(0, 1, ASCII[11]);
	  DisplayOneChar(1, 1, ASCII[10]);	//显示点
	  DisplayOneChar(2, 1, ASCII[11]);
	  DisplayOneChar(3, 1, ASCII[11]);
	  DisplayOneChar(4, 1, ASCII[12]);	//显示M
	 }
	 else
	 {
	  disbuff[0]=S%1000/100;
	  disbuff[1]=S%1000%100/10;
	  disbuff[2]=S%1000%10 %10;
	  DisplayOneChar(0, 1, ASCII[disbuff[0]]);
	  DisplayOneChar(1, 1, ASCII[10]);	//显示点
	  DisplayOneChar(2, 1, ASCII[disbuff[1]]);
	  DisplayOneChar(3, 1, ASCII[disbuff[2]]);
	  DisplayOneChar(4, 1, ASCII[12]);	//显示M
	 }
}


void zd0() interrupt 1 		 //T0中断用来计数器溢出,超过测距范围
{
    flag=1;							 //中断溢出标志
}

void main()
{
	 TMOD=0x01;		   //设T0为方式1,GATE=1;
	 TH0=0;
	 TL0=0;          
	 ET0=1;             //允许T0中断
	 EX0=1;       //外部中断0开()  EX1 为外部中断1 (P3^3)
	 IT0=1;        //低电平触发   IT1为中断1
	 EX1=1;       //外部中断0开()  EX1 为外部中断1 (P3^3)
	 IT1=1;        //低电平触发   IT1为中断1
	 EA=1;			   //开启总中断	
	 Set_dis = CC_RD(0x01);
	LcdInit();
	DisplayListChar(4,0,"Car system");
	while(1)
	{
		StartModule();
	  while(!Echo);		//当RX为零时等待
	  TR0=1;			    //开启计数
	  while(Echo);			//当RX为1计数并等待
	  TR0=0;				//关闭计数
    Conut();			//计算
		DisplayOneChar(8,1,(char)(Set_dis/100)+'0');
		DisplayOneChar(9,1,(char)(Set_dis/10%10)+'0');
		DisplayOneChar(10,1,(char)(Set_dis%10)+'0');
		if(DIstance>Set_dis)
		{
			BEEP = 0;
			RUN_RIGHT();
		}else
		{
			BEEP = 1;
			RUN_UP();
		}

	}
}


void Key1_INT( )  interrupt 0  // 这里0对应下表
{
    Set_dis = Set_dis+10; 
		CC_WR(0x01,Set_dis);
}


void Key2_INT( )  interrupt 2  // 这里0对应下表
{
	   Set_dis =Set_dis-10;
			CC_WR(0x01,Set_dis);
}

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6032

    文章

    44513

    浏览量

    632691
  • 仿真
    +关注

    关注

    50

    文章

    4036

    浏览量

    133393
  • 蜂鸣器
    +关注

    关注

    12

    文章

    889

    浏览量

    45860
  • 避障小车
    +关注

    关注

    1

    文章

    24

    浏览量

    19013
收藏 人收藏

    评论

    相关推荐

    智能小车问题

    谁有小车的程序与仿真图,请发我邮箱,804902426@qq.com,谢谢了。
    发表于 04-30 08:07

    寻人小车

    想做一个自动寻人小车,人身上装有特定的信号源,小车捕捉信号源跟着人走,行走途中可以自动
    发表于 10-11 16:28

    红外小车设计论文

    红外小车设计论文红外小车设计论文红外
    发表于 11-13 15:57 0次下载

    寻迹一体小车

    寻迹一体小车寻迹一体小车寻迹
    发表于 11-13 15:53 0次下载

    自动红外电动小车C51程序

    自动红外电动小车C51程序自动红外电动
    发表于 11-18 17:08 31次下载

    arduino版的自动小车程序

    自动小车 arduino版的自动
    发表于 11-24 15:24 0次下载

    论文1

    小车模糊控制算法的设计与仿真。本文详细阐述了智能小车
    发表于 05-10 15:12 36次下载

    循迹小车(寻迹程序+程序)

    循迹小车(寻迹程序+程序),感兴趣的小伙伴们可以瞧一瞧。
    发表于 11-23 15:45 457次下载

    自动充电小车5110电压检测版

    自动充电小车5110电压检测版
    发表于 04-28 08:57 0次下载

    寻迹一体小车

    寻迹一体小车
    发表于 01-30 16:48 27次下载

    怎样制作小车

    本项目是在 PVCBOT-A型 基础平台车——BEAM小车的基础上,加装了传感器以及控制电路,组成了一台具体有功能的
    的头像 发表于 09-18 09:35 1.9w次阅读

    使用Arduino设计的智能小车自动的接线说明

    本文档的主要内容详细介绍的是使用Arduino设计的智能小车自动的接线说明。
    发表于 11-22 08:00 18次下载
    使用Arduino设计的智能<b class='flag-5'>小车</b><b class='flag-5'>自动</b><b class='flag-5'>避</b><b class='flag-5'>障</b>的接线说明

    基于单片机的自动小车设计课设

    基于单片机的自动小车设计课设(单片机编程器)-该文档为基于单片机的自动
    发表于 07-22 13:32 24次下载
    基于单片机的<b class='flag-5'>自动</b><b class='flag-5'>避</b><b class='flag-5'>障</b><b class='flag-5'>小车</b>设计课设

    基于单片机的小车自动循迹的设计(proteus仿真+源码+原理图+软件设计流程+硬件清单+视频讲解)

    基于单片机的小车自动循迹的设计(proteus仿真+源码+原理图+软件设计流程+硬件清单+视频讲解)
    发表于 11-11 15:51 92次下载
    基于单片机的<b class='flag-5'>避</b><b class='flag-5'>障</b><b class='flag-5'>小车</b>及<b class='flag-5'>自动</b>循迹的设计(proteus<b class='flag-5'>仿真</b>+源码+原理图+软件设计流程+硬件清单+视频讲解)

    AGV小车使用雷达

    AGV(自动导引车)小车使用雷达是为了确保其在运行过程中的安全性和稳定性。雷达,如激光雷
    的头像 发表于 05-20 10:48 568次阅读