89c52的单片机自动往返电动小汽车设计报告 - 图文

更新时间:2024-01-09 20:11:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1. 设计任务:

设计并制作了一个自动往返小汽车,其行驶路线满足所需的要求。 1.1 要求: 1.1.1 基本要求:

(1)分区控制:

如(图1)所示:

(图1)

车辆从起跑线出发(出发前,车体不得超出起跑线)。在第一个路程C~D区(3~6米)以低速行驶,通过时间不低于10s;第二个路程D~E区(2米)以高速行驶,通过时间不得多于4秒;第三个路程E~F区(3~6米)以低速行驶,通过时间不低于8s。

1.1.2.发挥部分

(1)自动记录、显示一次往返时间(记录显示装置要求安装在车上)。 (2)自动记录、显示行驶距离(记录显示装置要求安装在车上)。 (3)其它特色与创新。

1

2. 方案设计:

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

555定时器 控速模块 路面检测 测速模块 AT89S51 LCD显示模块 (图2)

2.1 路面检测模块:

路面黑线检测模块采用反射式红外发射--接收器,在车底的前部和中部安装了两个反射式红外传感器.

2.2 LCD显示模块:

采用1602LCD,由单片机的总线模式连接。为节约电源电量并且不影响LCD的功能,LCD的背光用单片机进行控制,使LCD的背光在小车行驶的过程中不亮,因为我们不必看其显示;在其它我们需要看显示的内容的时候LCD背光亮。 2.3 测速模块:

采用采用霍尔开关元器件A44E检测轮子上的小磁铁从而给单片机中断脉冲,达到测量速度的作用。霍尔元件具有体积小,频率响应宽度大,动态特性好,对外围电路要求

2

简单,使用寿命长,价格低廉等特点,电源要求不高,安装也较为方便。霍尔开关只对一定强度的磁场起作用,抗干扰能力强,因此可以在车轮上安装小磁铁,而将霍尔器件安装在固定轴上,通过对脉冲的计数进行车速测量。

其原理图接线如(图3)所示:

(图3)

2.4 控速模块:

采用由双极性管组成的H桥电路。用单片机控制晶体管使之工作在占空比可调的开关状态,精确调整电机转速。这种电路由于工作在管子的饱和截止模式下,效率非常高;H桥电路保证了可以简单地实现转速和方向的控制;电子开关的速度很快,稳定性也很高,是一种广泛采用的调速技术。

其电路原理图如(图4)所示:

3

开始 (图4)

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

第3条黑线 设定速度 停10s,交替显示路程,时间 限速模块 刹车 刹车 限速模块 第6条黑线 第5条黑线 全速行驶 第4条黑线 刹车

停止,交替显示往返时间,路 程 第11条黑线 全速行驶 第8条黑线 刹车 第9条黑线 限速模块 限速模块 刹车 第10条黑线 全速倒车

4

(图5)

4.系统的具体设计与实现:

4.1 路面检测模块:

路面黑线检测模块采用反射式红外发射--接收器,在车底的前部和中部安装了两个反射式红外传感器.原理图如图6.

图6

4.2 LCD显示模块:

采用1602LCD,由单片机的总线模式连接。为节约电源,LCD的背光用单片机进行控制。

4.3 测速模块:

通过霍尔元件感应磁铁来产生脉冲(当霍尔元件在离磁场较近时输出会是高电平,其它时候是低电平),一个车轮均匀放四个小磁铁,计算一秒所得的脉冲数,从而计算出一秒小车轮子转动圈数,再测量出小车车轮周长即可计算出小车当前速度,累加可得到当前路程。

5

4.4 控速模块:

考虑到元器件的缺少以及我们所用的电路的驱动电机的电路原理图和和小车自带的电路的电机驱动原理图一样,所以暂时使用小车自带的电机驱动电路图。 4.5 复位电路模块:

单片机的复位电路通过手动来实现,复位电路图如(图7)所示。

(图7)

4.6 脉冲产生模块:

脉冲产生电路采用555定时器.原理图如图.

6

VCC5VR15kohm4RSTVCC3DISTHRTRI5CONGND1OUT8U1R41kohmR210kOhm 50%Key = a76D1DIODE_VIRTUAL2R35kohm555_VIRTUALD2C20.01uFDIODE_VIRTUALC11uF

(图8)

5.最小系统图:

