05

/**********************************************
工程名:可自动循迹、避障、精确定位的智能电动小车
说  明:本设计是基于89C52MCU的智能电动小车,系统
        启动后需要设定当前时间,紧接着选择系统模
        式-循迹、避障、定位。
        循迹模式主要利用红外反射管实现,发射管不
        断发出红外,若地面为黑线则接收管接收不到
        信号,输出高电平,当小车不在线上后接收管
        收到反射光,输出低电平,小车前头及左右各
        装一对,当左侧输出低电平时小车右转一定角
        度,当右侧输出高电平时小车左转一定角度。
        如此循环判断可实现小车循迹功能。
        避障功能大致和循迹功能一致一致,利用前头
        的红外收发管,可判断前方是否遇到障碍,若
        遇到绕过障碍物继续前行。
        定位功能,主要是是根据需要行驶的距离计算
        需要行驶的时间。
作 者:cloud
************************************************/
#include<reg52.h>

//—–以下是小车行驶模模式宏定义————–//
#define runstop  0×00
#define runhead  0×01
#define runback  0×02
#define runleft  0×03
#define runright 0×04

//—–以下是左右直流电机前进倒退控制口定义—-//
sbit runheadL = P0^0;
sbit runheadR = P0^2;
sbit runbackL = P0^1;
sbit runbackR = P0^3;

//—-以下是设置键端口定义———————//
//sbit INT0 = P3^2;
sbit keyADD = P2^1;
sbit keyDEC = P2^2;

//–以下是传感器输出端及车头左右亮灯端口定义—//
sbit leftled  = P2^0;
sbit rightled = P0^7;
sbit leftIR   = P3^5;
sbit rightIR  = P3^6;
sbit headIR   = P3^7;

//–以下是1602液晶显示的控制端口及数据口定义—//
sbit lcdrs = P2^3;
sbit lcdrw = P2^4;
sbit lcden = P2^5;
#define lcd_data P1

//——–以下是预设液晶显示内容—————//
unsigned char code num[10] = “0123456789″;
unsigned char code stunum[16] = ” 06050541 YXM.  “;
unsigned char code syswait[16] = ” Waitting Start!”;
unsigned char code sth[16] = “Please Set Hour!”;
unsigned char code stm[16] = “Please Set Mine!”;
unsigned char code cho[16] = “Please Chose!   “;
unsigned char code waitxj[16] = “Waitting XunJi! “;
unsigned char code waitbz[16] = “Waitting BiZhang”;
unsigned char code setdwi[16] = “Please Set DWei!”;
unsigned char code line1[8] = ” 07cm/s.”;
unsigned char code line2_1[16] = “XunJi           “;
unsigned char code line2_2[16] = “BiZhang         “;
unsigned char code line2_3[7] = “DingWi “;
unsigned char code line2_c[2] = “cm”;
unsigned char code cbz[16] = “You Chose BZ.   “;
unsigned char code cxj[16] = “You Chose XJ.   “;
unsigned char code cdw[16] = “You Chose DW.   “;

/*******以下是系统需要用到的全局变量,依次是时、分、秒
、定时器中断次数变量、系统标志变量、功能模式标志变量*/
unsigned char hour,mine,sec,tempnum,sysflag,workflag;
unsigned int  golong,dingtime;  //定位模式下设定行进的距离及时间

void delayms(unsigned int z)  //1毫秒延时函数
{
 unsigned int x,y;
 for(x=z;x>0;x–)
  for(y=124;y>0;y–);
}

void lcd_write_com(unsigned char com) //液晶写指令函数
{
 lcdrw = 0;
 lcdrs = 0;
 lcd_data = com;
 delayms(5);
 lcden = 1;
 delayms(5);
 lcden = 0;
}

void lcd_write_dat(unsigned char dat) //液晶写数据函数
{
 lcdrw = 0;
 lcdrs = 1;
 lcd_data = dat;
 delayms(5);
 lcden = 1;
 delayms(5);
 lcden = 0;
}

void lcd_init()    //液晶初始化函数
{
 lcden = 0;
 lcd_write_com(0×38);
 lcd_write_com(0x0c);
 lcd_write_com(0×06);
 lcd_write_com(0×01);
 lcd_write_com(0×80);
}

void runmode(unsigned char mode) //小车行进模式选择函数
{
 runheadL = 0;
 runbackL = 0;
 runheadR = 0;
 runbackR = 0;
 switch(mode)
 {
  case runstop:    //停止
  {
   runheadL = 0;
   runbackL = 0;
   runheadR = 0;
   runbackR = 0;
   break;
  }
  case runhead:    //前进
  {
   runheadL = 1;
   runheadR = 1;
   break;
  }
  case runback:    //后退
  {
   runbackL = 1;
   runbackR = 1;
   break;
  }
  case runleft:    //左转
  {
   runbackL = 1;
   runheadR = 1;
   break;
  }
  case runright:    //右转
  {
   runheadL = 1;
   runbackR = 1;
   break;
  }
  default :
  {
   break;
  }
 }
}

void xunji()     //循迹子程序
{
 leftled  = leftIR;
 rightled = rightIR;
 if(leftIR==0)
 {
  runmode(runright);
  delayms(10);
 }
 if(rightIR==0)
 {
  runmode(runleft);
  delayms(10);
 }
 runmode(runhead);
}

void bizhang()     //避障子程序
{
 if(headIR==0)
 {
  runmode(runback);
  delayms(100);
  runmode(runleft);
  delayms(333);
  runmode(runhead);
  delayms(500);
  runmode(runright);
  delayms(333);
  runmode(runhead);
  delayms(1000);
  runmode(runright);
  delayms(333);
  runmode(runhead);
  delayms(500);
  runmode(runleft);
  delayms(333);
  runmode(runhead);
 }
 runmode(runhead);
}

void dingwei(unsigned int dat) //定位子程序
{
 dat = (dat/7)*1000;   //秒速为7厘米
 runmode(runhead);
 delayms(dat);
 runmode(runstop);
 sysflag = 1;
}

void main()      //主函数入口
{
 unsigned char i,tempflag; //i用以液晶循环输出显示,tempflag用以设置时间标志零时状态
 //————–以下是系统初始化———————-//
 sysflag = 0;
 hour = 23;
 mine = 59;
 golong = 0;
 tempnum = 0;
 EA = 1;
 EX0 = 0;
 ET0 = 1;
 TR0 = 0;
 PT0 = 1;
 TMOD = 0×01;
 TH0 = 0x3C;
     TL0 = 0x0B0;
    //————–系统初始化结束———————-//
 lcd_init();  //液晶初始化调用
 //—显示初始欢迎数据——————-//
 lcd_write_com(0×80);
 for(i=0;i<16;i++)
  lcd_write_dat(stunum[i]);
 lcd_write_com(0×80+0×40);
 for(i=0;i<16;i++)
  lcd_write_dat(syswait[i]);
 //—显示初始欢迎数据结束—————//
 runmode(runstop);   //初始化小车处于停止状态
 while(1)
 {
  if(sysflag==0)   //当系统处于状态0时,判断等待按键设置时间
  {
   if(INT0==0)
   {
    delayms(5);
    if(INT0==0)
    {
     switch(tempflag)
     {
      case 0:
       tempflag = 1;
       lcd_write_com(0×80);
       lcd_write_dat(num[hour/10]);
       lcd_write_dat(num[hour%10]);
       lcd_write_dat(‘:’);
       lcd_write_dat(num[mine/10]);
       lcd_write_dat(num[mine%10]);
       for(i=0;i<11;i++)
        lcd_write_dat(‘ ‘);
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(sth[i]);
       break;
      case 1:
       tempflag = 2;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(stm[i]);
       break;
      case 2:
       TR0 = 1;
       tempflag = 0;
       sysflag = 1;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cho[i]);
       break;
      default :
          break;
     }
     while(!INT0);
    }
   }
   if(keyADD==0)
   {
    delayms(5);
    if(keyADD==0)
    {
     switch(tempflag)
     {
      case 1:
      {
       if(hour==23)
        hour = 0;
       else
        hour++;
       lcd_write_com(0×80);
       lcd_write_dat(num[hour/10]);
       lcd_write_dat(num[hour%10]);
       break;
      }
      case 2:
      {
       if(mine==59)
        mine = 0;
       else
        mine++;
       lcd_write_com(0×80+3);
       lcd_write_dat(num[mine/10]);
       lcd_write_dat(num[mine%10]);
       break;
      }
      default :
       break;
     }
    }
    while(!keyADD);
   }
   if(keyDEC==0)
   {
    delayms(5);
    if(keyDEC==0)
    {
     switch(tempflag)
     {
      case 1:
      {
       if(hour==0)
        hour = 23;
       else
        hour–;
       lcd_write_com(0×80);
       lcd_write_dat(num[hour/10]);
       lcd_write_dat(num[hour%10]);
       break;
      }
      case 2:
      {
       if(mine==0)
        mine = 59;
       else
        mine–;
       lcd_write_com(0×80+3);
       lcd_write_dat(num[mine/10]);
       lcd_write_dat(num[mine%10]);
       break;
      }
      default :
       break;
     }
    }
    while(!keyDEC);
   }

  }  
  if(sysflag==1)    //系统处于状态1时等待选择功能模式
  {
   if(INT0==0)
   {
    delayms(5);
    if(INT0==0)
    {
     if(workflag!=0)
     {
      sysflag = 2;
      lcd_write_com(0×80+5);
      for(i=0;i<8;i++)
       lcd_write_dat(line1[i]);
      switch(workflag)
      {
       case 1:
       {
        lcd_write_com(0×80+0×40);
        for(i=0;i<16;i++)
         lcd_write_dat(waitxj[i]);
        break;
       }
       case 2:
       {
        lcd_write_com(0×80+0×40);
        for(i=0;i<16;i++)
         lcd_write_dat(setdwi[i]);
        break;
       }
       case 3:
       {
        lcd_write_com(0×80+0×40);
        for(i=0;i<16;i++)
         lcd_write_dat(waitbz[i]);
        break;
       }
       default :
        break;
      }
     }
    }
    while(!INT0);
   }
   if(keyADD==0)
   {
    delayms(5);
    if(keyADD==0)
    {
     switch(workflag)
     {
      case 0:
      {
       workflag = 1;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cxj[i]);
       break;
      }
      case 1:
      {
       workflag = 2;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cdw[i]);
       break;
      }
      case 2:
      {
       workflag = 3;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cbz[i]);
       break;
      }
      case 3:
      {
       workflag = 1;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cxj[i]);
       break;
      }
      default :
       break;
     }
    }
    while(!keyADD);
   }
   if(keyDEC==0)
   {
    delayms(5);
    if(keyDEC==0)
    {
     switch(workflag)
     {
      case 0:
      {
       workflag = 3;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cbz[i]);
       break;
      }
      case 1:
      {
       workflag = 3;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cbz[i]);
       break;
      }
      case 2:
      {
       workflag = 1;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cxj[i]);
       break;
      }
      case 3:
      {
       workflag = 2;
       lcd_write_com(0×80+0×40);
       for(i=0;i<16;i++)
        lcd_write_dat(cdw[i]);
       break;
      }
     }
    }
    while(!keyDEC);
   }
  }
  if(sysflag==2)   //系统处于状态2时等待设置并启动相应的功能模式
  {
   if(workflag==1)
   {
    if(INT0==0)
    {
     delayms(5);
     if(INT0==0)
     {
      sysflag = 3;
      lcd_write_com(0×80+0×40);
      for(i=0;i<16;i++)
       lcd_write_dat(line2_1[i]);
      EX0 = 1;
     }
     while(!INT0);
    }
   }
   if(workflag==3)
   {
    if(INT0==0)
    {
     delayms(5);
     if(INT0==0)
     {
      sysflag = 3;
      lcd_write_com(0×80+0×40);
      for(i=0;i<16;i++)
       lcd_write_dat(line2_2[i]);
      EX0 = 1;
     }
     while(!INT0);
    }
   }
   if(workflag==2)
   {
    if(INT0==0)
    {
     delayms(5);
     if(INT0==0)
     {
      sysflag = 3;
      lcd_write_com(0×80+0×40);
      for(i=0;i<7;i++)
       lcd_write_dat(line2_3[i]);
      lcd_write_dat(num[(golong/100)%10]);
      lcd_write_dat(num[(golong/10)%10]);
      lcd_write_dat(num[golong%10]);
      lcd_write_dat(‘c’);
      lcd_write_dat(‘m’);
      for(i=0;i<4;i++)
       lcd_write_dat(‘ ‘);
      EX0 = 1;
     }
     while(!INT0);
    }
    if(keyADD==0)
    {
     delayms(5);
     if(keyADD==0)
     {
      if(golong==990)
       golong = 0;
      else
       golong = golong+10;
      lcd_write_com(0×80+0×40);
      lcd_write_dat(num[(golong/100)%10]);
      lcd_write_dat(num[(golong/10)%10]);
      lcd_write_dat(num[golong%10]);
      for(i=0;i<13;i++)
       lcd_write_dat(‘ ‘);
      
     }
     while(!keyADD);
    }
    if(keyDEC==0)
    {
     delayms(5);
     if(keyDEC==0)
     {
      if(golong==0)
       golong = 990;
      else
       golong = golong-10;
      lcd_write_com(0×80+0×40);
      lcd_write_dat(num[(golong/100)%10]);
      lcd_write_dat(num[(golong/10)%10]);
      lcd_write_dat(num[golong%10]);
      for(i=0;i<13;i++)
       lcd_write_dat(‘ ‘);
      
     }
     while(!keyDEC);
    }
   }
  }
  if(sysflag==3)   ///系统处于状态3时进行相应的功能模式
  {
   switch(workflag)
   {
    case 1:
     xunji();
     break;
    case 2:
     dingwei(golong);
     break;
    case 3:
     bizhang();
     break;
    default :
     break;
   }
  }
 }
}

