当前位置: 首页 > >

基于51单片机的多功能智能小车设计论文(电路+程序+论文)1

发布时间:

基于单片机的多功能智能小车设计论文(电路+ 程序+论文)

(关键词:智能车 单片机 金属感应器


霍尔元件 1602LCD)

智能作为现代的新发明, 是以后的发展方向, 他可以按照预先设定的模式在一个环 境里自动的运作,不需要人为的管理,可应用于科学勘探等等的用途。智能电动车就是 其中的一个体现。 本次设计的简易智能电动车, 采用 AT89S52 单片机作为小车的检测和 控制核心; 采用金属感应器 TL-Q5MC 来检测路上感应到的铁片, 从而把反馈到的信号送 单片机, 使单片机按照预定的工作模式控制小车在各区域按预定的速度行驶, 并且单片 机选择的工作模式不同也可控制小车顺着 S 形铁片行驶;采用霍尔元件 A44E 检测小车 行驶速度;采用 1602LCD 实时显示小车行驶的时间,小车停止行驶后,轮流显示小车行 驶时间、 行驶距离、 *均速度以及各速度区行驶的时间。 本设*峁辜虻ィ 较容易实现, 但具有高度的智能化、人性化,一定程度体现了智能。

1





1 设计任务………………………………………………………………………………3 1.1 要求………………………………………………………………………………3 2 方案比较与选择………………………………………………………………………4 2.1 路面检测模块………………………………………………………………………4 2.2 LCD 显示模块………………………………………………………………………5 2.3 测速模块……………………………………………………………………………5 2.4 控速模块……………………………………………………………………………6 2.5 模式选择模块………………………………………………………………………7 3 程序框图………………………………………………………………………………7 4 系统的具体设计与实现………………………………………………………………9 4.1 路面检测模块………………………………………………………………………9 4.2 LCD 显示模块………………………………………………………………………9 4.3 测速模块……………………………………………………………………………9 4.4 控速模块……………………………………………………………………………9 4.5 复位电路模块………………………………………………………………………9 4.6 模式选择模块………………………………………………………………………9 5 最小系统图……………………………………………………………………………10 6 最终 PCB 板图…………………………………………………………………………12 7 系统程序………………………………………………………………………………13 8 致谢……………………………………………………………………………………46 9 参考文献……………………………………………………………………………47 10 附录…………………………………………………………………………………48

2

1. 设计任务:
设计并制作了一个智能电动车,其行驶路线满足所需的要求。 1.1 要求: 1.1.1 基本要求: (1)分区控制: 如(图 1)所示:

(图 1)

车辆从起跑线出发(出发前,车体不得超出起跑线) 。在第一个路程 C~D 区(3~6 米)以低速行驶,通过时间不低于 10s;第二个路程 D~E 区(2 米)以高速行驶,通过 时间不得多于 4 秒;第三个路程 E~F 区(3~6 米)以低速行驶,通过时间不低于 10s。 (2)小车能自动记录、显示行驶时间、行驶距离以及行驶速度,还能记录每段所走 的时间,从而判断是否符合课程设计要求。 (记录显示装置要求安装在车上) 。 1.1.2 发挥部分: S 型控制:如(图 2)所示:

3

(图 2)

车辆沿着 S 形铁片行驶,自动转弯,自动寻找正确方向和铁片。当离开 S 型铁片跑 道或者感应不到铁片一段时间的时候,小车自动停止,并记录行驶时间,路程,*均速 度并通过 LCD 显示出来。

2. 方案比较与选择:
根据设计任务要求,并且根据我们自己的需要而附加的功能,该电路的总体框图可 分为几个基本的模块,框图如(图 3)所示:

(图 3)

2.1 路面检测模块: 采用铁片感应器 TL-Q5MC 来检测路面上的铁片从而给单片机中断脉冲。原理图接线 如(图 4)所示:

4

(图 4) 2.2 LCD 显示模块: 采用 1602LCD,由单片机的总线模式连接。为节约电源电量并且不影响 LCD 的功能, LCD 的背光用单片机进行控制, LCD 的背光在小车行驶的过程中不亮, 使 因为我们不必看 其显示;在其它我们需要看显示的内容的时候 LCD 背光亮。 2.3 测速模块: 2.3.1 方案 1: 采用采用霍尔开关元器件 A44E 检测轮子上的小磁铁从而给单片机中断脉冲, 达到测 量速度的作用。霍尔元件具有体积小,频率响应宽度大,动态特性好,对外围电路要求 简单,使用寿命长,价格低廉等特点,电源要求不高,安装也较为方便。霍尔开关只对 一定强度的磁场起作用,抗干扰能力强,因此可以在车轮*沧靶〈盘舳骷 安装在固定轴上,通过对脉冲的计数进行车速测量。 2.3.2 方案 2: 采用红外传感器进行测速。但无论是反射式红外传感器还是对射式红外传感器,他们对都
对外围环境要求较高,易受外部环境的影响,稳定性不高,且价格较为昂贵。 通过对方案 1、方案 2 的比较其优缺点,综合多方面因素决定选用方案 1,其原理图接线如(图 5)所示:

(图 5)

5

2.4 控速模块: 2.4.1 方案 1: 使用功率三极管作为功率放大器的输出控制直流电机。线性型驱动的电路结构和原 理简单,成本低,加速能力强,但功率损耗大,特别是低速大转距运行时,通过电阻 R 的电流大,发热厉害,损耗大,对于小车的长时间运行不利。 2.4.2 方案 2: 采用继电器对电动机的开或关进行控制,通过开关的切换对小车的速度进行调整.此 方案的优点是电路较为简单,缺点是继电器的响应时间慢,易损坏,寿命较短,可靠性不 高。 2.4.3 方案 3: 采用由双极性管组成的 H 桥电路。用单片机控制晶体管使之工作在占空比可调的开 关状态,精确调整电机转速。这种电路由于工作在管子的饱和截止模式下,效率非常高; H 桥电路保证了可以简单地实现转速和方向的控制; 电子开关的速度很快, 稳定性也很高, 是一种广泛采用的调速技术。 综合 3 种方案的优缺点,决定选择方案 3,其电路原理图如(图 6)所示:

