基于51单片机智能小车防撞系统系统 代码+protuse仿真

        本次设计考虑到经济效应,使用51单片机来完成系统设计,而在本次设计当中所需要用到的定时器需要三个,所以选择stc89c52的芯片完成系统设计。整体主要是通过51单片机最小系统、超声波测距模块、驱动显示电路、报警电路、按键电路和舵机来实现整个控制系统。首先是利用超声波测距模块HC-SR04测量距离,通过其传回的数据进行计算和分析,再利用单片机将得到的相关信息,发送至LED数码管显示出来,并且当计算出的相关数据小于设定数据时,单片机还能控制蜂鸣器发出警报同时控制舵机转向,避免小车撞击,除此以外还设计可以通过按键调整报警距离,同时电源部分采用5V稳压直流电源。

        首先是对于电路的设计,,我们通过对所需要的元器件进行添加,在添加完需要元器件后,我们首先构建处最小单片机系统,主要为芯片、复位电路和晶振电路的连接,之后再在P0口接LED显示电路的段码处,P1口接3个按键后连接到地,P2接蜂鸣器与LED报警电路、超声波测距电路,P3.7口接舵机转向电路。其仿真原理图如附图所示。

        此次为第一次实际设计电路,如有欠缺望指正。

下面为代码

#include <reg52.H>//器件配置文件
#include <intrins.h>
#include "eeprom52.h"
//传感器接口
sbit RX  = P2^3;
sbit TX  = P2^2;
//按键声明
sbit S1  = P1^4;
sbit S2  = P1^5;
sbit S3  = P1^6;
sbit pwm=P3^7;
sbit DIAN=P0^5;			//小数点引脚
//蜂鸣器
sbit Feng= P2^0;

//变量声明
unsigned int  time=0;
unsigned int  timer=0;
unsigned char posit=0;
unsigned long S=0;
unsigned long BJS;//报警距离
char num=0;
//模式 0正常模式 1调整
char Mode=0;
bit  flag=0;
unsigned char n=0,m=0;o=0,k=0,fmq=1;
unsigned char const discode[] ={0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x47,0xDF,0xD7,0x80};	//数码管显示码0123456789-和不显示

unsigned char disbuff[4]	   ={0,0,0,0};		 //数组用于存放距离信息
unsigned char disbuff_BJ[4]	={0,0,0,0};//报警信息

void Display(void);

sbit W0=P2^4;
sbit W1=P2^5;
sbit W2=P2^6;
sbit W3=P2^7;								  //数码管的位选引脚

void write_eeprom()
{
	SectorErase(0x2000);			  //先清除
	byte_write(0x2000, BJS);		  //写数据
	byte_write(0x2060, a_a);	
}

void read_eeprom()
{
	BJS   = byte_read(0x2000);
	a_a      = byte_read(0x2060);
}

void init_eeprom() 
{
	read_eeprom();		//先读
	if(a_a != 1)		//新的单片机初始单片机内问eeprom
	{
		BJS   = 199;
		a_a = 1;
		write_eeprom();	   //保存数据
	}	
}
//延时1ms(不精确)
void delay(unsigned int x)
{
    unsigned int i,j;
    for(i=0;i<x;i++)
	for(j=0;j<121;j++);
}




//按键扫描
void Key_()
{
	unsigned char DIS_I;
	//+
	if(S1==0&&Mode==1)
	{
		for(DIS_I=0;DIS_I<100;DIS_I++)
		Display();	   //延时去抖
		if(S1==0)
		{
			Feng=0;
			for(DIS_I=0;DIS_I<200;DIS_I++)
			Display();	   //延时
			Feng=1;
			BJS++;	 //报警值加
			if(BJS>=151) //最大151
			{
				BJS=0;
			}
			disbuff_BJ[0]=BJS%1000/100;
			disbuff_BJ[1]=BJS%1000%100/10;
			disbuff_BJ[2]=BJS%1000%10 %10;
			while(S1==0) Display();
		}
	}
	//-
	else if(S2==0&&Mode==1)
	{
		for(DIS_I=0;DIS_I<100;DIS_I++)
		Display();	   //延时去抖
		if(S2==0)
		{
			Feng=0;
			for(DIS_I=0;DIS_I<200;DIS_I++)
			Display();	   //延时
			Feng=1;
			BJS--;	 //报警值减
			if(BJS<=1)	 //最小1
			{
				BJS=150;
			}
			disbuff_BJ[0]=BJS%1000/100;
			disbuff_BJ[1]=BJS%1000%100/10;
			disbuff_BJ[2]=BJS%1000%10 %10;
			while(S2==0) Display();
		}
	}
	//功能
	else if(S3==0)		//设置键
	{
		for(DIS_I=0;DIS_I<100;DIS_I++)
		Display();	   //延时去抖
		if(S3==0)
		{
			Feng=0;
			for(DIS_I=0;DIS_I<200;DIS_I++)
			Display();	   //延时
			Feng=1;
			Mode=!Mode;		//模式加
			num=0;
			Feng=1;
			disbuff_BJ[0]=BJS%1000/100;
			disbuff_BJ[1]=BJS%1000%100/10;
			disbuff_BJ[2]=BJS%1000%10 %10;
			while(S3==0) Display();
			if(Mode==0)
			write_eeprom();			   //保存数据
		}
	}
}
//扫描数码管
void Display(void)				 
{
	//正常显示
	if(Mode==0)			   //正常测距模式
	{
		num++;							   //计数切换不同显示数码管
		if(num==1)						   //第一个数码管
		{
			W3=1;						   //关闭第二位
			W0=1;						   //关闭第二位
			P0=~discode[disbuff[0]];	  
			DIAN=0;						   //点亮小数点
			W1=0;						   //打开位
		}
		else if(num==2)					   //第二位
		{
			W1=1;						   //关闭第一位
			P0=~discode[disbuff[1]];	   //显示小数点后一位
			W2=0;						   //打开第二位
		}
		else if(num>=3)					   //第三个位置
		{
			W2=1;						   //关闭第二位
			P0=~discode[disbuff[2]];	   //显示小数点后二位
			W3=0;						   //打开第三位
			num=0;						   //清零
		}
	}
	//报警显示
	else
	{
		num++;
		if(num==1)
		{
			W3=1;
			P0=~0xCE;		  //11001110 显示字母H
			W0=0;
		}
		else if(num==2)
		{
			W0=1;
			P0=~discode[disbuff_BJ[0]];		   //显示报警值
			DIAN=0;
			W1=0;	
		}
		else if(num==3)
		{
			W1=1;
			P0=~discode[disbuff_BJ[1]];
			W2=0;
		}
		else if(num>=4)
		{
			W2=1;
			P0=~discode[disbuff_BJ[2]];
			W3=0;
			num=0;
		}
	}
}
//计算
void Conut(void)
{
	time=TH0*256+TL0;	  //读出T0的计时数值
	TH0=0;
	TL0=0;				  //清空计时器
	S=(time*1.7)/100;     //算出来是CM
	if(Mode==0)			  //非设置状态时
	{
		if((S>=700)||flag==1) //超出测量范围显示“-”
		{	
			Feng=0; 		   //蜂鸣器报警
			flag=0;
			disbuff[0]=10;	   //“-”
			disbuff[1]=10;	   //“-”
			disbuff[2]=10;	   //“-”
		}
		else
		{
			//距离小于报警距
			if(S<=BJS)
			{
				Feng=0;	//报警
				fmq=0;
			}
			else  //大于
			{
				Feng=1;		//关闭报警	
				fmq=1;
			}
			disbuff[0]=S%1000/100;		 //将距离数据拆成单个位赋值
			disbuff[1]=S%1000%100/10;
			disbuff[2]=S%1000%10 %10;
		}
	}
	else
	{
			Feng=1;
			disbuff_BJ[0]=BJS%1000/100;
			disbuff_BJ[1]=BJS%1000%100/10;
			disbuff_BJ[2]=BJS%1000%10 %10;
	}
}
//定时器0
void zd0() interrupt 1 		 //T0中断用来计数器溢出,超过测距范围
{
	flag=1;						 //中断溢出标志
}
//定时器1
void zd1() interrupt 3 		 //T1中断用来扫描数码管和计800MS启动模块
{
	TH1=0xf8;
	TL1=0x30;				 //定时2ms
	Key_();					//扫描按键
	Display();				//扫描显示
	timer++;				//变量加
	if(timer>=400)			//400次就是800ms
	{
		timer=0;
		TX=1;			          //800MS  启动一次模块
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		_nop_(); 
		TX=0;
	} 
}
void zd2() interrupt 5 
{
	TF2=0;
	TH2=(65536-10)/256;
	TL2=(65536-10)%256;
	n++;

	if (n>o)
	{
		pwm=0;
	}
	else
	{
		pwm=1;
	}
	if (n>451)
	{
		n=0;
	}

}
//主函数
void main(void)
{  
	TMOD=0x11;		   //设T0为方式1,GATE=1;
	IE=0xa0;
	TH0=0;
	TL0=0;          
	TH1=0xf8;		   //2MS定时
	TL1=0x30;
	TH2=(65536-10)/256;
	TL2=(65536-10)%256;
	ET0=1;				//允许T0中断
	ET1=1;			   //允许T1中断
	ET2=1;
	TR1=1;			   //开启定时器
	TR2=1;
	EA=1;					//开启总中断
	disbuff[1]=0;	   //“0”
	disbuff[2]=0;	   //“0”
	disbuff[3]=0;	   //“0”
	delay(1000);
	init_eeprom();  //开始初始化保存的数据	
	while(1)
	{


		  if(fmq==0)
		   {
		   	o=25;
		   }
		  else if(fmq==1)
		   {
		   	o=0;
		   }
		

		while(!RX);		
		TR0=1;			
		while(RX);		
		TR0=0;			
		Conut();			
}
}

 

整体仿真如下

  • 7
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值