找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2788|回复: 0
打印 上一主题 下一主题
收起左侧

希望哪位大神帮我写一下详细的解释

[复制链接]
跳转到指定楼层
楼主
ID:193395 发表于 2017-4-30 12:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>//单片机头文件
#include <intrins.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>    //va_list 的头文件
#define uchar unsigned char
#define uint  unsigned int
sbit RS = P3^5;
sbit RW = P3^6;
sbit EN = P3^7;
sbit RX = P3^3;  //超声波接收
sbit TX = P3^2;  //超声波发射
static bit flag = 0;
/********************寻迹模块IO口定义*********************************/
sbit xun_ll = P0^4;   //从左到右第1
sbit xun_l = P0^3;        //从左到右第2
sbit xun_z = P0^2;        //从左到右第3
sbit xun_r = P0^1;        //从左到右第4
sbit xun_rr = P0^0;         //从左到右第5
/********************LN298电机驱动IO口定义*********************************/
sbit qu_ll = P2^0;      //左边电机控制IN1
sbit qu_zl = P2^1;     //左边电机控制IN2
sbit qu_zr = P2^2;     //右边电机控制IN1
sbit qu_rr = P2^3;     //右边电机控制IN2
#define RS_H       RS = 1
#define RS_L       RS= 0
#define RW_H       RW = 1
#define RW_L       RW = 0
#define EN_H       EN = 1
#define EN_L       EN = 0
#define READ_DATA  P1
void DelayMs(unsigned int z)  //1ms延时函数
{
  unsigned int x;
  for(;z>0;z--)
    for(x=110;x>0;x--);
}
void LCDWriteCom(unsigned char com)
{
       RS_L;
       RW_L;
       READ_DATA= com;
       EN_H;
       DelayMs(5);
       EN_L;
}
void LCDWriteData(unsigned char dat)
{
       RS_H;
       RW_L;
       READ_DATA= dat;
       EN_H;
       DelayMs(5);
       EN_L;
}
/*******************************************************************************
**函数名称:LCD_Write_str()
**函数功能:在LCD上写入一串字符
** 口:hang : 要写入的行,add 要写入列   *s要写入的指针数组
** 口:无
** 值:无
**    注:strlen()是引用库函数string.h  ,可以求出数组的长度
**    期:2014.2.22
*******************************************************************************/
void LcdWriteStr(unsigned charhang,unsigned char add,char*s)
{
   unsigned char i;
   unsigned char length = 0;
       if(hang==1)   
              LCDWriteCom(0x80+add);
       else
              LCDWriteCom(0x80+0x40+add);
   length = strlen(s);
   for(i=0;i<length;i++)
     LCDWriteData(*s++);          //指针送完数据后自加一
}
/*void LcdWriteChar(unsigned charhang,unsigned char add,char Ch)
{
       if(hang== 1)LCDWriteCom(0x80+add);
       elseLCDWriteCom(0x80+0x40+add);
       LCDWriteData(Ch);
}*/
//能像printf一样使用
void Lcd1602Printf( unsigned char x, unsignedchar y, unsigned char *p,...)
{
       charidata LcdBuf[17];
va_list ap;
va_start(ap, p);
       vsprintf(LcdBuf,p,ap);
       va_end(ap);
LcdWriteStr(x,y,LcdBuf);
}
void Init_1602(void)
{
        LCDWriteCom(0x38);
        LCDWriteCom(0x0c);
        LCDWriteCom(0x06);
        LCDWriteCom(0x01);
        DelayMs(2);
       //Lcd1602Printf(1,0,"Lcd1602 Normal");    //测试液晶1602显示用  Normal:正常
}
//触发一个高电平时间
static void StartModule(void)                    //启动模块
{
       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;
}
/*******************************************************************************
* Function Name  : Conut
* Description    : 取出定时器的值,并通过计算得到距离,返回距离到调用函数
* Input          : None
* Output         : None
* Return         : 计算得到的距离
* Attention             : 当距离大于5m时,返回38,表示超出量程
*******************************************************************************/
static int Conut(void)
{
       uintS,time;
       time=TH0*256+TL0;
       TH0=0;
       TL0=0;
       S=(time*1.7)/100;     //算出来是CM
       if((S>=500)||flag==1)//超出测量范围 , 亲测可以达到6M多一点点,不过
       {                     //跳动的很厉厉害,现改为5M
              flag = 0;
              S = 888;
       }
       returnS;
}
/*******************************************************************************
* Function Name  : GetDis
* Description    : 发出一个10us的高电平脉冲,得到超声波测出的距离
* Input          : None
* Output         : None
* Return         : S 测得的距离,Uint型变量,比如返回124,则表示为1.24M
* Attention             : 调用的函数有:StartModuleConut
*******************************************************************************/
int GetDis(void)
{
       StartModule();      //给一个高电平触发脉冲
       while(!RX)xunnji();                 //RX为零时等待
       TR0=1;                    //开启计数
       while(RX)xunnji();               //RX1计数并等待
       TR0=0;   
       returnConut();              //计算
}
//定时器初始化
static void Timer0Init(void)
{
       TMOD&= 0xf0;
       TMOD|= 0x01;        //T0为方式1
       TH0=0;
       TL0=0;         
       ET0=1;             //允许T0中断
       EA=1;                     //开启总中断   
}
/*******************************************************************************
* Function Name  : CsbInit
* Description    : 超声波初始化函数
* Input          : None
* Output         : None
* Return         : None
* Attention             : 调用的函数有:Timer0Init ,只调用了一个定时器初始化
*******************************************************************************/
void CsbInit(void)
{
       Timer0Init();
}
/************************** 定时器0中断服务函数 *******************************/
void zd0() interrupt 1            //T0中断用来计数器溢出,超过测距范围
{
       flag=1;                                               //中断溢出标志
}
/***********************小车前进函数************************/
void go()
{
       qu_ll= 1;  
       qu_zl= 0;
       qu_zr= 0;
       qu_rr= 1;           
}
// /***********************小车后退函数************************/
// void back()
// {
//    qu_ll= 0;  
//    qu_zl= 1;
//    qu_zr= 1;
//    qu_rr= 0;           
// }
/***********************小车左转函数 只有一个轮子动************************/
void left()
{
       qu_ll= 0;  
       qu_zl= 0;
       qu_zr= 0;
       qu_rr= 1;           
}
/***********************小车左转函数 左边轮子后退 右边轮子前进************************/
void left_s()
{
       qu_ll= 0;  
       qu_zl= 1;
       qu_zr= 0;
       qu_rr= 1;           
}
/***********************小车停下函数************************/
void stop()
{
       qu_ll= 0;  
       qu_zl= 0;
       qu_zr= 0;
       qu_rr= 0;
}
/***********************小车右转函数 只有一个轮子动************************/
void right()
{
       qu_ll= 1;  
       qu_zl= 0;
       qu_zr= 0;
       qu_rr= 0;           
}
/***********************小车右转函数 左边轮子前进 右边轮子后退************************/
void right_s()
{
       qu_ll= 1;  
       qu_zl= 0;
       qu_zr= 1;
       qu_rr= 0;      
}
void che_90_180_break(uchar dat)
{     
       uchari_z = 0;
       while(1)                 //循环等待中间寻迹传感器到黑线上
       {     
           if(xun_z == 0)         //如果中间那寻迹传感器到了黑线上,要让小车停下来前进了
              {
                     i_z++;          //消去干扰
                     if(i_z>= 10) //10次之后就确定寻迹模块的中间传感器到黑线上了
                     {
                            if(dat == L)   //如果是左转90度就让右转的方法制动
                                   right_s();
                            else
                                   left_s();  //如果是右转90度就让左转的方法制动
                            DelayMs(50);
                            go();               
                            break;              //break退出while(1)这个死循环
                     }
              }
              else     //没有在黑钱上就给i_z变量清零
              {
                     i_z= 0;
              }     
       }
}
/***********************小车左转90************************/
void left_s_90_while()          //小车向左转90
{
       go();                                   //前进一小会让小车转90度时刚好让黑线在小车的中间                              
       DelayMs(120);
       left_s();                        //左转90度注意这个延时不能太长  只要能让寻迹模块中间的传感离开黑线就好
       DelayMs(180);
       che_90_180_break(L);   
}
/***********************小车向右转90************************/
void right_s_90_while()     //
{
       go();                                   //前进一小会让小车转90度时刚好让黑线在小车的中间                              
       DelayMs(120);
       right_s();                      //左转90度注意这个延时不能太长  只要能让寻迹模块中间的传感离开黑线就好
       DelayMs(180);
       che_90_180_break(R);   
}
// 白线为 1   黑线为 0
void xunnji()
{
       if((xun_ll==1)&& (xun_l==1) && (xun_z==0) && (xun_r==1) &&(xun_rr==1))
       {
              go();         //小车前进
       }            
       if((xun_ll==0)&& (xun_l==0) && (xun_z==0) && (xun_r==0) &&(xun_rr==0))
       {     
              stop();                                 
       }
      
       if(((xun_ll==1)&& (xun_l==1) && (xun_z==0) && (xun_rr==1)) ||
          ((xun_ll==1) && (xun_l==1)&& (xun_z==1) && (xun_rr==1)) ||
          ((xun_ll==1) && (xun_z==1)&&  (xun_rr==0)) ||
          ((xun_ll==1) && (xun_l==1)&& (xun_z==1) && ( (xun_rr==0)))      
       {
              right();
       }
       if(((xun_ll==1)&& (xun_l==0) && (xun_r==1) && (xun_rr==1)) ||
          ((xun_ll==0) && (xun_l==0)&& (xun_z==1) && (xun_rr==1)) ||
          ((xun_ll==0) && (xun_l==1)&&  && (xun_r==1)&& (xun_rr==1)))      
       {
              left();
       }
       if((xun_ll==1)&& (xun_z==0) && (xun_rr==0))         
       {            
              go();                                                        
              DelayMs(1);
              if((xun_ll==1) &&(xun_z==0)&& (xun_rr==0))        
              {     
                     right_s_90_while();
              }
       }     
       if((xun_ll==0)&& (xun_l==0) && (xun_rr==1))        
       {
              go();
              DelayMs(1);
              if((xun_ll==0) && (xun_l==0)&& (xun_rr==1))      
              {
                     left_s_90_while();
              }
       }
}
void main(void)
{
       intDis = 0;
       InitTimer();
       Init_1602();
       CsbInit();
       Dis= GetDis();
       while(1)
       {
              xunnji();
              if(bTime_500Ms)
              {
                     bTime_500Ms= 0 ;
                     Dis= GetDis();
                     Lcd1602Printf(2,3,"Dis= %4.2f",Dis/100.0);
                     if(Dis< 24)
                     {
                            right_s();
                            DelayMs(500);
                     }
              }
              
       }
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表