📄 智能小车c程序.txt
字号:
#include <intrins.h>
#include <AT89X52.h>
/********************************************************************************\
** 宏定义区 **
\********************************************************************************/
/*------------------------------- LCD模块 ------------------------------------*/
#define LCD_RW P2_6 //读写控制端
#define LCD_RS P2_7 //数据命令选择端
#define LCD_E P2_5 //执行使能端
#define LCD_Data P1 //P1口
#define Write 0x00 //低电平写入
#define Read 0x01 //高电平读出
#define Data 0x01 //高电平选择数据
#define Cmd 0x00 //低电平选择命令
#define Enable 0x00 //跃变到低电平时执行命令
#define Disable 0x01
#define True 0x01
#define False 0x00
#define LCD_Init 0x38 //初始化模式
#define LCD_DispCtr 0x0C //开显示及光标设置
#define LCD_CloseCtr 0x08 //关显示
#define LCD_CLS 0x01 //清屏幕
#define LCD_EnterSet 0x06 //显示光标
#define Busy P1_7 //忙信号
/*-------------------------- 测速/测距/测时模块 -------------------------------*/
#define CircleLength 0.132 //小车转一轮的长度为.132m
/*-------------------------------- 控速模块 -----------------------------------*/
#define P03 P0_3 //后电机
#define P04 P0_4 //后电机
#define P01 P0_1 //前电机
#define P02 P0_2 //前电机
#define P31 P0_5 //控制液晶背光
#define P33 P3_3
/*------------------------------ 菜单选择模块 ---------------------------------*/
#define Line 0x00 //0代表直线模式
#define Curve 0x01 //1代表S型模式
#define Normal 0x00 //0 代表正常速度
#define Low 0x01 //1 代表低速
#define High 0x02 //2 代表高速
/*********************************************************************************\
** 全局函数声明区 **
\*********************************************************************************/
/*------------------------------- LCD模块 -------------------------------------*/
void LCDInit(void); //LCD初始化
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); //显示一段字符串
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中断时间计时
float PassTime=0.00; //小车行走的时间
short IsT0INT=1;
bit IsT1INT; //判断T1是否已经响应中断
short IsT0INT2=1;
char Thx[5]={0xf4,0xf4,0xc5,0xf4,0xff}; //3ms,3ms,15ms,3ms
char Tlx[5]={0x48,0x48,0x68,0x48,0xff};
char Thx0=0xd8;
char Tlx0=0xf0;
char Thx1=0xb1; //20ms
char Tlx1=0xe0;
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 IsSelectingMode; //模式选择标志
bit IsSelectingSpeed; //速度选择标志
bit ModeSelected; //已经被选择的模式标志
char SelectedMode=10; //模式选择是否完毕标志
bit Next; //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;
char PassLine=0;
float PrepareDistance;
float FirstDistance;
float SecondDistance;
float ThirdDistance;
int FirstHigh;
int SecondHigh;
int ThirdHigh;
float Rate=1.25; //5ms时的速度
float Count=4; //时间的倍数
/*------------------------------------- 延时函数 -------------------------------------*/
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_();
}
/*------------------------------------- 中断初始化 -------------------------------------*/
void INTInit(void)
{
EA=1; //开总中断
IT0=1; //INTO边沿触发
PX0=1; //INTO优先级为高级
EX1=1; //开INT1中断
IT1=1; //INT1边沿触发
PX1=1; //INT1优先级为高级
Clock0_Init(); //初始化时钟中断
TMOD=0x11; //T0/T1定时方式1
ET0=0x01; //开T0中断
ET1=0x01; //开T1中断
}
void Clock0_Init(void)
{
TR0=0x01; //启动T0
TH0=Thx0; //定时初值
TL0=Tlx0;
}
void Clock1_Init(void)
{
TR1=0x01; //启动T1
TH1=0x3C; //定时初值-50ms中断一次
TL1=0x0B0;
}
/*******************************************************************************************\
** 中断处理程序 **
\*******************************************************************************************/
/*----------------------------------- 外部中断0 ----------------------------------------*\
外部中断0有两个功能
(1)作为菜单选择的Next键
(2)作为测速的计数器
\*-----------------------------------------------------------------------------------------*/
void SpeedINT(void) interrupt 0 //中断INT0
{
if (SelectedAll==False) //如果模式和速度还没有选择完毕,则此中断作为Next键
Next=True;
if (Running==True) //如果模式和速度已经选择完毕,则此中断作为测速中断
SpeedCount++;
if (ChoosingDisplay==True) //如果是在选择要显示的内容
Next=True;
}
/*----------------------------------- 外部中断1 ----------------------------------------*\
外部中断1有两个功能
(1)作为菜单选择的确定键/返回键
(2)控速
\*-----------------------------------------------------------------------------------------*/
void CtrSpeedINT(void) interrupt 2 //中断INT1
{
if (SelectedAll==False) //如果模式和速度还没有选择完毕,则此中断作为确定键
{
if (IsSelectingMode==True) //模式选择标志
ModeSelected=True;
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 //S型模式
{
Nocurve++;
Round++;
if(Roundid==1&&Round==2)
{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中断 ----------------------------------------*\
T0中断用来输出方波以控制速度
\*-----------------------------------------------------------------------------------------*/
void Time0INT(void) interrupt 1 //T0中断
{
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;
}
switch(PassLineID)
{
case 0 :{
if(IsT0INT==1)
{TR0=0x01;TH0=0xec;TL0=0x78;} //5ms
else
{TR0=0x01;TH0=0xb1;TL0=0xe0;} //20ms
}break;
case 1 :{
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; //启动T0
TH0=Thx1; //定时初值
TL0=Tlx1;
}
}
else
IsT0INT=-1;
}
else
{
IsT0INT2*=-1;
if(IsT0INT2==1)
{TR0=0x01;TH0=0xd8;TL0=0xf0;} //10ms
else
{TR0=0x01;TH0=0xb1;TL0=0xe0;} //20ms
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中断用来定时
\*-----------------------------------------------------------------------------------------*/
void Time1INT(void) interrupt 3 //T1中断
{
Clock1_Init();
Time1INTCount++;
if (Time1INTCount == 10) //500ms扫描一次
{
IsT1INT=1;
if (Area0>5)
P03=0;
Time1INTCount=0;
}
TF1=0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -