51智能红外循迹小车(含测速和LCD显示)


前言

本文设计的智能车带有循迹、测速以及计时的功能,它能够在设定的范围内沿着特定的路线在前进过程中,方向可以根据线路自动更改,并且可以显示速度和运行时间。


一、结构

1.我们先看下物品清单:

万向轮1
橡胶车轮2
亚克力板1
电位器10K1
电机码盘1
直流减速电机2
L298N电机驱动模块1
TCRT5000红外传感器2
LCD1602液晶显示屏1
STC89C51单片机1
测速传感器模块1
USB转TTL下载器1
1.5V干电池4
杜邦线、铜柱、螺丝若干

2.接下来看下重要部件以及最终实物图片

(1)电位器

在这里插入图片描述

(2)L298N电机驱动模块

在这里插入图片描述

(3)电机码盘

在这里插入图片描述

(4)TCRT5000红外传感器

在这里插入图片描述

(5)LCD1602液晶显示屏

在这里插入图片描述

(6)测速传感器模块

在这里插入图片描述

(7)小车正面

在这里插入图片描述

(8)小车背面

在这里插入图片描述
(9)LCD1602液晶屏幕实现效果

在这里插入图片描述

二、接线

1.我们先来看LCD1602液晶显示屏的接线

在这里插入图片描述

1.直接接地

2.接VCC

3.接在一个滑动变阻上再与地相接。VEE(V0)为液晶显示器对比度调整端,我们通过一个10K的电位器再与地相接用以调整对比度。(不接电位器也要接地)

4.接RS->P2.7 (RS在感应到高电平时是数据寄存器、低电平时是指令寄存器)

5.接RW->P2.6

6.接E使能端->P2.5。当E端由高电平信号跳变成低电平信号时,液晶模块执行命令

7-14.接数据写入->P0.0-P0.7

15.我们通过连接一个电阻再与VCC相连,电阻可以防止显示屏烧坏

16.直接接地(屏幕背光灯的负极)

2.测速传感器模块接线

除了接好ACC和GND外,需要把DO口接在单片机的T0计数器P3.2口上。

3.其余模块的接线较为简单,具体可以参考我的视频资料以及个人博客里的程序。

三、程序

#include<AT89X52.H>
#include <intrins.h>     //Keil外部函数库包含文件,_nop_函数在此库中

#define uint unsigned int 
//定义uint为无符号整型       
#define uchar unsigned char 
//定义uchar为无符号整型
void delayXms(uint );   //声明Xms延时函数
void delay1ms(void);    //声明1ms延时函数
/*********************变量定义***************************/
uint i,n,sec,min,hour;
uchar sec_ge,sec_shi,min_ge,min_shi,hour_ge,hour_shi,bai,shi,ge;
long int s,M;
/***************小车驱动模块输入IO口*****************/ 
   sbit IN1=P1^2; 
   sbit IN2=P1^3;
   sbit IN3=P1^4;
   sbit IN4=P1^5; 
/********************液晶屏I/O口定义**********************/
sbit RS=P2^7;	//寄存器选择位,将RS位定义为P2.0引脚			
sbit RW=P2^6;	//读写选择位,将RW位定义为P2.1引脚
sbit E =P2^5;		//使能信号位,将E位定义为P2.2引脚
/********传感器接线定义********/
    #define Left_led        P3_7	  		//接循迹模块L0,左
    #define Right_led       P3_6	       	//接循迹模块R0,右
	#define Left_go      {P1_2=1,P1_3=0;}   //左电机向前走
	#define Left_back    {P1_2=0,P1_3=1;} 	//左电机向后转
	#define Left_Stop    {P1_2=0,P1_3=0;}   //左电机停转                     
	#define Right_go     {P1_4=1,P1_5=0;}	//右电机向前走
	#define Right_back   {P1_4=0,P1_5=1;}	//右电机向后走
	#define Right_Stop   {P1_4=0,P1_5=0;}   //右电机停转   							 
/*******************初使化显示数组*********************/
uchar dis1[]={"Time:  h  m  s"};					  
uchar dis2[]={"Speed:   mm/s"};
/************************驱动函数**************************/
//前速前进
     void  run(void)
{
	 Left_go ;   //左电机往前走
	 Right_go ;  //右电机往前走
}

//后退函数 
     void  backrun(void)
{
	 Left_back;   //左电机往后走
	 Right_back;  //右电机往后走
}

//左转
     void  leftrun(void)
{
	 Right_go ;  //右电机往前走
     Left_back;  //左电机后走
}

//右转
     void  rightrun(void)
{ 
     Left_go  ;   //左电机往前走
	 Right_back;  //右电机往后走	
}

//停止
     void  stop(void)
{	 
	 Right_Stop ;  //右电机停止
     Left_Stop  ;  //左电机停止
}												  
/********************X毫秒延时函数**********************/
void delayXms(uint ms)
{
	uint k;
	for(k=0;k<ms;k++)
	  {delay1ms();}
} 
void delay1ms(void)
{
    uint j;
    for(j=0;j<=120;j++)
      {_nop_();}
}
/*******************液晶显示函数*********************/
uchar lcd_busy()	    /*判断液晶模块的忙碌状态*/
{
	bit result;
	RS=0;
	RW=1;
	E=1;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	result = (bit)(P0&0x80);
	E=0;
	return result;
}
void lcd_wcmd(uchar cmd)   /*写指令数据到LCD*/
{
	while(lcd_busy());
	RS=0;
	RW=0;
	E=0;
	_nop_();
	_nop_();
	P0=cmd;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	E=1;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	E=0;		
}

void lcd_pos(uchar pos)	 /*指定字符显示的实际地址*/ 
{
	lcd_wcmd(pos|0x80);
}
void lcd_wdat(uchar dat)		/*将数据(字符的标准ASCII码)写入液晶模块*/
{
	while(lcd_busy());
	RS=1;
	RW=0;
	E=0;
	P0=dat;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	E=1;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	E=0;	
}
void LcdInit()		/*LCD1602初始化函数*/
{
	delayXms(12);
	lcd_wcmd(0x38);
	delayXms(4);
	lcd_wcmd(0x38);	
	delayXms(4);
	lcd_wcmd(0x38);
	delayXms(4);
	lcd_wcmd(0x0c);
	delayXms(4);
	lcd_wcmd(0x06);
	delayXms(4);
	lcd_wcmd(0x01);
	delayXms(4);	
}
/*******************定时器1初使化函数**********************/
void T1_Init()
{
	TMOD = 0x10;	            //定时器1设置为8位自动加载模式
	ET1=1;			        	//开定时器中断
	EA=1;                       //打开总中断
	IP=0x04;                    //设置中断优先级
	TH1 = (65535-50000)/256;	//初使加载50毫秒
	TL1 = (65535-50000)%256;
}
/*******************外部中断初使化***********************/
void INT_Init()
{
	IT0 = 1;			//设置外部中断0为下降沿触发 
	EX0 = 1;  			//开外部中断0
	EA = 1;				//开总中断
}
/********************外部中断**************************/
void my_INT0(void) interrupt 0
{
	M=M++;			    //每中断一次变量加1
}
/******************定时器1中断*************************/
void timer1() interrupt 3
{   
    TR1=0;                      //停止T1
	TH1 = (65535-50000)/256;    //求整放在高8位
	TL1 = (65535-50000)%256;    //求余放在低8位
	n=n+1;                      //n++
	if(n==20)				  	//定时1秒(20个50ms为1秒)
	{     
		s=M/20.00*3.14*65;	    //1秒钟小车左轮走s1毫米,车轮胎直径为65MM
		bai=(s/100)+48;		    //百位转换成字符
		shi=(s%100/10)+48;		//十位转换成字符
		ge=(s%100%10)+48;	    //个位转换成字符
		n=0;                    //定时器中断次数归零
		sec++;					//1s时间											  
   		if(sec==60)             //如果秒为60,则清零,分加1
  		 {
   	   	    sec=0;
   		    min++;
   		}
   		if(min==60)             //如果分为60,则清零,时加1
   		{
    		min=0;
    		hour++;
   		}
   		if(hour==24)            //如果时为24,则清零
   		{
    		hour=0;
   		}
		sec_ge=sec%10+48;      //秒的个位和十位
		sec_shi=sec/10+48;
		min_ge=min%10+48;      //分的个位和十位
		min_shi=min/10+48;														
		hour_ge=hour%10+48;    //时的个位和十位
		hour_shi=hour/10+48;
		s=0;                   //小车左轮走的路程s1归零
		M=0;                   //外部中断0中断次数归零
	}
	 TR1=1;                    //启动T1
}
/************************主函数******************************/
void main()
{  
	T1_Init();                    //定时器T1初使化
	INT_Init();                   //外部中断初使化
	LcdInit();                    //1602液晶显示初使化
	TR1=1;			              //启动定时器T1
	lcd_pos(0x01);
	i=0;								   
	while(dis1[i] != '\0')        //1602液晶显示器第一行初使化显示
	{
		lcd_wdat(dis1[i]);
		i++;
	};											
	i=0;
	lcd_pos(0x41);
	while(dis2[i] != '\0')		  //1602液晶显示器第二行初使化显示
	{
		lcd_wdat(dis2[i]);
		i++;	
	};
/******while(1)无限循环******/ 
	while(1)                        
	{   
		if(Left_led==0&&Right_led==0)      //有信号为0  没有信号为1	  
			run();                             //调用前进函数		 
		else
		{			  
			if(Left_led==1&&Right_led==0)  //左边检测到黑线
			{
				leftrun();		               //调用小车左转函数
			}			   
			if(Right_led==1&&Left_led==0)  //右边检测到黑线
			{	  
				rightrun();		               //调用小车右转函数
			}
			if(Right_led==1&&Left_led==1)  //悬空状态  避悬崖
			{	  
				stop();		                   //调用小车停止		
			}									  
		}							 
	/****行驶时间显示***/                                   
	    lcd_pos(0x06);            
	    lcd_wdat(hour_shi);           
		lcd_pos(0x07);            
		lcd_wdat(hour_ge);                 			  
		lcd_pos(0x09);                 
		lcd_wdat(min_shi);         
        lcd_pos(0x0a);            
	    lcd_wdat(min_ge);          
		lcd_pos(0x0c);          
		lcd_wdat(sec_shi);  
		lcd_pos(0x0d);          
		lcd_wdat(sec_ge);         
	/****平均速度显示****/                                   
		lcd_pos(0x47);		     	
		lcd_wdat(bai);          
		lcd_pos(0x48);           
		lcd_wdat(shi);                    
		lcd_pos(0x49);                      
		lcd_wdat(ge);                      						  
    }	
}

具体的程序我就不讲解了,里面的注释也清晰明了,小车安装视频教程可去这里下载,本来设置不用积分下载的,不知道为什么每次都自动加上去了,没有积分的兄弟萌可以去百度云链接下载。链接:https://pan.baidu.com/s/1drKI1TT4TpylFfub0z32RA 提取码:zu15

四、运行视频

智能小车循迹

智能小车时间和速度显示

总结

我的智能小车功能比较简单,适合入门练手,具体的操作步骤和源码可以去我的个人博客里下载相关资料。# 51智能红外循迹小车(含测速和LCD显示)

  • 60
    点赞
  • 334
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值