1602+电机控制+51单片机C编程+proteus仿真

 /********************************************************************
* 文件名  : 液晶1602显示.c
* 描述    :  该程序实现了对液晶1602,电机 继电器的控制。
***********************************************************************/
#include<reg52.h>
 #include <intrins.h>
#include <absacc.h>
#define uchar unsigned char
#define uint  unsigned int
#define busy 0x80
#define lucheng 450
///*************************测速测距************************///////////
unsigned int SpeedDet_h,SpeedDet_v,flag,luchengstop_h=1,luchengstop_v=1;  //高电平脉冲的个数
uchar count=0,j=0,Speed_second1=1,Speed_second2=1;
float Speed_h=0,Speed_v=0; 
unsigned long  distance_h=0,distance_v=0;   
unsigned int V_lucheng[]={480,400,320,240,160,80,80,160,240,320,400,480};   //电机每次升降的高度表
//这三个引脚参考资料
sbit E=P2^7;  //1602使能引脚
sbit RW=P2^6;  //1602读写引脚 
sbit RS=P2^5;  //1602数据/命令选择引脚
            
sbit key_hz=P2^1;//定义按键位置   水平电机正转
sbit key_hf=P2^2;//定义按键位置   水平电机反转
sbit key_hstop=P2^3;//定义按键位置  水平电机停
sbit key_vz=P2^4;//定义按键位置    垂直电机正转
sbit key_vf=P3^0;//定义按键位置    垂直电机正转
sbit key_vstop=P3^1;//定义按键位置 垂直电机正转
sbit key_sz=P3^6;//定义按键位置   机械手电机正转
sbit key_sf=P3^7;//定义按键位置    机械手电机正转
sbit key_sstop=P1^7;//定义按键位置  机械手电机正转
sbit RELAY_HZ = P1^1;
sbit RELAY_HF = P1^2;
sbit RELAY_VZ = P1^3;
sbit RELAY_VF = P1^4;
sbit RELAY_SZ = P1^5;
sbit RELAY_SF = P1^6;
 /********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间大概为140US。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay(uchar k)
{
     uint i,j;
  for(i =0;i<k;i++)
     for(j = 0;j<60;j++);
}
void DelayMs(uchar aa) //延时1ms
 {
   uchar i,j;
    for(i=aa;i>0;i--)
      for(j=110;j>0;j--);
 }
 void Speed_init()
{
 TMOD=0x66;      //计数器T0在模式2下工作  定时器T1在模式1下工作
 TL0=0;   //计数器T0计数初值
 TH0=0;  
 TL1=0;    //计数器T0计数初值
 TH1=0;   
 TR0=1;         //T0计数器开始计数
 TR1=1;         //T1定时器开始定时
 ET0=0;
 ET1=1;   //定时器T1允许中断
 RCAP2H=0xDB; //定时10ms常数 
    RCAP2L=0xF0;
    TH2=RCAP2H;  //定时器2赋初值
     TL2=RCAP2L;  
    ET2=1;   //开外定时器2中断
    TR2=1;   //启动定时器2
 EA=1;       //使能总中断
    
}
void test_1602busy()         //读状态,输出状态字,检测LCD状态字DB7是否为1即忙,为1则LCD禁止
{
  P0 = 0xFF;
  E = 1;
  RS = 0;
  RW = 1;
  _nop_();
  _nop_();
  while(P0&busy)
  {
       E = 0;
    _nop_();
    E = 1;
    _nop_();
  }
  E = 0;
}
void write_1602Command(uchar co)      //写命令,写状态字
{
     test_1602busy();         //检测LCD是不是忙
  RS = 0;
  RW = 0;
  E = 0;
  _nop_();
  P0 = co;
  _nop_();
  E = 1;           // LCD使能,高电平有效
  _nop_();
  E = 0;
}
void write_1602Data(uchar Data)                      //写LCD数据函数
{
     test_1602busy();
     P0 = Data;
  RS = 1;
  RW = 0;
  E = 1;
  _nop_();
  E = 0;
}
void initial_1602()            //初始化函数
{
     write_1602Command(0x38);     //LCD功能设定,DL=1(8位)N=1(2行显示)
  delay(5);
  write_1602Command(0x01);     //清除LCD的屏幕
  delay(5);
  write_1602Command(0x06);     //LCD的模式设定,I/D=1(计数地址加1)
  delay(5);
  write_1602Command(0x0F);     //显示屏幕
  delay(5);
  write_1602Command(0x0C);      //消除光标
}
void displayonechar(uchar x,y,ddata)     //在LCD上显示一个字符
{
     uchar a;
 if(y == 0) a = 0x80;
 if(y == 1) a = 0xc0;
 a = a + x - 1;
 write_1602Command(a);
 write_1602Data(ddata);
}
void display_1602(uchar *ddata,x,y)           //在LCD上显示一行字符

    uchar a;
 if(y == 0) a = 0x80;
 if(y == 1) a = 0xc0;
 a = a + x - 1;
 write_1602Command(a);
 while(1)
 {
  if(*ddata == '\0') break;
  write_1602Data(*ddata);
  ddata++;
 }
}
/**********************************************************
*转换显示子程序
**********************************************************/
void display(float Speed1,Speed2,unsigned long  distance1,distance2)
{
 uchar temp1[10];                    //存放分解的数据
 
  //************************速度显示**************//
 Speed_second1=(unsigned char)(Speed1);           //存放分解的数据
 temp1[0] = (Speed_second1%100)/10+0x30;         //取十位转换为ASCII 码
 temp1[1] = (Speed_second1%100)%10+0x30;            //取个位转换为ASCII 码
    Speed_second2=(unsigned char)(Speed2);           //存放分解的数据
 temp1[5] = (Speed_second2%100)/10+0x30;         //取十位转换为ASCII 码
 temp1[6] = (Speed_second2%100)%10+0x30;            //取个位转换为ASCII 码
 displayonechar(5,0,temp1[0]);          //十位
 displayonechar(6,0,temp1[1]);             //个位
 displayonechar(5,1,temp1[5]);          //十位
 displayonechar(6,1,temp1[6]);             //个位

 //****************************总路程显示****************************//
 temp1[2] = distance1/100+0x30;           //取百位转换为ASCII 码
 temp1[3] = (distance1%100)/10+0x30;         //取十位转换为ASCII 码
 temp1[4] = (distance1%100)%10+0x30;         //取个位转换为ASCII 码
 temp1[7] = distance2/100+0x30;           //取百位转换为ASCII 码
 temp1[8] = (distance2%100)/10+0x30;         //取十位转换为ASCII 码
 temp1[9] = (distance2%100)%10+0x30;         //取个位转换为ASCII 码
 if(temp1[2]==0x30)
    displayonechar(13,0,'0');         //如果百位为0,显示0
 else
       {displayonechar(13,0,temp1[2]); }          //否则正常显示百位
 displayonechar(14,0,temp1[3]);          //十位
 displayonechar(15,0,temp1[4]);             //个位             //个位
   if(temp1[7]==0x30)
    displayonechar(13,1,'0');         //如果百位为0,显示0
 else
       {displayonechar(13,1,temp1[7]); }          //否则正常显示百位
 displayonechar(14,1,temp1[8]);          //十位
 displayonechar(15,1,temp1[9]);             //个位             //个位
}
void h_motorcontroler()
{
       if(!luchengstop_h)   //路程到时,电机停下,只等正键按下
    {
         RELAY_HF=1;
     DelayMs(10);
     RELAY_HZ=1;
     if(! key_hz  )     //按下相应的按键 水平电机正转
        {
     DelayMs(10);
        if(! key_hz  )     //去抖后是否按下相应的按键
    {
    luchengstop_h=1;
     RELAY_HF=1;
     DelayMs(10);
     RELAY_HZ=0;
    }
  }
    }
    else if(! key_hz  )     //按下相应的按键 水平电机正转
        {
     DelayMs(10);
        if(! key_hz  )     //去抖后是否按下相应的按键
    {
     RELAY_HF=1;
     DelayMs(10);
     RELAY_HZ=0;
    }
  }
   else if(! key_hstop )     //按下相应的按键    水平电机停
        {
   DelayMs(10);
        if(! key_hstop)     //去抖后是否按下相应的按键
    {
     RELAY_HF=1;
     DelayMs(10);
     RELAY_HZ=1;
    }  
  }
    if(!luchengstop_h)    //路程到时,电机停下,只等反键按下
    {
         RELAY_HF=1;
     DelayMs(10);
     RELAY_HZ=1;
   if(! key_hf )     //按下相应的按键   水平电机反转
        {
  DelayMs(10);
        if(! key_hf)     //去抖后是否按下相应的按键
    {
     luchengstop_h=1;
     RELAY_HZ=1;
     DelayMs(10);
     RELAY_HF=0;
    }  
  }
 
    }
    else if(! key_hf )     //按下相应的按键   水平电机反转
        {
  DelayMs(10);
        if(! key_hf)     //去抖后是否按下相应的按键
    {
     RELAY_HZ=1;
     DelayMs(10);
     RELAY_HF=0;
    }  
  }
 
    else if(! key_hstop )     //按下相应的按键    水平电机停
        {
   DelayMs(10);
        if(! key_hstop)     //去抖后是否按下相应的按键
    {
     RELAY_HF=1;
     DelayMs(10);
     RELAY_HZ=1;
    }  
  }
 
}
void v_motorcontroler()
{
       if(!luchengstop_v)   //路程到时,电机停下,只等正键按下
    {
         RELAY_VF=1;
     DelayMs(10);
     RELAY_VZ=1;
     if(! key_vz  )     //按下相应的按键 水平电机正转
        {
     DelayMs(10);
        if(! key_vz  )     //去抖后是否按下相应的按键
    {
    j++;     //改变电机每次升降的高度
    luchengstop_v=1;
     RELAY_VF=1;
     DelayMs(10);
     RELAY_VZ=0;
    }
  }
    }
    else if(! key_vz  )     //按下相应的按键 水平电机正转
        {
     DelayMs(10);
        if(! key_vz  )     //去抖后是否按下相应的按键
    {
     RELAY_VF=1;
     DelayMs(10);
     RELAY_VZ=0;
    }
  }
   else if(! key_vstop )     //按下相应的按键    水平电机停
        {
   DelayMs(10);
        if(! key_vstop)     //去抖后是否按下相应的按键
    {
     RELAY_VF=1;
     DelayMs(10);
     RELAY_VZ=1;
    }  
  }
    if(!luchengstop_v)    //路程到时,电机停下,只等反键按下
    {
         RELAY_VF=1;
     DelayMs(10);
     RELAY_VZ=1;
   if(! key_vf )     //按下相应的按键   水平电机反转
        {
  DelayMs(10);
        if(! key_vf)     //去抖后是否按下相应的按键
    {
    j++;    //改变电机每次升降的高度
     luchengstop_v=1;
     RELAY_VZ=1;
     DelayMs(10);
     RELAY_VF=0;
    }  
  }
 
    }
    else if(! key_vf )     //按下相应的按键   水平电机反转
        {
  DelayMs(10);
        if(! key_vf)     //去抖后是否按下相应的按键
    {
     RELAY_VZ=1;
     DelayMs(10);
     RELAY_VF=0;
    }  
  }
 
    else if(! key_vstop )     //按下相应的按键    水平电机停
        {
   DelayMs(10);
        if(! key_vstop)     //去抖后是否按下相应的按键
    {
     RELAY_VF=1;
     DelayMs(10);
     RELAY_VZ=1;
    }  
  }
 
}

void jixieshuo_motorcontroler()
{
    if(! key_sz  )     //按下相应的按键 水平电机正转
        {
     DelayMs(10);
        if(! key_sz  )     //去抖后是否按下相应的按键
    {
     RELAY_SF=1;
     DelayMs(10);
     RELAY_SZ=0;
    }
  }
   else if(! key_sstop )     //按下相应的按键    水平电机停
        {
   DelayMs(10);
        if(! key_sstop)     //去抖后是否按下相应的按键
    {
     RELAY_SF=1;
     DelayMs(10);
     RELAY_SZ=1;
    }  
  }
     if(! key_sf )     //按下相应的按键   水平电机反转
        {
  DelayMs(10);
        if(! key_sf)     //去抖后是否按下相应的按键
    {
     RELAY_SZ=1;
     DelayMs(10);
     RELAY_SF=0;
    }  
  }
 
    else if(! key_sstop )     //按下相应的按键    水平电机停
        {
   DelayMs(10);
        if(! key_sstop)     //去抖后是否按下相应的按键
    {
     RELAY_SF=1;
     DelayMs(10);
     RELAY_SZ=1;
    }  
  }
 
}

/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main()
{
    RELAY_HZ = 0;
    RELAY_HF = 0;
    RELAY_VZ = 0;
    RELAY_VF = 0;
    RELAY_SZ = 0;
    RELAY_SF = 0;
 initial_1602(); 
 Speed_init();
 display_1602("sph:",1,0);       //显示基本的字符
 display_1602("dish:",8,0);
 display_1602("spv:",1,1);       //显示基本的字符
 display_1602("disv:",8,1);
 display(Speed_h,Speed_v,distance_h,distance_v);
 
 while(1)
 {
  // display_1602("sph:",1,0);       //显示基本的字符
     // display_1602("dish:",8,0);
 
    // display_1602("spv:",1,1);       //显示基本的字符
 //    display_1602("disv:",8,1);
     v_motorcontroler();
  h_motorcontroler();
     jixieshuo_motorcontroler();
     display(Speed_h,Speed_v,distance_h,distance_v);
 }
}
 //**************************测速模块******************************//
 //**************************测速模块******************************//