(图 6)

6

2.5 模式选择模块: 模式选择模块通过一个 74LS00 与非门和两个不带锁按钮来控制单片机单片机的两个 中断口,从而按动按钮来选择小车走动的路型、来选择小车的速度是快速、中速、慢速; 走完路程小车停止后还可以通过按钮选择想要在 LCD 上想看的信息,比如总时间、走过 各段路程的时间、*均速度、总路程等。 小车走动的模式选择有: (1) 直线型:满足设计任务的基本要求,能稳定的走完全程。之后按顺序循环不 断的显示走完全程所用的时间、走完高速区所用的时间和走完低速区所用的时间这三个 时间;或者可以通过两个按钮以及 LCD 显示的菜单选择所要看的内容如*均速度、全程 距离以及那三个时间。 (2) S 型:满足设计任务的发挥部分的要求,小车能自动的感应到在前面或在后面 铁片,即第一次转弯后若感应到的是错误的方向,则小车会后退自动调整方向,沿着 S 型的铁片走。当走完 S 型铁片后的一定时间里,小车自动停止。之后自动进入菜单由我 们自己选择要看的内容时间、*均速度和所走的距离。 (3)自动型:小车先以一定的速度走完全程,之后再以一定的速度倒退*鸬悖 调整速度在一定的时间内走完全程。走完后 LCD 显示的内容与直线型显示的内容一样。

3. 程序框图:
单片机主程序框图、速度感应程序框图和铁片感应程序框图分别如(图 7)所示。

7

8

(图 7)
9

4.系统的具体设计与实现:
4.1 路面检测模块: 应用一个金属感应器,安装在车盘下,离地略小于或约四毫米。当金属传感器检测 到铁片时将对单片机发送中断信号,单片机运行中断,改变输给电机驱动信号的电压占 空比来控制小车的速度。 4.2 LCD 显示模块: 采用 1602LCD,由单片机的总线模式连接。为节约电源,LCD 的背光用单片机进行控 制。 4.3 测速模块: 通过霍尔元件感应磁铁来产生脉冲(当霍尔元件在离磁场较*时输出会是高电*,其 它时候是低电*),一个车轮均匀放四个小磁铁,计算一秒所得的脉冲数,从而计算出一 秒小车轮子转动圈数,再测量出小车车轮周长即可计算出小车当前速度,累加可得到当 前路程。 4.4 控速模块: 考虑到元器件的缺少以及我们所用的电路的驱动电机的电路原理图和和小车自带的 电路的电机驱动原理图一样,所以暂时使用小车自带的电机驱动电路图。 4.5 复位电路模块: 单片机的复位电路通过手动来实现,复位电路图如(图 8)所示。

2

2

u

VCC

2

0

0

1

(图 8)

4.6 模式选择模块:
10

K

RST

两个中断口使用和感应铁片、感应速度所使用的中断口一样,通过一个与非门和按 钮控制。原理图如(图 9)所示:

(图 9)

5.最小系统图:
该系统主要用到的是单片机,所以主要的部分是最小系统图,该最小系统图如(图 10)所示:

11

(图 12)
12

6. 最终 PCB 板图:
该最小系统的最终 PCB 板图(包括 LCD 接口以及其他的外部扩展电路部分,考虑到 最小系统的简洁以及容易看懂,外部扩展电路不在最小系统图上显示。 )分别如(图 11) 、 (图 12)所示:

(图 11)

13

(图 12)

7.系统程序:
按照预定的功能,系统实现预定的功能的程序如下所示:

#include <intrins.h> #include <AT89X52.h> /********************************************************************************\ ** 宏定义区 ** \********************************************************************************/ /*------------------------------#define LCD_RW #define LCD_RS #define LCD_E #define LCD_Data #define Write #define Read #define Data #define Cmd P2_1 P2_0 P2_2 P1 0x00 0x01 0x01 0x00 LCD模块 ------------------------------------*/ //读写控制端 //数据命令选择端 //执行使能端 //P1口 //低电*写入 //高电*读出 //高电*选择数据 //低电*选择命令 14

#define Enable #define Disable #define True #define False #define LCD_Init #define LCD_DispCtr #define LCD_CloseCtr #define LCD_CLS #define LCD_EnterSet #define Busy /*-------------------------#define CircleLength

0x00 0x01 0x01 0x00 0x38 0x0C 0x08 0x01 0x06 P1_7

//跃变到低电*时执行命令

//初始化模式 //开显示及光标设置 //关显示 //清屏幕 //显示光标 //忙信号

测速/测距/测时模块 -------------------------------*/ 0.132 //小车转一轮的长度为.132m 控速模块 -----------------------------------*/ //后电机 //后电机 //前电机 //前电机 //控制液晶背光

/*-------------------------------#define P03 #define P04 #define P01 #define P02 #define P31 #define P33 P0_3 P0_4 P0_1 P0_2 P0_5 P3_3

/*-----------------------------#define Line #define Curve #define Normal #define Low #define High 0x00 0x01 0x00 0x01 0x02

菜单选择模块 ---------------------------------*/ //0代表直线模式 //1代表S型模式 //0 代表正常速度 //1 代表低速 //2 代表高速

/*********************************************************************************\ ** 全局函数声明区 ** \*********************************************************************************/ /*------------------------------void LCDInit(void); void SetWriteCmd(void); void SetReadCmd(void); void SetWriteData(void); void WriteCmd(char cmd); void WriteData(char ddata); void ExecuteCmd(void); void SetXY(char x,char y); void DisplaySingleChar(char x,char y,char cchar); void DisplayString(char x,char y,char *str); 15 LCD模块 -------------------------------------*/ //LCD初始化 //设置写命令模式 //设置读命令模式 //设置写数据模式 //写命令 //写数据 //执行命令 //定位显示地址 //显示单个字符 //显示一段字符串