void intt0() interrupt 0   //外部中断0中断函数,当系统处于状态3时可以通过按外部中断键来使系统回到选择模式的状态
{
 unsigned char i;
 EX0 = 0;
 runmode(runstop);
 leftled  = 1;
 rightled = 1;
 delayms(5);
 sysflag = 1;
 lcd_write_com(0×80+0×40);
 for(i=0;i<16;i++)
  lcd_write_dat(cho[i]);
 while(!INT0);
}

void intt1() interrupt 1   //定时器T0中断函数,用于实时显示
{
 TH0 = 0x3C;
    TL0 = 0x0B0;
 if(tempnum==11)
 {
  tempnum = 0;
  if(sec==59)
  {
   sec = 0;
   if(mine==59)
   {
    mine = 0;
    lcd_write_com(0×80);
    lcd_write_dat(num[hour/10]);
    lcd_write_dat(num[hour%10]);
    lcd_write_dat(‘:’);
    lcd_write_dat(num[mine/10]);
    lcd_write_dat(num[mine%10]);
    if(hour==23)
    {
     hour = 0;
    }
    else
     hour++;
   }
   else
   {
    mine++;
    lcd_write_com(0×80);
    lcd_write_dat(num[hour/10]);
    lcd_write_dat(num[hour%10]);
    lcd_write_dat(‘:’);
    lcd_write_dat(num[mine/10]);
    lcd_write_dat(num[mine%10]);
   }
  }
  else
   sec++;
 }
 else
  tempnum++;
}

Leave a Reply

click to change 看不清?点击换一张!

备案号:晋ICP备08002207号