//***************************************************************************// 

//          (2)T2的中断标志位不能硬件自动清零,必须在中断服务程序软件清零, 
//         为了定时的准确,在进入中断服务程序后第一步就使TF2=0 ;
//         (3)T2工作在16位自动重装模式下,不需要在中断服务程序重新赋值,硬件会自动使TH2=RCAP2H,TL2=RCAP2L;
void timer2() interrupt 5      //定时器1中断子程序
{
    TF2=0;        //注意 T2的溢出标志位必须软件清零,硬件不能清零,这与T0和T1不同!!
    count++;
    if(count==10)
 {
                 
  TR0=0;              //T0停止计数
  SpeedDet_h=TL0;                //读取计数值
  TL0=0;                         //重装TL0=0
  TH0=0;
     TR0=1;              //T0开始计数
     TR1=0;              //T0停止计数
  SpeedDet_v=TL1;                //读取计数值
  TL1=0;                         //重装TL0=0
  TH1=0;
     TR1=1;              //T0开始计数
         
  Speed_h= (SpeedDet_h)*20.7345/20*10;        //轮子的周长
  distance_h=distance_h+Speed_h/10;
  Speed_v= (SpeedDet_v)*20.7345/20*10;        //轮子的周长
  distance_v=distance_v+Speed_v/10;
  count=0;
  
 }
 if(distance_h>=lucheng)
  {        
    distance_h= 0;
       luchengstop_h=0;
  }
 
  if(distance_v>=V_lucheng[j])
  { 
   if(j<12)
       {       
    distance_v= 0;
    luchengstop_v=0;
    }
  else
      j = 0;
  }

 }
posted @ 2019-04-17 10:37  大海在倾听  阅读(748)  评论(0编辑  收藏  举报