void Delay(unsigned int time); void DelayUs(unsigned int time); bit IsBusy(void); void DisplayTime(void); void DisplayAVGSpeed(void); void DisplayDistance(void); /*-------------------------void INTInit(void); void SpeedINT(void); void ComputeTime(void); void ComputeSpeedANDDistance(void); /*-------------------------------void CtrSpeedINT(void); void Time0INT(void); void Time1INT(void); void Clock0_Init(void); void Clock1_Init(void); void CtrSpeed(void);

//延时主程序 //延时子程序 //判断忙标志函数 //显示时间 //显示*均速度 //显示路程

测速/测距/测时模块 -------------------------------*/ //所有中断初始化 //测速中断 //计算速度和距离 控速模块 -----------------------------------*/ //控速中断 //控速单位时间中断 //时钟中断初始化 //时钟中断初始化

/********************************************************************************\ ** 全局变量区 ** \********************************************************************************/ float SpeedCount = 0; float Speed = 0.0; float Distance = 0.0; char Time1INTCount=0; //T1中断时间计时 //小车行走的时间 //判断T1是否已经响应中断 float PassTime=0.00; short IsT0INT=1; bit IsT1INT; short IsT0INT2=1; char char char char char char Thx[5]={0xf4,0xf4,0xc5,0xf4,0xff}; Tlx[5]={0x48,0x48,0x68,0x48,0xff}; Thx0=0xd8; Tlx0=0xf0; Thx1=0xb1; Tlx1=0xe0; //20ms //3ms,3ms,15ms,3ms //测速计数脉冲

short Round=0; short Back=0; 16

short Back0=0; bit bit char char char char char char char char char char char bit char char char bit bit bit bit bit char bit bit char bit bit bit bit bit bit bit bit bit bit bit Backid; Stop=0; Area0=0; Area1=0; LowSpeedArea1StartTime; LowSpeedArea1EndTime; HighSpeedAreaEndTime; LowSpeedArea2EndTime; LowSpeedArea1PassTime=0; HighSpeedAreaPassTime=0; LowSpeedArea2PassTime=0; ReadyToGo=4; flag; Roundid=0; Nocurve=0; ChangeFlag; Mode; Running; SelectedAll; IsSelectingMode; IsSelectingSpeed; ModeSelected; SelectedMode=10; Next; SpeedSelected; SelectedSpeed; ChoosingDisplay; SelectedShow; SelectedReturn; Selected; ReturnSelection; AVGSpeedShow; TotalDistanceShow; ReturnMain; AutoDisplay; GoToChoosingDisplay; AutoMode=0; 17 //模式和速度是否选择完毕标志 //模式选择标志 //速度选择标志 //已经被选择的模式标志 //模式选择是否完毕标志 //Next键标志 //已经被选中的速度方案标志 //速度选择是否完毕标志 //人工选择菜单开始标志 //显示选择标志 //返回选择标志 //确定/返回键选择标志 //返回键启用标志 //*均速度显示标志 //总路程显示标志 //返回主菜单标志 //自动显示标志 //人工选择标志 //第一个低速区通过时间 //高速区通过时间 //第二个低速区通过时间 //倒计时 //区域变量

char char

PassLineID=0; PassLine=0;

float PrepareDistance; float FirstDistance; float SecondDistance; float ThirdDistance; int int int FirstHigh; SecondHigh; ThirdHigh; //5ms时的速度 //时间的倍数

float Rate=1.25; float Count=4;

/********************************************************************************\ ** 全局函数实现区 ** \********************************************************************************/ /*-------------------------------void main() { P01=0; P02=0; P03=0; P04=0; P31=1; Delay(40); LCDInit(); DisplayString(0x0,0," Starting... "); DisplayString(0x0,1,"Designed By 202"); Delay(300); WriteCmd(LCD_CLS); EA=1; EX0=1; IT0=1; EX1=1; IT1=1; SelectedAll=False; /*-----------------------------//开总中断 //开INT0中断 //INTO边沿触发 //开INT1中断 //INT1边沿触发 //开始模式和速度选择 模式选择 ---------------------------------*/ //单片机复位,背光开 //延时等待LCD启动 //初始化LCD 主函数 ------------------------------------*/

DisplayString(0x0,0,"Choose The Mode "); 18

DisplayString(0x0,1,"you want. Delay(50); WriteCmd(LCD_CLS); IsSelectingMode=True; while(1) { WriteCmd(LCD_CLS); DisplayString(0x0,0,"

");

Line Mode

"); Yes"); //延时消除抖动 //不断检测中断,直到按确定键或是NEXT键 //如果按Next键则直接跳出 //如果按确定键则设置模式为Line并跳出

DisplayString(0x0,1,"Next Delay(300); while (1) { if (Next==True) break; if (ModeSelected==True) { SelectedMode=Line; break; } } if (ModeSelected==True) { IsSelectingMode=False; break; } if (Next==True) { Next=False; WriteCmd(LCD_CLS);

//如果什么键都没有按下,那么一直显示等待

//按下了确定键,退出模式选择

//按下了Next键,显示下一个菜单项

DisplayString(0x0,0," Curve Mode DisplayString(0x0,1,"Next Delay(300); while(1) { if (Next==True) break; if (ModeSelected==True) { SelectedMode=Curve;

"); Yes"); //延时消除抖动 //不断检测中断,直到按确定键或是Next键 //如果再一次按下Next键,则跳出 //如果按下确定键,则设置模式为Curve,并跳出

19

break; } } } if (ModeSelected==True) { IsSelectingMode=False; break; } if (Next==True) { Next=False; WriteCmd(LCD_CLS); DisplayString(0x0,0," AutoMode "); Yes"); //延时消除抖动 DisplayString(0x0,1,"Next Delay(300); while(1) { if (Next==True) break; if (ModeSelected==True) { AutoMode=1; break; } } } if (ModeSelected==True) { IsSelectingMode=False; break; } if (Next==True) { Next=False; continue; } } //再一次按下了Next键,则循环模式选择 //按下了确定键,退出模式选择

20