该系统主要用到的是单片机,所以主要的部分是最小系统图,该最小系统图如图9.

7

(图9)

6.系统程序:

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

#include

#include

/********************************************************************************\\ **

宏定义区

**

\\********************************************************************************/

/*------------------------------- LCD模块 ------------------------------------*/ #define LCD_RW P2_6 //读写控制端 #define LCD_RS P2_7 //数据命令选择端 #define LCD_E P2_5 //执行使能端 #define LCD_Data

P1

//P1口

8

#define Write #define Read #define Data #define Cmd

#define Enable #define Disable #define True #define False

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

//低电平写入 //高电平读出 //高电平选择数据 //低电平选择命令

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

#define LCD_Init #define LCD_CloseCtr

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

#define LCD_DispCtr #define LCD_CLS #define LCD_EnterSet #define Busy

//开显示及光标设置

/*-------------------------- 测速/测距/测时模块 -------------------------------*/ #define CircleLength

/*-------------------------------- 控速模块 -----------------------------------*/ #define P03 #define P04 #define P01 #define P02 #define P31 #define P33

/*------------------------------ 菜单选择模块 ---------------------------------*/ #define Normal #define Low #define High

/*********************************************************************************\\ **

/*------------------------------- LCD模块 -------------------------------------*/ void LCDInit(void);

9

//LCD初始化 //设置写命令模式 //设置读命令模式 //设置写数据模式 //写命令 //写数据 //执行命令 //定位显示地址

void SetWriteCmd(void); void SetReadCmd(void); void SetWriteData(void); void WriteCmd(char cmd); void ExecuteCmd(void);

全局函数声明区

**

\\*********************************************************************************/

0x00 0x01 0x02

//0 代表正常速度 //1 代表低速 //2 代表高速

P0_3 P0_4 P0_1 P0_2 P3_3

//后电机 //后电机 //前电机 //前电机 //控制液晶背光

0.132

//小车转一轮的长度为.132m

P0_5

void WriteData(char ddata); void SetXY(char x,char y);

void DisplaySingleChar(char x,char y,char cchar); void DisplayString(char x,char y,char *str); 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 CtrSpeed(void);

void Clock1_Init(void);

/********************************************************************************\\ **

float SpeedCount = 0; float Speed = 0.0;

//T1中断时间计时 //小车行走的时间

//判断T1是否已经响应中断 //测速计数脉冲

全局变量区

**

\\********************************************************************************/

float Distance = 0.0; char Time1INTCount=0; float PassTime=0.00; short IsT0INT=1; bit IsT1INT; short IsT0INT2=1;

char Thx[5]={0xf4,0xf4,0xc5,0xf4,0xff}; char Tlx[5]={0x48,0x48,0x68,0x48,0xff}; char Thx0=0xd8; char Tlx0=0xf0; char Thx1=0xb1; char Tlx1=0xe0;

//3ms,3ms,15ms,3ms

//20ms

10

short Round=0; short Back=0; short Back0=0; bit Backid; bit Stop=0;

char Area0=0; char Area1=0;

char LowSpeedArea1StartTime; char LowSpeedArea1EndTime; char HighSpeedAreaEndTime; char LowSpeedArea2EndTime; char LowSpeedArea1PassTime=0; char HighSpeedAreaPassTime=0; char LowSpeedArea2PassTime=0; char ReadyToGo=4;

char flag; bit Roundid=0; char Nocurve=0; char ChangeFlag; char Mode;

bit Running; bit SelectedAll; bit IsSelectingSpeed; bit Next;

bit SpeedSelected; char SelectedSpeed;

bit ChoosingDisplay; bit SelectedShow; bit SelectedReturn; bit Selected; bit ReturnSelection;

bit AVGSpeedShow; bit TotalDistanceShow;

bit ReturnMain;

bit AutoDisplay;

bit GoToChoosingDisplay;

bit AutoMode=0; char PassLineID=0;

//区域变量

//第一个低速区通过时间 //高速区通过时间 //第二个低速区通过时间

//倒计时

//速度是否选择完毕标志 //速度选择标志 //Next键标志

//已经被选中的速度方案标志 //速度选择是否完毕标志 //人工选择菜单开始标志 //显示选择标志 //返回选择标志 //确定/返回键选择标志 //返回键启用标志 //平均速度显示标志 //总路程显示标志 //返回主菜单标志 //自动显示标志

