基于51单片机的循线测距测速及1602显示.docx
《基于51单片机的循线测距测速及1602显示.docx》由会员分享,可在线阅读,更多相关《基于51单片机的循线测距测速及1602显示.docx(15页珍藏版)》请在冰豆网上搜索。
基于51单片机的循线测距测速及1602显示
#include//器件配置文件
#include
#defineTXP1_2//Trig
#defineRXP1_3//Echo
#defineLCM_RSP2_5//概念LCD引脚
#defineLCM_RWP2_6
#defineLCM_EP2_7
#defineLCM_DataP0
#defineBusy0x80//用于检测LCM状态字中的Busy标识
#defineuintunsignedint
#defineucharunsignedchar
sbitP10=P2^1;//操纵左电机前进
sbitP11=P2^2;//操纵左电机后退
sbitP12=P2^3;//操纵右电机前进
sbitP13=P2^4;//操纵右电机后退
sbitP14=P1^4;//寻迹左
sbitP15=P1^5;//寻迹中
sbitP16=P1^6;//寻迹右
sbitP17=P1^7;//避障
voidLCMInit(void);
voidDisplayOneChar(unsignedcharX,unsignedcharY,unsignedcharDData);
voidDisplayListChar(unsignedcharX,unsignedcharY,unsignedcharcode*DData);
voidDelay5Ms(void);
voidDelay400Ms(void);
voidDecode(unsignedcharScanCode);
voidWriteDataLCM(unsignedcharWDLCM);
voidWriteCommandLCM(unsignedcharWCLCM,BuysC);
voidfun2(void);
voidfun3(void);
voidfun4(void);
voidfun5(void);
unsignedcharReadDataLCM(void);
unsignedcharReadStatusLCM(void);
unsignedcharcodemcustudio[]={"…………."};
unsignedcharcodeemail[]={"…………"};
unsignedcharcodeCls[]={"……………"};
unsignedcharcodeASCII[15]={'0','1','2','3','4','5','6','7','8','9','.','-','M'};
staticunsignedcharDisNum=0;//显示用指针
unsignedinttime=0;
unsignedlongS=0;
bitflag=0;
unsignedchardisbuff[4]={0,0,0,0,};
bitFlg_5ms=0;
unsignedcharCounter_100ms=0;
unsignedcharbuf[5]={0,0,0,0,0};
unsignedintSpeed;
unsignedintspeed_frequency;//frequency
unsignedintspeed_catch1;//catch1
unsignedintspeed_catch2;//catch2
unsignedcharspeed_t2_ovf_count_temp;//T1overflowcountertempregister
unsignedcharspeed_t2_ovf_count;//T1overflowcounterregister
unsignedcharspeed_catch_p;//catchpointer
//写数据
voidWriteDataLCM(unsignedcharWDLCM)
{
ReadStatusLCM();//检测忙
LCM_Data=WDLCM;
LCM_RS=1;
LCM_RW=0;
LCM_E=0;//假设晶振速度太高能够在这后加小的延时
LCM_E=0;//延时
LCM_E=1;
}
//写指令
voidWriteCommandLCM(unsignedcharWCLCM,BuysC)//BuysC为0时忽略忙检测
{
if(BuysC)ReadStatusLCM();//依照需要检测忙
LCM_Data=WCLCM;
LCM_RS=0;
LCM_RW=0;
LCM_E=0;
LCM_E=0;
LCM_E=1;
}
//读数据
unsignedcharReadDataLCM(void)
{
LCM_RS=1;
LCM_RW=1;
LCM_E=0;
LCM_E=0;
LCM_E=1;
return(LCM_Data);
}
//读状态
unsignedcharReadStatusLCM(void)
{
LCM_Data=0xFF;
LCM_RS=0;
LCM_RW=1;
LCM_E=0;
LCM_E=0;
LCM_E=1;
while(LCM_Data&Busy);//检测忙信号
return(LCM_Data);
}
voidLCMInit(void)//LCM初始化
{
LCM_Data=0;
WriteCommandLCM(0x38,0);//三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1);//显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1);//关闭显示
WriteCommandLCM(0x01,1);//显示清屏
WriteCommandLCM(0x06,1);//显示光标移动设置
WriteCommandLCM(0x0F,1);//显示开及光标设置
}
//按指定位置显示一个字符
voidDisplayOneChar(unsignedcharX,unsignedcharY,unsignedcharDData)
{
Y&=0x1;
X&=0xF;//限制X不能大于15,Y不能大于1
if(Y)X|=0x40;//当要显示第二行时地址码+0x40;
X|=0x80;//算出指令码
WriteCommandLCM(X,1);//发命令字
WriteDataLCM(DData);//发数据
}
//按指定位置显示一串字符
voidDisplayListChar(unsignedcharX,unsignedcharY,unsignedcharcode*DData)
{
unsignedcharListLength;
ListLength=0;
Y&=0x1;
X&=0xF;//限制X不能大于15,Y不能大于1
while(DData[ListLength]>0x19)//假设抵达字串尾那么退出
{
if(X<=0xF)//X坐标应小于0xF
{
DisplayOneChar(X,Y,DData[ListLength]);//显示单个字符
ListLength++;
X++;
}
}
}
//5ms延时
voidDelay5Ms(void)
{
unsignedintTempCyc=5552;
while(TempCyc--);
}
//400ms延时
voidDelay400Ms(void)
{
unsignedcharTempCycA=5;
unsignedintTempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}
/********************************************************/
voidConut(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.7)/100;//算出来是CM
if((S>=700)||flag==1)//超出测量范围显示"-"
{
flag=0;
DisplayOneChar(0,1,ASCII[11]);
DisplayOneChar(1,1,ASCII[10]);//显示点
DisplayOneChar(2,1,ASCII[11]);
DisplayOneChar(3,1,ASCII[11]);
DisplayOneChar(4,1,ASCII[12]);//显示M
}
else
{
disbuff[0]=S%1000/100;
disbuff[1]=S%1000%100/10;
disbuff[2]=S%1000%10%10;
DisplayOneChar(0,1,ASCII[disbuff[0]]);
DisplayOneChar(1,1,ASCII[10]);//显示点
DisplayOneChar(2,1,ASCII[disbuff[1]]);
DisplayOneChar(3,1,ASCII[disbuff[2]]);
DisplayOneChar(4,1,ASCII[12]);//显示M
}
}
/********************************************************/
voidzd0()interrupt1//T0中断用来计数器溢出,超过测距范围
{
flag=1;//中断溢出标志
}
/********************************************************/
voidStartModule()//启动模块
{
TX=1;//启动一次模块
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TX=0;
}
//--------------------------------------------
voidfun2(void)
{P10=1;P11=0;P12=1;P13=0;}//前进
voidfun3(void)
{P10=0;P11=0;P12=1;P13=0;}//左转
voidfun4(void)
{P10=1;P11=0;P12=0;P13=0;}//右转
voidfun5(void)
{P10=0;P11=0;P12=0;P13=0;}//停止
/********************************************************/
voidtimer1()interrupt3//T0中断用来计数器溢出,超过测距范围
{
Flg_5ms=1;
TH1=0xee;
TL1=0;
TF1=0;
if(P14==1&&P15==0&&P16==1)fun2();
if((P14==0&&P15==0&&P16==1)||(P14==0&&P15==1&&P16==1))fun3();
if((P14==1&&P15==0&&P16==0)||(P14==1&&P15==1&&P16==0))fun4();
if((P14==1&&P15==1&&P16==1)||(P14==0&&P15==0&&P16==0)||(P17==0))fun5();
}
//-------------------------------------------
voidTimer2()interrupt5//按时器2捕捉中断,溢出中断
{
if(TF2)
{
if(speed_t2_ovf_count_temp<2)speed_t2_ovf_count_temp++;
else
{
speed_frequency=0;//frequency
speed_catch1=0;//catch1
speed_catch2=0;//catch2
speed_catch_p=0;//catchpointer
speed_t2_ovf_count_temp=0;//T2overflowcountertempregister
speed_t2_ovf_count=0;//T2overflowcounterregister
Speed=0;
}
TF2=0;
}
if(EXF2)
{
switch(speed_catch_p)
{
case0:
speed_catch1=RCAP2H;
speed_catch1<<=8;
speed_catch1+=RCAP2L;
speed_catch_p++;
break;
case1:
speed_catch2=RCAP2H;
speed_catch2<<=8;
speed_catch2+=RCAP2L;
speed_t2_ovf_count=speed_t2_ovf_count_temp;
speed_catch_p++;
break;
default:
break;
}
speed_t2_ovf_count_temp=0;
EXF2=0;
}
}
/*********************************************************/
voidmain(void)
{
unsignedcharTempCyc;
unsignedlongtemp;
Delay400Ms();//启动等待,等LCM讲入工作状态
LCMInit();//LCM初始化
Delay5Ms();//延时片刻(可不要)
DisplayListChar(0,0,mcustudio);
DisplayListChar(0,1,email);
ReadDataLCM();//测试用句无心义
for(TempCyc=0;TempCyc<10;TempCyc++)
Delay400Ms();//延时
DisplayListChar(0,1,Cls);
Speed=0;
speed_frequency=0;//frequency
speed_catch1=0;//catch1
speed_catch2=0;//catch2
speed_catch_p=0;//catchpointer
speed_t2_ovf_count_temp=0;//T2overflowcountertempregister
speed_t2_ovf_count=0;//T2overflowcounterregister
while
(1)
{
TMOD=0x11;//设T0为方式1,GATE=1;
TH0=0;
TL0=0;
TH1=0xee;
TL1=0;
T2CON=0x09;//捕捉模式
ET0=1;//许诺T0中断
ET1=1;//许诺T0中断
ET2=1;
EA=1;//开启总中断
TR1=1;//开启计数
TR2=1;
while
(1)
{
if(Flg_5ms)
{
Flg_5ms=0;
if(Counter_100ms<39)
{
Counter_100ms++;
if(Counter_100ms==20)
{
if(speed_catch_p>1)
{
temp=(unsignedlong)((65536UL*speed_t2_ovf_count)+speed_catch2-speed_catch1);//calculateT
Speed=(unsignedint)(9584640UL/temp);
speed_catch_p=0;
}
if(Speed>9999U)Speed=9999U;
buf[0]=Speed/1000;
buf[1]=(Speed/100)%10;
buf[2]=(Speed/10)%10;
buf[3]=Speed%10;
DisplayOneChar(8,1,ASCII[buf[0]]);
DisplayOneChar(9,1,ASCII[buf[1]]);
DisplayOneChar(10,1,ASCII[buf[2]]);
DisplayOneChar(11,1,ASCII[buf[3]]);
DisplayOneChar(12,1,'m');//显示M
DisplayOneChar(13,1,'m');//显示M
DisplayOneChar(14,1,'/');
DisplayOneChar(15,1,'s');
}
}else
{
Counter_100ms=0;
StartModule();
//DisplayOneChar(0,1,ASCII[0]);
TH0=0;
TL0=0;
while(!
RX);//当RX为零时等待
TR0=1;//开启计数
while(RX);//当RX为1计数并等待
TR0=0;//关闭计数
Conut();//计算
}
}
}
}
}