Delay(50); WriteCmd(LCD_CLS); /*------------------------------ 速度选择 ---------------------------------*/ if (SelectedMode==Line && AutoMode==0) { DisplayString(0x0,0," Now Choose a Delay(50); WriteCmd(LCD_CLS); IsSelectingSpeed=True; while(1) { WriteCmd(LCD_CLS); DisplayString(0x0,0," Normal Speed DisplayString(0x0,1,"Next Delay(300); while(1) { if (Next==True) break; if (SpeedSelected==True) { Thx[0]=0xec;Tlx[0]=0x78; Thx[1]=0xf0;Tlx[1]=0x60; Thx[2]=0x8a;Tlx[2]=0xd0; Thx[3]=0xf4;Tlx[3]=0x48; SelectedSpeed=Normal; break; } } if (SpeedSelected==True) { IsSelectingSpeed=False; break; } if (Next==True) { Next=False; 21 //按下了确定键,退出速度选择 //如果什么键都没有按下,那么一直显示等待 //5ms //4ms //30ms //3ms //如果按确定键则设置速度为Normal并跳出 //如果按Next键则直接跳出 "); Yes"); //延时消除抖动 "); DisplayString(0x0,1," kind of Speed ");

WriteCmd(LCD_CLS); DisplayString(0x0,0," Low Speed "); DisplayString(0x0,1,"Next Delay(300); while(1) { if (Next==True) break; if (SpeedSelected==True) { SelectedSpeed=Low; break; } } } if (SpeedSelected==True) { IsSelectingSpeed=False; break; } if (Next==True) { Next=False; WriteCmd(LCD_CLS); DisplayString(0x0,0," High DisplayString(0x0,1,"Next Delay(300); while(1) { if (Next==True) break; if (SpeedSelected==True) { Thx[0]=0xe0;Tlx[0]=0xc0; //8ms Thx[1]=0xe0;Tlx[1]=0xc0; Thx[2]=0x63;Tlx[2]=0xc0; Thx[3]=0xec;Tlx[3]=0x78; SelectedSpeed=High; break; 22 //8ms //40ms //5ms //如果按下确定键,则设置速度为High,并跳出 //如果再一次按下Next键,则跳出 Speed "); Yes"); //延时消除抖动 //按下了确定键,退出速度选择 //这里没有速度设置,因为默认速度就是Low //如果按下确定键,则设置速度为Low,并跳出 //如果再一次按下Next键,则跳出 Yes"); //延时消除抖动

} } } if (SpeedSelected==True) { IsSelectingSpeed=False; break; } if (Next==True) { Next=False; continue; } } } SelectedAll=True; Running=True; Delay(50); WriteCmd(LCD_CLS); //标志模式选择和速度选择完毕 //再一次按下了Next键,则循环速度选择 //按下了确定键,退出速度选择