//人工选择标志

11

char PassLine=0; float PrepareDistance; float FirstDistance; float SecondDistance; float ThirdDistance; int FirstHigh; int SecondHigh; int ThirdHigh; float Rate=1.25; float Count=4;

/********************************************************************************\\ **

/*-------------------------------- void main() {

SelectedAll=False;

//开始速度选择

/*------------------------------ 速度选择 ---------------------------------*/ if (SelectedMode==Line && AutoMode==0) {

DisplayString(0x0,0,\);

12

Delay(40); LCDInit();

//延时等待LCD启动 //初始化LCD

P02=0; P03=0; P04=0; P31=1;

//单片机复位,背光开

P01=0;

主函数 ------------------------------------*/

全局函数实现区

**

\\********************************************************************************/

//5ms时的速度 //时间的倍数

DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(300); WriteCmd(LCD_CLS);

//开总中断

//开INT0中断 //INTO边沿触发 //INT1边沿触发

EA=1; EX0=1; IT0=1; EX1=1; IT1=1;

//开INT1中断

DisplayString(0x0,1,\); Delay(50);

WriteCmd(LCD_CLS);

IsSelectingSpeed=True; while(1) {

}

if (SpeedSelected==True) { }

if (Next==True) {

Next=False; WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\);

Delay(300); while(1)

13

//延时消除抖动

IsSelectingSpeed=False; break;

//按下了确定键,退出速度选择

WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(300);

while(1) {

if (Next==True) { }

break;

//如果按确定键则设置速度为Normal并跳出

//5ms //4ms

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;

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

//如果按Next键则直接跳出

//延时消除抖动

if (SpeedSelected==True)

//30ms //3ms

}

{ }

if (Next==True) { }

break;

//如果按下确定键,则设置速度为Low,并跳出 //这里没有速度设置,因为默认速度就是Low

SelectedSpeed=Low; break;

//如果再一次按下Next键,则跳出

if (SpeedSelected==True)

if (SpeedSelected==True) { }

if (Next==True) { }

if (SpeedSelected==True) {

Next=False; WriteCmd(LCD_CLS);

//按下了确定键,退出速度选择

IsSelectingSpeed=False; break;

DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(300); while(1) { }

if (Next==True) {

Thx[0]=0xe0;Tlx[0]=0xc0; //8ms break;

//如果按下确定键,则设置速度为High,并跳出

//如果再一次按下Next键,则跳出

//延时消除抖动

if (SpeedSelected==True)

Thx[1]=0xe0;Tlx[1]=0xc0; //8ms

Thx[2]=0x63;Tlx[2]=0xc0; //40ms Thx[3]=0xec;Tlx[3]=0x78; //5ms }

SelectedSpeed=High; break;

//按下了确定键,退出速度选择

IsSelectingSpeed=False;

14

}

}

}

break;

if (Next==True) { }

Next=False; continue;

//再一次按下了Next键,则循环速度选择

SelectedAll=True; //标志模式选择和速度选择完毕

Running=True; Delay(50);

WriteCmd(LCD_CLS);

/*------------------------- 显示所选择的模式和速度方案 -------------------------*/ if (SelectedMode==Line) { }

if (SelectedMode==Curve) { }

if (AutoMode==1) { }

DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(50);

WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(50);

WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(50);

WriteCmd(LCD_CLS);

if (SelectedMode==Line) {

15

if (SelectedSpeed==Normal) { DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(50); WriteCmd(LCD_CLS);

}

if (SelectedSpeed==Low) { DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(50); WriteCmd(LCD_CLS);

}

if (SelectedSpeed==High) { DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(50); WriteCmd(LCD_CLS);

}

}

INTInit(); DisplayString(0x0,0,\); while (ReadyToGo--) DisplaySingleChar(0x7,1,ReadyToGo+0x30); DisplaySingleChar(0x09,1,'s'); Delay(300);

}

WriteCmd(LCD_CLS);

DisplayString(0x05,0,\); Delay(100); WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\);

if (SelectedMode==Line&&AutoMode==0)

flag=Area0; else flag=1;

16

//初始化所有中断

{

while(flag<5) {

if(AutoMode==1) }

{

switch(PassLineID) case 0 :{

if(IsT0INT==1)

{P01=P02=P04=0;P03=1;} {P01=P02=P03=P04=0;}

}break;

{

else

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((Nocurve<2)&&Round!=0&&(Back0>0)&&Back!=0)

if(Backid==1)

{P01=1;P02=0;P03=0;P04=1;}

else

{P01=0;P02=1;P03=0;P04=1;}

Back=1; else

}

{

if(Round==0)

17

}

{

if(IsT0INT2==1)

{P01=0;P02=0;P03=1;P04=0;} {P01=0;P02=0;P03=0;P04=0;} else

}

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

{P01=1;P02=0;P03=0;P04=0;}

} else {

if(IsT0INT2==1) else

else

{P01=0;P02=1;P03=1;P04=0;Backid=0;}

{P01=0;P02=1;P03=0;P04=0;}

}

}

}

} } }

if (IsT1INT==1) { }

IsT1INT=0; ComputeTime();

ComputeSpeedANDDistance();

18

//补中断路程,加上最后一次中断缺失的路程 ComputeSpeedANDDistance(); P04=1;P03=0;P01=P02=0;Delay(90); P03=0;P04=0; P31=1;

ET0=0x0; ET1=0x0; EX1=0x01;

AutoDisplay=True; WriteCmd(LCD_CLS);

if (SelectedMode==Line)

while(1) {

if (GoToChoosingDisplay==True)

break; Delay(200); WriteCmd(LCD_CLS); Delay(200);

DisplayString(0,0,\); DisplayString(0,1,\); DisplaySingleChar(0x0C,1,'s');

LowSpeedArea1PassTime=LowSpeedArea1EndTime-LowSpeedArea1StartTime; DisplaySingleChar(0x0A,1,LowSpeedArea1PassTime+0x30); if (LowSpeedArea1PassTime > 9)

break;

//通过第一个低速区的时间超过s

DisplaySingleChar(0x0B,1,LowSpeedArea1PassTime/10+0x30);

//自动显示各个区域经过的时间

Running=False;

//行程结束,小车停止 //关T0中断 //关T1中断 //开INT1中断 //行程结束,背光开

if (GoToChoosingDisplay==True) Delay(200); WriteCmd(LCD_CLS); Delay(200);

DisplayString(0,0,\); DisplayString(0,1,\); DisplaySingleChar(0x0C,1,'s');

HighSpeedAreaPassTime=HighSpeedAreaEndTime-LowSpeedArea1EndTime; DisplaySingleChar(0x0A,1,HighSpeedAreaPassTime+0x30); if ( HighSpeedAreaPassTime> 9)

//通过高速区的时间超过s

DisplaySingleChar(0x0B,1,HighSpeedAreaPassTime/10+0x30);

19

}

}

if (GoToChoosingDisplay==True)

break; Delay(200); WriteCmd(LCD_CLS); Delay(200);

DisplayString(0,0,\); DisplayString(0,1,\); DisplaySingleChar(0x0C,1,'s');

LowSpeedArea2PassTime=LowSpeedArea2EndTime-HighSpeedAreaEndTime; DisplaySingleChar(0x0A,1,LowSpeedArea2PassTime+0x30); if ( LowSpeedArea2PassTime> 9)

//通过第二个低速区的时间超过s

DisplaySingleChar(0x0B,1,LowSpeedArea2PassTime/10+0x30);

AutoDisplay=False;

/*---------------- 菜单选择你想要看的内容--总时间、总路程以及平均速度 --------------*/ ChoosingDisplay=True; WriteCmd(LCD_CLS);

/*首先显示主菜单,然后显示第一个选项*/ DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(100); while(1) {

WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); Delay(250);

//延时消除抖动

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

/*不断检测确定键和Next键*/ while(1) {

if (Next==True)

break; break;

20

if (SelectedShow==True)

}

/*按下了确定键,显示第一个选项的内容*/ if (SelectedShow==True) { }

/**按下了Next键,则显示第二个选项*/ if (Next==True) { }

Next=False; WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); ReturnMain=False; ReturnSelection=False; AVGSpeedShow=True; Delay(250);

//按下了Next键,那么这个时候关闭返回键的功能

//表明AVGSpeed选项已经显示过了 //延时消除抖动

//按下Next键,显示AVGSpeed菜单项

SelectedShow=False; SelectedReturn=False; Selected=False; WriteCmd(LCD_CLS);

DisplayString(0,0,\); DisplayTime();

DisplayString(0x0A,1,\); ReturnSelection=True; AVGSpeedShow=False; Delay(250);

//延时消除抖动

//按下了确定键,那么这个时候开启返回键的功能

/*------------------------------------第二次按键--------------------------------------*/

/*显示第一个选项的内容后又不断检测返回键(确定键)和Next键*/ while(1) { } {

Next=False;

21

if (Next==True)

if (Next==True)

break; break;

if (Selected==True)

}

ReturnMain=False; ReturnSelection=False; if (AVGSpeedShow==False) { } { }

//按下了确定键或返回键

WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); TotalDistanceShow=False;

Delay(250);

//已经显示过AVGSpeed选项了,则显示下一个选项 //即第一次选择了Next键

//延时消除抖动

//显示了AVGSpeed,则表明TotalDistance还没有显示

//按下了Next键,那么这个时候关闭返回键的功能 //还没有显示AVGSpeed选项,显示它

//即第一次选择了确定键

if (AVGSpeedShow==True)

WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); TotalDistanceShow=True; Delay(250);

//表明显示了TotalDistance选项

//延时消除抖动

if (Selected==True) { }

SelectedShow=False; SelectedReturn=False; Selected=False;

if (ReturnSelection==True) //第一次选择了确定键,故这次按下的是返回键 { }

TotalDistanceShow=False;

WriteCmd(LCD_CLS);

DisplayString(0,0,\); DisplayAVGSpeed();

DisplayString(0x0A,1,\); ReturnSelection=True;

Delay(250);

//延时消除抖动

//按下了确定键,那么这个时候开启返回键的功能

ReturnMain=True;

if (ReturnSelection==False)

if (ReturnMain==True) {

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

22

}

ReturnMain=False; continue;

/*------------------------------------第三次按键--------------------------------------*/

/*如果没有返回主菜单,则继续检测Next键和确定键*/ while(1) { }

/*按下Next键,显示下一个选项*/ if (Next==True) { }

if (Selected==True) {

SelectedShow=False; SelectedReturn=False; Selected=False;

if (ReturnSelection==True) {

if (TotalDistanceShow==False)

23

//表明AVGSpeed选项的内容还没有显示

ReturnMain=True;

if (ReturnSelection==False)

//按下的是返回键

//按下了确定键或返回键

Next=False; ReturnMain=False; ReturnSelection=False; { }

ReturnMain=True;

//还没有显示TotalDistance选项,显示它

//按下了Next键,那么这个时候关闭返回键的功能

if (TotalDistanceShow==True) if (TotalDistanceShow==False)

WriteCmd(LCD_CLS);

DisplayString(0x0,0,\); DisplayString(0x0,1,\); TotalDistanceShow=True;

Delay(250);

//延时消除抖动

if (Next==True)

break; break;

if (SelectedShow==True)

}

}

{ }

if (TotalDistanceShow==True) { }

WriteCmd(LCD_CLS);

DisplayString(0,0,\); DisplayDistance();

DisplayString(0x0A,1,\); ReturnSelection=True; Delay(250);

//按下了确定键,那么这个时候开启返回键的功能

//延时消除抖动

WriteCmd(LCD_CLS);

DisplayString(0,0,\); DisplayAVGSpeed();

DisplayString(0x0A,1,\); ReturnSelection=True; Delay(250);

//延时消除抖动

if (ReturnMain==True) { }

ReturnMain=False; continue;

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

/*------------------------------------第四次按键--------------------------------------*/

while(1) { }

if (Next==True) {

Next=False; ReturnMain=False; ReturnSelection=False; {

if (TotalDistanceShow==False)

WriteCmd(LCD_CLS);

24

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

if (Next==True)

break; break;

if (SelectedShow==True)

}

}

DisplayString(0x0,0,\); DisplayString(0x0,1,\); TotalDistanceShow=True;

Delay(250);

//延时消除抖动

if (SelectedShow==True) { }

if (ReturnMain==True) { }

ReturnMain=False; continue;

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

SelectedShow=False; SelectedReturn=False; Selected=False;

if (ReturnSelection==True) { }

if (TotalDistanceShow==True) { }

WriteCmd(LCD_CLS);

DisplayString(0,0,\); DisplayDistance();

DisplayString(0x0A,1,\);

ReturnSelection=True; //按下了确定键,那么这个时候开启返回键的功能 Delay(250);

