51智能红外循迹小车(含测速和LCD显示)
51智能红外循迹小车(含测速和LCD显示)一、结构1.我们先看下物品清单:万向轮1橡胶车轮2亚克力板1电位器10K1电机码盘1直流减速电机2L298N电机驱动模块1TCRT5000红外传感器2LCD1602液晶显示屏1STC89C51单片机1测速传感器模块1USB转TTL下载器1杜邦线、铜柱、螺丝若干2.接下来看下重要部件以及最终实物图片(1)电位器(2)L298N电机驱动模块
前言
本文设计的智能车带有循迹、测速以及计时的功能,它能够在设定的范围内沿着特定的路线在前进过程中,方向可以根据线路自动更改,并且可以显示速度和运行时间。
一、结构
1.我们先看下物品清单:
万向轮 | 1 |
---|---|
橡胶车轮 | 2 |
亚克力板 | 1 |
电位器10K | 1 |
电机码盘 | 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显示)
更多推荐
所有评论(0)