/*------------------------- 显示所选择的模式和速度方案 -------------------------*/ if (SelectedMode==Line) { DisplayString(0x0,0,"Choosen Mode is "); DisplayString(0x0,1," Delay(50); WriteCmd(LCD_CLS); } if (SelectedMode==Curve) { DisplayString(0x0,0,"Choosen Mode is "); DisplayString(0x0,1," Delay(50); WriteCmd(LCD_CLS); } if (AutoMode==1) { DisplayString(0x0,0,"Choosen Mode is "); 23 Curve "); Line ");

DisplayString(0x0,1," Delay(50); WriteCmd(LCD_CLS); } if (SelectedMode==Line) {

AutoMode

");

if (SelectedSpeed==Normal) { DisplayString(0x0,0,"Choosen Speed is"); DisplayString(0x0,1," Delay(50); WriteCmd(LCD_CLS); } if (SelectedSpeed==Low) { DisplayString(0x0,0,"Choosen Speed is"); DisplayString(0x0,1," Delay(50); WriteCmd(LCD_CLS); } if (SelectedSpeed==High) { DisplayString(0x0,0,"Choosen Speed is"); DisplayString(0x0,1," Delay(50); WriteCmd(LCD_CLS); } } INTInit(); DisplayString(0x0,0,"Left Times To Go"); while (ReadyToGo--) { DisplaySingleChar(0x7,1,ReadyToGo+0x30); DisplaySingleChar(0x09,1,'s'); Delay(300); } WriteCmd(LCD_CLS); DisplayString(0x05,0,"Go!!!"); Delay(100); WriteCmd(LCD_CLS); DisplayString(0x0,0," Living... "); 24 //初始化所有中断 High "); Low "); Normal ");

DisplayString(0x0,1,"Designed by 202");

if (SelectedMode==Line&&AutoMode==0) flag=Area0; else flag=1; while(flag<5) { if(AutoMode==1) { switch(PassLineID) { case 0 :{ if(IsT0INT==1) {P01=P02=P04=0;P03=1;} else {P01=P02=P03=P04=0;} }break; case 1 :{ P01=P02=P03=0;P04=1; }break; case 2 :{ P01=P02=P04=0;P03=1; }break; default :break; } } else { if(SelectedMode==Line) { flag=Area0; if(IsT0INT==1) {P03=1;P04=0;P01=P02=0;} else {P03=0;P04=0;P01=P02=0;} } else { { if(Backid==1) {P01=1;P02=0;P03=0;P04=1;} 25 //S型模式 if((Nocurve<2)&&Round!=0&&(Back0>0)&&Back!=0) //直线模式 //自动模式

else {P01=0;P02=1;P03=0;P04=1;} Back=1; } else { if(Round==0) { if(IsT0INT2==1) {P01=0;P02=0;P03=1;P04=0;} else {P01=0;P02=0;P03=0;P04=0;} } else { if(P33==0) { if(IsT0INT2==1) {P01=0;P02=0;P03=1;P04=0;} else {P01=0;P02=0;P03=0;P04=0;} } else { EX1=1; if(Round%2) { if(IsT0INT2==1) {P01=1;P02=0;P03=1;P04=0;Backid=1;} else {P01=1;P02=0;P03=0;P04=0;} } else { if(IsT0INT2==1) {P01=0;P02=1;P03=1;P04=0;Backid=0;} else {P01=0;P02=1;P03=0;P04=0;} } } } } } }

26

if (IsT1INT==1) { IsT1INT=0; ComputeTime(); ComputeSpeedANDDistance(); } } //补中断路程,加上最后一次中断缺失的路程 ComputeSpeedANDDistance(); P04=1;P03=0;P01=P02=0;Delay(90); P03=0;P04=0; P31=1; ET0=0x0; ET1=0x0; EX1=0x01; Running=False; //行程结束,小车停止 //行程结束,背光开 //关T0中断 //关T1中断 //开INT1中断

AutoDisplay=True; WriteCmd(LCD_CLS); if (SelectedMode==Line) { while(1) { if (GoToChoosingDisplay==True) break; Delay(200); WriteCmd(LCD_CLS); Delay(200);

//默认情况下直线模式会自动显示各个区域经过的时间

//直线模式才显示

DisplayString(0,0," LowSpeedArea1"); DisplayString(0,1," Costed "); DisplaySingleChar(0x0C,1,'s'); LowSpeedArea1PassTime=LowSpeedArea1EndTime-LowSpeedArea1StartTime; DisplaySingleChar(0x0A,1,LowSpeedArea1PassTime%10+0x30); if (LowSpeedArea1PassTime > 9) //通过第一个低速区的时间超过s DisplaySingleChar(0x0B,1,LowSpeedArea1PassTime/10+0x30); if (GoToChoosingDisplay==True) break; Delay(200); WriteCmd(LCD_CLS); Delay(200); DisplayString(0,0," HighSpeedArea "); 27

DisplayString(0,1," Costed "); DisplaySingleChar(0x0C,1,'s'); HighSpeedAreaPassTime=HighSpeedAreaEndTime-LowSpeedArea1EndTime; DisplaySingleChar(0x0A,1,HighSpeedAreaPassTime%10+0x30); if ( HighSpeedAreaPassTime> 9) //通过高速区的时间超过s DisplaySingleChar(0x0B,1,HighSpeedAreaPassTime/10+0x30);

if (GoToChoosingDisplay==True) break; Delay(200); WriteCmd(LCD_CLS); Delay(200); DisplayString(0,0," LowSpeedArea2 "); DisplayString(0,1," Costed "); DisplaySingleChar(0x0C,1,'s'); LowSpeedArea2PassTime=LowSpeedArea2EndTime-HighSpeedAreaEndTime; DisplaySingleChar(0x0A,1,LowSpeedArea2PassTime%10+0x30); if ( LowSpeedArea2PassTime> 9) //通过第二个低速区的时间超过s DisplaySingleChar(0x0B,1,LowSpeedArea2PassTime/10+0x30); } } AutoDisplay=False; /*---------------WriteCmd(LCD_CLS); /*首先显示主菜单,然后显示第一个选项*/ DisplayString(0x0,0,"Now Choose what "); DisplayString(0x0,1,"you want to see "); Delay(100); while(1) { WriteCmd(LCD_CLS); DisplayString(0x0,0," Costed Time "); DisplayString(0x0,1,"Next Delay(250); Show"); //延时消除抖动 菜单选择你想要看的内容--总时间、总路程以及*均速度 --------------*/

ChoosingDisplay=True;

/*------------------------------------第一次按键--------------------------------------*/ 28

/*不断检测确定键和Next键*/ while(1) { if (Next==True) break; if (SelectedShow==True) break; } /*按下了确定键,显示第一个选项的内容*/ if (SelectedShow==True) { SelectedShow=False; SelectedReturn=False; Selected=False; WriteCmd(LCD_CLS); DisplayString(0,0,"Costed Time is"); DisplayTime(); DisplayString(0x0A,1,"s"); ReturnSelection=True; AVGSpeedShow=False; Delay(250); } /**按下了Next键,则显示第二个选项*/ if (Next==True) { Next=False; WriteCmd(LCD_CLS); DisplayString(0x0,0," ReturnMain=False; ReturnSelection=False; AVGSpeedShow=True; Delay(250); } /*------------------------------------第二次按键--------------------------------------*/ /*显示第一个选项的内容后又不断检测返回键(确定键)和Next键*/ while(1) { if (Next==True) 29 //按下了Next键,那么这个时候关闭返回键的功能 //表明AVGSpeed选项已经显示过了 //延时消除抖动 AVGSpeed "); Show"); DisplayString(0x0,1,"Next //按下Next键,显示AVGSpeed菜单项 //延时消除抖动 //按下了确定键,那么这个时候开启返回键的功能

break; if (Selected==True) break; } if (Next==True) { Next=False; ReturnMain=False; ReturnSelection=False; if (AVGSpeedShow==False) { WriteCmd(LCD_CLS); DisplayString(0x0,0," TotalDistanceShow=False; Delay(250); } if (AVGSpeedShow==True) { WriteCmd(LCD_CLS); DisplayString(0x0,0," Total Distance "); DisplayString(0x0,1,"Next TotalDistanceShow=True; Delay(250); } } if (Selected==True) { SelectedShow=False; SelectedReturn=False; Selected=False; if (ReturnSelection==True) ReturnMain=True; if (ReturnSelection==False) { WriteCmd(LCD_CLS); DisplayString(0,0,"The AVGSpeed is"); DisplayAVGSpeed(); DisplayString(0x0A,1,"m/s"); ReturnSelection=True; //按下了确定键,那么这个时候开启返回键的功能 30 //第一次选择了确定键,故这次按下的是返回键 //按下了确定键或返回键 Show"); //表明显示了TotalDistance选项 //延时消除抖动 //已经显示过AVGSpeed选项了,则显示下一个选项 //即第一次选择了Next键 AVGSpeed "); Show"); //显示了AVGSpeed,则表明TotalDistance还没有显示 //延时消除抖动 DisplayString(0x0,1,"Next //按下了Next键,那么这个时候关闭返回键的功能 //还没有显示AVGSpeed选项,显示它 //即第一次选择了确定键

Delay(250); } TotalDistanceShow=False; } if (ReturnMain==True) { ReturnMain=False; continue; }

//延时消除抖动

//按下了返回键,返回主菜单

/*------------------------------------第三次按键--------------------------------------*/ /*如果没有返回主菜单,则继续检测Next键和确定键*/ while(1) { if (Next==True) break; if (SelectedShow==True) break; } /*按下Next键,显示下一个选项*/ if (Next==True) { Next=False; ReturnMain=False; ReturnSelection=False; if (TotalDistanceShow==True) ReturnMain=True; if (TotalDistanceShow==False) { WriteCmd(LCD_CLS); DisplayString(0x0,0," Total Distance "); DisplayString(0x0,1,"Next TotalDistanceShow=True; Delay(250); } } if (Selected==True) { 31 //按下了确定键或返回键 //延时消除抖动 Show"); //还没有显示TotalDistance选项,显示它 //按下了Next键,那么这个时候关闭返回键的功能

SelectedShow=False; SelectedReturn=False; Selected=False; if (ReturnSelection==True) ReturnMain=True; if (ReturnSelection==False) { if (TotalDistanceShow==False) { WriteCmd(LCD_CLS); DisplayString(0,0,"The AVGSpeed is"); DisplayAVGSpeed(); DisplayString(0x0A,1,"m/s"); ReturnSelection=True; Delay(250); } if (TotalDistanceShow==True) { WriteCmd(LCD_CLS); DisplayString(0,0,"Total Distance"); DisplayDistance(); DisplayString(0x0A,1,"m"); ReturnSelection=True; Delay(250); } } } if (ReturnMain==True) { ReturnMain=False; continue; } /*------------------------------------第四次按键--------------------------------------*/ while(1) { if (Next==True) break; if (SelectedShow==True) break; } //按下了返回键,返回主菜单 //按下了确定键,那么这个时候开启返回键的功能 //延时消除抖动 //延时消除抖动 //表明AVGSpeed选项的内容还没有显示 //按下的是返回键

32

if (Next==True) { Next=False; ReturnMain=False; ReturnSelection=False; if (TotalDistanceShow==False) { WriteCmd(LCD_CLS);

//所有菜单项已经显示完毕,返回主菜单

DisplayString(0x0,0," Total Distance "); DisplayString(0x0,1,"Next TotalDistanceShow=True; Delay(250); } } if (SelectedShow==True) { SelectedShow=False; SelectedReturn=False; Selected=False; if (ReturnSelection==True) ReturnMain=True; if (ReturnSelection==False) { if (TotalDistanceShow==True) { WriteCmd(LCD_CLS); DisplayString(0,0,"Total Distance"); DisplayDistance(); DisplayString(0x0A,1,"m"); ReturnSelection=True; //按下了确定键,那么这个时候开启返回键的功能 Delay(250); } } } if (ReturnMain==True) { ReturnMain=False; continue; } //按下了返回键,返回主菜单 //延时消除抖动 //按下的是返回键 //延时消除抖动 Show");

33

/*------------------------------------第五次按键--------------------------------------*/ while(1) { if (Next==True) break; if (SelectedShow==True) break; } if (Next==True) { Next=False; ReturnMain=False; ReturnSelection=False; if (TotalDistanceShow==True) { ReturnMain=True; } } if (SelectedShow==True) { SelectedShow=False; SelectedReturn=False; Selected=False; if (ReturnSelection==True) ReturnMain=True; if (ReturnSelection==False) { if (TotalDistanceShow==True) { WriteCmd(LCD_CLS); DisplayString(0,0,"Total Distance"); DisplayDistance(); DisplayString(0x0A,1,"m"); ReturnSelection=True; Delay(250); } } } /*------------------------------------第六次按键--------------------------------------*/ while(1) 34 //按下了确定键,那么这个时候开启返回键的功能 //延时消除抖动 //按下的是返回键 //最后一个选项已经显示完毕,返回主菜单 //所有菜单项已经显示完毕,返回主菜单

{ if (Next==True) break; if (SelectedShow==True) break; } if (Next==True) { Next=False; ReturnMain=False; ReturnSelection=False; } if (SelectedShow==True) { SelectedShow=False; SelectedReturn=False; Selected=False; } continue; } while(1); }

/****************************************************************************************\ ** LCD驱动模块 ** \****************************************************************************************/ /*--------------------------------void LCDInit(void) { //三次显示模式设置 LCD_Data=0; LCD_E=Disable; Delay(5); WriteCmd(LCD_Init); Delay(5); WriteCmd(LCD_Init); Delay(5); WriteCmd(LCD_Init); WriteCmd(LCD_Init); WriteCmd(LCD_CloseCtr); 35 //初始化 //关显示 LCD初始化函数--------------------------------------*/

WriteCmd(LCD_CLS); WriteCmd(LCD_EnterSet); WriteCmd(LCD_DispCtr); } /*--------------------------------SetWriteCmd() SetReadCmd() SetWriteData()

//清屏幕 //光标移动设置 //显示开以及光标设置

LCD模式设置函数--------------------------------------*\ 设置LCD为写命令模式 设置LCD为读命令模式 设置LCD为写数据模式

\*----------------------------------------------------------------------------------------*/ void SetWriteCmd(void) { LCD_RW=Write; LCD_RS=Cmd; } void SetReadCmd(void) { LCD_RW=Read; LCD_RS=Cmd; } void SetWriteData(void) { LCD_RW=Write; LCD_RS=Data; } /*--------------------------------WriteCmd() WriteData() ExecuteCmd() SetXY() DisplaySingleChar() DisplayString() IsBusy() void WriteCmd(char cmd) { while(IsBusy()); LCD_Data=cmd; 36 LCD功能执行函数--------------------------------------*\ 写命令 写数据 执行命令 显示定位 显示单个字符 显示一串字符 忙标志检测

\*----------------------------------------------------------------------------------------*/

SetWriteCmd(); ExecuteCmd(); } void WriteData(char ddata) { while(IsBusy()); LCD_Data=ddata; SetWriteData(); ExecuteCmd(); } void ExecuteCmd(void) { LCD_E=Enable; LCD_E=Disable; } void SetXY(char x,char y) { if (y) x|=0x40; x|=0x80; Delay(5); WriteCmd(x); } void DisplaySingleChar(char x,char y,char cchar) { SetXY(x,y); WriteData(cchar); } void DisplayString(char x,char y,char *str) { while(*str) { Delay(5); DisplaySingleChar(x++,y,*str); str++; } } bit IsBusy(void) 37

{ LCD_Data=0xFF; SetReadCmd(); ExecuteCmd(); return (bit)(P1 & 0x80); } /*------------------------------------void Delay(unsigned int time) { unsigned int timeCounter = 0; for (timeCounter = time;timeCounter > 0 ;timeCounter --) DelayUs(255); } void DelayUs(unsigned int time) { unsigned int timeCounter = 0; for (timeCounter = 0;timeCounter < time;timeCounter ++) _nop_(); } /*******************************************************************************************\ ** LCD显示模块 ** \*******************************************************************************************/ void ComputeTime(void) { if (Area0 < 5) PassTime+=0.5; } void ComputeSpeedANDDistance(void) { Speed=SpeedCount/4*CircleLength; Distance+=Speed; SpeedCount=0; } /*------------------------------------void DisplayTime(void) { char PassTime1=0x30; char PassTime2=0x30; char PassTime3=0x30; 38 显示时间 ----------------------------------------*/ //计算瞬时速度 //计算距离 延时函数 -------------------------------------*/

char PassTime4=0x30; if ((int)PassTime*100<100) { PassTime1+=0; PassTime2+=(int)(PassTime*100)/10; PassTime3+=(int)(PassTime*100)%10; } else if ((int)(PassTime*100) > 100 && (int)(PassTime*100) < 1000) //够1s而未够10s { PassTime1+=(int)(PassTime*100)/100; PassTime2+=(int)(PassTime*100)/10%10; PassTime3+=(int)(PassTime*100)%10; } else { PassTime1+=(int)(PassTime*100)/1000; PassTime2+=(int)(PassTime*100)/100%10; PassTime3+=(int)(PassTime*100)/10%10; PassTime4+=(int)(PassTime*100)%10; } if ((int)(PassTime*100) < 1000) { DisplaySingleChar(0x05,1,PassTime1); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,PassTime2); DisplaySingleChar(0x08,1,PassTime3); } else { DisplaySingleChar(0x04,1,PassTime1); DisplaySingleChar(0x05,1,PassTime2); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,PassTime3); DisplaySingleChar(0x08,1,PassTime4); } //时间未够1s

} /*------------------------------------ 显示*均速度----------------------------------------*/ void DisplayAVGSpeed(void) { int Speed1=0x30; 39 //初始化为0的ASCII码

int Speed2=0x30; int Speed3=0x30; if ((int)(Distance/PassTime*100)< 100) { Speed1+=0; Speed2+=(int)(Distance/PassTime*100)/10; Speed3+=(int)(Distance/PassTime*100)%10; } else { Speed1+=(int)(Distance/PassTime*100)/100; Speed2+=(int)(Distance/PassTime*100)/10%10; Speed3+=(int)(Distance/PassTime*100)%10; } DisplaySingleChar(0x05,1,Speed1); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,Speed2); DisplaySingleChar(0x08,1,Speed3); } /*------------------------------------void DisplayDistance(void) { int Distance1=0x30; int Distance2=0x30; int Distance3=0x30; int Distance4=0x30; if ((int)(Distance*100) < 100) { Distance1+=0; Distance2+=(int)(Distance*100)/10; Distance3+=(int)(Distance*100)%10; } else if ((int)(Distance*100) > 100 && (int)(Distance*100) < 1000) { Distance1+=(int)(Distance*100)/100; Distance2+=(int)(Distance*100)/10%10; Distance3+=(int)(Distance*100)%10; } else { Distance1+=(int)(Distance*100)/1000; 40 显示路程 ----------------------------------------*/

Distance2+=(int)(Distance*100)/100%10; Distance3+=(int)(Distance*100)/10%10; Distance4+=(int)(Distance*100)%10; }

if ((int)(Distance*100) < 1000) { DisplaySingleChar(0x05,1,Distance1); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,Distance2); DisplaySingleChar(0x08,1,Distance3); } else { DisplaySingleChar(0x04,1,Distance1); DisplaySingleChar(0x05,1,Distance2); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,Distance3); DisplaySingleChar(0x08,1,Distance4); } } /*------------------------------------void INTInit(void) { EA=1; IT0=1; PX0=1; EX1=1; IT1=1; PX1=1; Clock0_Init(); TMOD=0x11; ET0=0x01; ET1=0x01; } void Clock0_Init(void) { TR0=0x01; TH0=Thx0; TL0=Tlx0; } 41 //启动T0 //定时初值 //开总中断 //INTO边沿触发 //INTO优先级为高级 //开INT1中断 //INT1边沿触发 //INT1优先级为高级 //初始化时钟中断 //T0/T1定时方式1 //开T0中断 //开T1中断 中断初始化 -------------------------------------*/