//延时消除抖动

ReturnMain=True;

if (ReturnSelection==False)

//按下的是返回键

/*------------------------------------第五次按键--------------------------------------*/

while(1) {

if (Next==True)

break;

if (SelectedShow==True)

25

}

break;

if (Next==True) { }

Next=False;

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

ReturnMain=False; ReturnSelection=False; if (TotalDistanceShow==True) { }

ReturnMain=True;

//最后一个选项已经显示完毕,返回主菜单

if (SelectedShow==True) { }

while(1) { }

if (Next==True)

26

if (Next==True)

break; break;

if (SelectedShow==True) SelectedShow=False; SelectedReturn=False; Selected=False;

if (ReturnSelection==True) { }

if (TotalDistanceShow==True) { }

WriteCmd(LCD_CLS);

DisplayString(0,0,\); DisplayDistance();

DisplayString(0x0A,1,\); ReturnSelection=True; Delay(250);

//按下了确定键,那么这个时候开启返回键的功能

//延时消除抖动

ReturnMain=True;

if (ReturnSelection==False)

//按下的是返回键

/*------------------------------------第六次按键--------------------------------------*/

}

}

{ }

if (SelectedShow==True) { }

continue;

SelectedShow=False; SelectedReturn=False; Selected=False; Next=False; ReturnMain=False; ReturnSelection=False;

while(1);

/****************************************************************************************\\ **

/*--------------------------------- LCD初始化函数--------------------------------------*/

void LCDInit(void) {

//三次显示模式设置 }

/*--------------------------------- LCD模式设置函数--------------------------------------*\\

27

WriteCmd(LCD_Init); WriteCmd(LCD_CLS);

//初始化 //关显示 //清屏幕 //光标移动设置 //显示开以及光标设置

WriteCmd(LCD_CloseCtr); WriteCmd(LCD_EnterSet); WriteCmd(LCD_DispCtr);

LCD_Data=0; LCD_E=Disable; Delay(5);

WriteCmd(LCD_Init); Delay(5);

WriteCmd(LCD_Init); Delay(5);

WriteCmd(LCD_Init);

LCD驱动模块

**

\\****************************************************************************************/

SetWriteCmd() SetReadCmd() SetWriteData()

设置LCD为写命令模式 设置LCD为读命令模式 设置LCD为写数据模式

\\*----------------------------------------------------------------------------------------*/ void SetWriteCmd(void) { }

void SetReadCmd(void) { }

void SetWriteData(void) { }

/*--------------------------------- LCD功能执行函数--------------------------------------*\\

WriteCmd()

写命令 写数据 执行命令 显示定位 显示单个字符 显示一串字符 忙标志检测

WriteData() ExecuteCmd() SetXY()

LCD_RW=Write; LCD_RS=Data; LCD_RW=Read; LCD_RS=Cmd; LCD_RW=Write; LCD_RS=Cmd;

DisplaySingleChar() DisplayString() IsBusy()

\\*----------------------------------------------------------------------------------------*/ void WriteCmd(char cmd) { }

void WriteData(char ddata) {

while(IsBusy()); LCD_Data=ddata;

28

while(IsBusy()); LCD_Data=cmd; SetWriteCmd(); ExecuteCmd();

}

SetWriteData(); ExecuteCmd();

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) { }

bit IsBusy(void) { }

/*------------------------------------- 延时函数 -------------------------------------*/

29

LCD_Data=0xFF; SetReadCmd(); ExecuteCmd();

return (bit)(P1 & 0x80);

while(*str) { }

Delay(5);

DisplaySingleChar(x++,y,*str); str++; SetXY(x,y); WriteData(cchar); if (y)

x|=0x40; x|=0x80; Delay(5); WriteCmd(x); LCD_E=Enable; LCD_E=Disable;

void Delay(unsigned int time) {

unsigned int timeCounter = 0; }

void DelayUs(unsigned int time) { }

/*******************************************************************************************\\ ** LCD显示模块 ** \\*******************************************************************************************/

void ComputeTime(void) { }

void ComputeSpeedANDDistance(void) { }

/*------------------------------------- 显示时间 ----------------------------------------*/ void DisplayTime(void) {

char PassTime1=0x30; char PassTime2=0x30; char PassTime3=0x30; char PassTime4=0x30;

if ((int)PassTime*100<100) { }

30

PassTime1+=0;

PassTime2+=(int)(PassTime*100)/10; PassTime3+=(int)(PassTime*100);

//时间未够1s

Speed=SpeedCount/4*CircleLength; Distance+=Speed; SpeedCount=0;

//计算瞬时速度 //计算距离

if (Area0 < 5)

PassTime+=0.5;

unsigned int timeCounter = 0;

for (timeCounter = 0;timeCounter < time;timeCounter ++)

_nop_();

for (timeCounter = time;timeCounter > 0 ;timeCounter --)

DelayUs(255);

}

else if ((int)(PassTime*100) > 100 && (int)(PassTime*100) < 1000) //够1s而未够10s { } else { }

if ((int)(PassTime*100) < 1000) { } else { }

DisplaySingleChar(0x04,1,PassTime1); DisplaySingleChar(0x05,1,PassTime2); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,PassTime3); DisplaySingleChar(0x08,1,PassTime4);

DisplaySingleChar(0x05,1,PassTime1); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,PassTime2); DisplaySingleChar(0x08,1,PassTime3); PassTime1+=(int)(PassTime*100)/1000; PassTime2+=(int)(PassTime*100)/100; PassTime3+=(int)(PassTime*100)/10; PassTime4+=(int)(PassTime*100); PassTime1+=(int)(PassTime*100)/100; PassTime2+=(int)(PassTime*100)/10; PassTime3+=(int)(PassTime*100);

/*------------------------------------ 显示平均速度----------------------------------------*/

void DisplayAVGSpeed(void) {

if ((int)(Distance/PassTime*100)< 100) {

Speed1+=0;

Speed2+=(int)(Distance/PassTime*100)/10; Speed3+=(int)(Distance/PassTime*100);

31

int Speed1=0x30; int Speed2=0x30; int Speed3=0x30;

//初始化为0的ASCII码

}

} else { }

DisplaySingleChar(0x05,1,Speed1); DisplaySingleChar(0x06,1,'.'); DisplaySingleChar(0x07,1,Speed2); DisplaySingleChar(0x08,1,Speed3);

Speed1+=(int)(Distance/PassTime*100)/100; Speed2+=(int)(Distance/PassTime*100)/10; Speed3+=(int)(Distance/PassTime*100);

/*------------------------------------- 显示路程 ----------------------------------------*/

void DisplayDistance(void) {

if ((int)(Distance*100) < 1000) {

32

if ((int)(Distance*100) < 100) { }

else if ((int)(Distance*100) > 100 && (int)(Distance*100) < 1000) { } else { }

Distance1+=(int)(Distance*100)/1000; Distance2+=(int)(Distance*100)/100; Distance3+=(int)(Distance*100)/10; Distance4+=(int)(Distance*100); Distance1+=(int)(Distance*100)/100; Distance2+=(int)(Distance*100)/10; Distance3+=(int)(Distance*100); Distance1+=0;

Distance2+=(int)(Distance*100)/10; Distance3+=(int)(Distance*100); int Distance1=0x30; int Distance2=0x30; int Distance3=0x30; int Distance4=0x30;

}

}

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) { }

void Clock0_Init(void) { }

void Clock1_Init(void) { }

/*******************************************************************************************\\

33

TR1=0x01; TH1=0x3C; TL1=0x0B0;

//启动T1

//定时初值-50ms中断一次

TR0=0x01; TH0=Thx0; TL0=Tlx0;

//启动T0 //定时初值

//开总中断 //INTO边沿触发 //INTO优先级为高级 //开INT1中断 //INT1边沿触发 //INT1优先级为高级 //初始化时钟中断 //T0/T1定时方式1 //开T0中断 //开T1中断

EA=1; IT0=1; EX1=1; IT1=1;

PX0=1;

PX1=1; TMOD=0x11;

Clock0_Init(); ET0=0x01; ET1=0x01;

**

中断处理程序 **

\\*******************************************************************************************/ /*----------------------------------- 外部中断0 ----------------------------------------*\\

\\*-----------------------------------------------------------------------------------------*/ void SpeedINT(void) interrupt 0 { }

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

\\*-----------------------------------------------------------------------------------------*/ void CtrSpeedINT(void) interrupt 2 {

if (Running==True) {

if (Area0==0) {

EX0=1;

34

//经过第一条铁线(即起跑线),开始计时,开始测速

//如果速度选择已经完毕,则此中断作为控速中断

if (SelectedAll==False) { }

if (IsSelectingSpeed==True)

SpeedSelected=True;

//速度选择标志

//如果速度还没有选择完毕,则此中断作为确定键

//中断INT1

外部中断1有两个功能

(1)作为菜单选择的确定键/返回键 (2)控速

if (SelectedAll==False)

Next=True;

if (Running==True)

SpeedCount++;

//如果是在选择要显示的内容

Next=True;

//如果模式和速度还没有选择完毕,则此中断作为Next键

//如果模式和速度已经选择完毕,则此中断作为测速中断

//中断INT0

外部中断0有两个功能 (1)作为菜单选择的Next键 (2)作为测速的计数器

if (ChoosingDisplay==True)

}

}

Clock1_Init(); P31=0;

//过起跑线,背光灭

if (Area0==1)

if(AutoMode==1) {

PassLine++; switch(PassLine) {

}

case 5 :PassLineID=1;break;

default :PassLineID=PassLineID;break;

case 10 :PassLineID=2;break;

LowSpeedArea1StartTime=PassTime; //读取进入第一个低速区的时刻

LowSpeedArea1EndTime=PassTime;//读取离开第一个低速区的时刻,也就是进入高速区的时刻 HighSpeedAreaEndTime=PassTime;//读取离开高速区的时刻,也就是进入第二个低速区的时刻 LowSpeedArea2EndTime=PassTime; //读取离开第二个低速去的时刻 if (Area0==2) if (Area0==3) if (Area0==4)

} else { } IE1=0;

if (SelectedMode==Line) { } else {

Nocurve++; Round++;

if(Roundid==1&&Round==2) }

{Round++;Roundid=0;} Back=0; Back0=0; EX1=0;

Thx0=Thx[Area0++]; Tlx0=Tlx[Area1++]; if (Area0==5)

EX1=0;

if (AutoDisplay==True)

35

}

{ }

if (ChoosingDisplay==True) { }

SelectedShow=True; SelectedReturn=True; Selected=True;

GoToChoosingDisplay=True;

/*-------------------------------------- T0中断 ----------------------------------------*\\

\\*-----------------------------------------------------------------------------------------*/ void Time0INT(void) interrupt 1 {

if(AutoMode==1)

IsT0INT*=-1;

{

switch(PassLine)

{ case 2 :PrepareDistance=Distance;break;

case 3 :FirstDistance=Distance-PrepareDistance;break;

case 4 :SecondDistance=Distance-PrepareDistance-FirstDistance;break;

case 5 :ThirdDistance=Distance-PrepareDistance-FirstDistance-SecondDistance;break; default :break;

//T0中断

T0中断用来输出方波以控制速度

}

switch(PassLineID) {

case 0 :{

if(IsT0INT==1)

{TR0=0x01;TH0=0xec;TL0=0x78;} //5ms

{TR0=0x01;TH0=0xb1;TL0=0xe0;} //20ms

else

}break;

if(PassLine==5) {

TR0=0x01;TH0=0xf4;TL0=0x48;

36

case 1 :{

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

}

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

{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)

{

37

//启动T0 //定时初值 //10ms

//20ms

}

}

}

}

if(Back0<=65)

Roundid=1; Back0--; }

{Stop=1;IsT0INT2=-1;}

if((Nocurve>2)&&Back>=450) if(Stop==1) flag=6;

TF0=0;

/*----------------------------------- T1中断 ----------------------------------------*\\

T1中断用来定时

\\*-----------------------------------------------------------------------------------------*/ void Time1INT(void) interrupt 3 { }

Clock1_Init(); Time1INTCount++; { } TF1=0;

IsT1INT=1; if (Area0>5)

P03=0;

Time1INTCount=0;

//500ms扫描一次

if (Time1INTCount == 10)

//T1中断

参 考 文 献

吴黎明 第一版 《单片机原理及应用技术》 谭浩强 第二版 《C程序设计》 《LAB2000系列单片机实验系统实验指导书》 《单片机C语言入门教程》

38

附 录:

元件清单:

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

数量 1片 1个 1个 1片 1部 4片 2个 2个 3个 1个 1个 2个 1条 若干 若干 电容 导线

若干 若干 40

本文来源:https://www.bwwdw.com/article/c89o.html

Top