void Clock1_Init(void) { TR1=0x01; TH1=0x3C; TL1=0x0B0; } /*******************************************************************************************\ ** 中断处理程序 ** \*******************************************************************************************/ /*----------------------------------外部中断0有两个功能 (1)作为菜单选择的Next键 (2)作为测速的计数器 \*-----------------------------------------------------------------------------------------*/ void SpeedINT(void) interrupt 0 { if (SelectedAll==False) Next=True; if (Running==True) SpeedCount++; if (ChoosingDisplay==True) Next=True; } //如果是在选择要显示的内容 //如果模式和速度已经选择完毕,则此中断作为测速中断 //如果模式和速度还没有选择完毕,则此中断作为Next键 //中断INT0 外部中断0 ----------------------------------------*\ //启动T1 //定时初值-50ms中断一次

/*----------------------------------外部中断1有两个功能 (1)作为菜单选择的确定键/返回键 (2)控速

外部中断1 ----------------------------------------*\

\*-----------------------------------------------------------------------------------------*/ void CtrSpeedINT(void) interrupt 2 { if (SelectedAll==False) { if (IsSelectingMode==True) ModeSelected=True; 42 //模式选择标志 //如果模式和速度还没有选择完毕,则此中断作为确定键 //中断INT1

if (IsSelectingSpeed==True) SpeedSelected=True; } if (Running==True) { if (Area0==0) { EX0=1; Clock1_Init(); P31=0; } if (Area0==1) LowSpeedArea1StartTime=PassTime; if (Area0==2)

//速度选择标志

//如果模式和速度选择已经完毕,则此中断作为控速中断 //经过第一条铁线(即起跑线),开始计时,开始测速

//过起跑线,背光灭

//读取进入第一个低速区的时刻

LowSpeedArea1EndTime=PassTime;//读取离开第一个低速区的时刻,也就是进入高速区的时刻 if (Area0==3) HighSpeedAreaEndTime=PassTime;//读取离开高速区的时刻,也就是进入第二个低速区的时刻 if (Area0==4) LowSpeedArea2EndTime=PassTime; if(AutoMode==1) { PassLine++; switch(PassLine) { case 5 :PassLineID=1;break; case 10 :PassLineID=2;break; default :PassLineID=PassLineID;break; } } else { if (SelectedMode==Line) { Thx0=Thx[Area0++]; Tlx0=Tlx[Area1++]; if (Area0==5) EX1=0; } else { Nocurve++; Round++; if(Roundid==1&&Round==2) 43 //S型模式 //直线模式 //读取离开第二个低速去的时刻 //自动模式

{Round++;Roundid=0;} Back=0; Back0=0; EX1=0; } } IE1=0; } if (AutoDisplay==True) { GoToChoosingDisplay=True; } if (ChoosingDisplay==True) { SelectedShow=True; SelectedReturn=True; Selected=True; } } /*-------------------------------------T0中断用来输出方波以控制速度 \*-----------------------------------------------------------------------------------------*/ void Time0INT(void) interrupt 1 { if(AutoMode==1) { IsT0INT*=-1; switch(PassLine) { case 2 case 4 case 5 } switch(PassLineID) { case 0 :{ if(IsT0INT==1) {TR0=0x01;TH0=0xec;TL0=0x78;} else {TR0=0x01;TH0=0xb1;TL0=0xe0;} }break; case 1 :{ 44 //20ms //5ms :PrepareDistance=Distance;break; :SecondDistance=Distance-PrepareDistance-FirstDistance;break; :ThirdDistance=Distance-PrepareDistance-FirstDistance-SecondDistance;break; case 3 :FirstDistance=Distance-PrepareDistance;break; //T0中断 T0中断 ----------------------------------------*\

default :break;

if(PassLine==5) { FirstHigh=(int)(65536-20*FirstDistance/(15*Count*Rate-FirstDistance)*1000); SecondHigh=(int)(65536-20*SecondDistance/(15*Rate-SecondDistance)*1000); ThirdHigh=(int)(65536-20*FirstDistance/(15*Count*Rate-FirstDistance)*1000); TR0=0x01;TH0=0xf4;TL0=0x48; } }break; case 2 :{ AutoMode=0;SelectedMode=Line;Area0=Area1=0;PassTime=0;Distance=0; TR0=0x01;TH0=0xf4;TL0=0x48; Thx[0]=Thx[1]=((FirstHigh & 0xf0)>>8);Tlx[0]=Tlx[1]=(FirstHigh & 0x0f); Thx[2]=Thx[2]=((SecondHigh & 0xf0)>>8);Tlx[2]=Tlx[2]=(SecondHigh & 0x0f); Thx[3]=Thx[3]=((ThirdHigh & 0xf0)>>8);Tlx[3]=Tlx[3]=(ThirdHigh & 0x0f); Thx[4]=Thx[4]=0xff;Tlx[4]=Tlx[4]=0xff; }break; default :break; } } else { if (SelectedMode==Line) { IsT0INT*=-1; if (Area0<5) { if(IsT0INT==1) Clock0_Init(); else { TR0=0x01; TH0=Thx1; TL0=Tlx1; } } else IsT0INT=-1; } else { IsT0INT2*=-1; if(IsT0INT2==1) 45 //启动T0 //定时初值

{TR0=0x01;TH0=0xd8;TL0=0xf0;} else {TR0=0x01;TH0=0xb1;TL0=0xe0;} Back++; if(Back>=90) Back0=70; if((Nocurve<2)&&(Back0>0)&&Back!=0) { if(Back0<=65) Roundid=1; Back0--; } if((Nocurve>2)&&Back>=450) {Stop=1;IsT0INT2=-1;} if(Stop==1) flag=6; } } TF0=0; } /*----------------------------------T1中断用来定时 T1中断

//10ms //20ms

----------------------------------------*\

\*-----------------------------------------------------------------------------------------*/ void Time1INT(void) interrupt 3 { Clock1_Init(); Time1INTCount++; if (Time1INTCount == 10) { IsT1INT=1; if (Area0>5) P03=0; Time1INTCount=0; } TF1=0; } //500ms扫描一次 //T1中断

46





在本次设计中感谢俞龙老师、邓小玲老师以及实验室的老师在设计中对我们的指导 和帮助!

47


吴黎明 谭浩强 第一版 第二版

考 文 献

《单片机原理及应用技术》 《C 程序设计》

《LAB2000 系列单片机实验系统实验指导书》 《单片机 C 语言入门教程》

48

附 录:
元件清单:

元件 AT89S52 单片机 霍尔元件 A44E 铁片感应器 TL-Q5MC 1602LCD 小车 小磁铁片 发光二极管 带锁按钮 不带锁按钮 12MHz 晶振 排阻 510 74ls00 16 位排线 排针 电阻 电容 导线

数量 1片 1个 1个 1片 1部 4片 2个 2个 3个 1个 1个 2个 1条 若干 若干 若干 若干

49




友情链接: