微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机控制电机正反转用LCD显示电机运行方向和速度

51单片机控制电机正反转用LCD显示电机运行方向和速度

时间:10-02 整理:3721RD 点击:
我是一个纯新手,根据网上的LCD程序和正反转程序,自己稍微弄了个程序,但是仿真时候LCD是亮了,却没有显示数据;而电机根本没有运转。求高手解答,我是一个新手,真新手。
/*直流电机的PWM速度控制程序*/                                        
/*晶振采用11.0592M,产生pwm的频率约为91hz*/
/*LCD程序*/
#include<reg51.h>
#include <intrins.h>  //内部包含延时函数 _nop_();
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
uchar code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9};        //正转相序编码
uchar code REV[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1};
sbit  K1   = P3^0;       //运行与停止
sbit  K3   = P3^2;       //方向转换   
sbit  LCD_RS = P2^0;            
sbit  LCD_RW = P2^1;
sbit  LCD_EN = P2^2;
bit  on_off=0,on_off1=0;   //运行与停止标志
bit  direction=1;         //方向标志
bit  rate_dr=1;           //速率标志
uchar code  cdis1[ ] = {" STEPPING MOTOR "};
uchar code  cdis2[ ] = {"CONTROL  PROCESS"};
uchar code  cdis3[ ] = {"    STOP        "};
uchar code  cdis4[ ] = {"NO:    RATE:    TEXT:   "};
uchar code  cdis5[ ] = {"    RUNNING     "};
uchar   m,v=0,q=0,q1;
uchar   data_temp,data_temp1,data_temp2;
sbit en1=P2^7;    /*L298 Enable A*/
sbit en2=P3^0;          /*L298 Enable B*/
sbit s1=P2^3;     /*L298 input 1*/
sbit s2=P2^4;     /*l298 input 2*/
sbit s3=P2^5;     /*L298 Input 3*/
sbit s4=P2^6;     /*L298 Inout 4*/
uchar t=0;        /*中断计数器*/
uchar m1=0;                  /*电机1速度值*/
uchar m2=0;       /*电机2速度值*/
uchar tmp1,tmp2;  /*电机当前速度值*/
/*电机控制函数index-电机号(1,2);speed-电机速度(-100-100)*/
void motor_1(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
  if(index==1);     /*电机1的处理*/
  {
   m1=abs(speed);    /*取速度值的绝对值*/
   if(speed<0)       /*速度值为负则反转*/
   {
     s1=0;
     s2=1;
    }
   else              /*不为负数则正转*/
    {
     s1=1;
     s2=0;
    }
   }
}
}
void motor_2(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
  if(index==2)      /*电机2的处理*/
  {
   m2=abs(speed);    /*电机2的速度控制*/
   if(speed<0)      /*电机2的方向控制*/
   {
     s3=0;
     s4=1;
   }
   else
   {
     s3=1;
     s4=0;
   }
  }
}
}
void motor_12(uchar index,char speed)
{
if(speed>=-100&&speed<=100)
{
  if(index==1);     /*电机1的处理*/
  {
   m1=abs(speed);    /*取速度值的绝对值*/
   if(speed<0)       /*速度值为负则反转*/
    {
     s1=0;
     s2=1;
    }
   else              /*不为负数则正转*/
    {
     s1=1;
     s2=0;
    }
  }
if(index==2)      /*电机2的处理*/
{
  m2=abs(speed);    /*电机2的速度控制*/
  if(speed<0)      /*电机2的方向控制*/
   {
    s3=0;
    s4=1;
   }
  else
   {
    s3=1;
    s4=0;
   }
  }
}
}
void delayA(uint j)/*简易延时函数*/
{
for(j;j>0;j--);
}   
/********************************************************/
/*                                                  
/* 延时t毫秒
/* 11.0592MHz时钟,延时约1ms                                    
/*                                                      
/********************************************************/
void delay(uint t)                //tms
{                           
   uchar k;
   while(t--)
   {
     for(k=0; k<125; k++)
     { }
   }
}
/********************************************************/
void delayB(uchar x)    //x*0.14MS
{
   uchar i;
   while(x--)
   {
     for (i=0; i<13; i++)
     { }
   }
}
/********************************************************/
/********************************************************/
/*                                                               
/*检查LCD忙状态                                                   
/*lcd_busy为1时,忙,等待。为0时,闲,可写指令与数据。     
/*                                                               
/********************************************************/
bit lcd_busy()
{                          
    bit result;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(P0&0x80);
    LCD_EN = 0;
    return(result);
}
/********************************************************/
/*                                                                 
/*写指令数据到LCD                                                
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                             
/*                                                               
/********************************************************/
void lcd_wcmd(uchar cmd)
{                          
   while(lcd_busy());
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    _nop_();
    _nop_();
    P0 = cmd;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}
/********************************************************/
/*                                                               
/*写显示数据到LCD                                                  
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。                              
/*                                                               
/********************************************************/
void lcd_wdat(uchar dat)
{                          
   while(lcd_busy());
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 0;
    P0 = dat;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;
}
/********************************************************/
/*                                                               
/*  LCD初始化设定                                                
/*                                                               
/********************************************************/
void lcd_init()
{
    delay(30);                  
    lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据
    delay(5);
    lcd_wcmd(0x38);         
    delay(5);
    lcd_wcmd(0x38);         
    delay(5);
    lcd_wcmd(0x0c);      //显示开,关光标
    delay(5);
    lcd_wcmd(0x06);      //写入新数据后光标右移
    delay(5);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delay(5);
}
/********************************************************/
/*                                                                 
/*  设定显示位置                                                  
/*                                                               
/********************************************************/
void lcd_pos(uchar pos)
{                          
  lcd_wcmd(pos | 0x80);  //数据指针=80+地址变量
}
/********************************************************/
/*                                                      
/* LCD1602初始显示子程序                                             
/*                                                      
/********************************************************/
void  LCD_init_DIS()
{            
     delay(10);                 //延时
     lcd_init();                //初始化LCD            
     lcd_pos(0);                //设置显示位置为第一行的第1个字符
     m = 0;
     while(cdis1[m] != '\0')
      {                         //显示字符
        lcd_wdat(cdis1[m]);
        m++;
      }
     lcd_pos(0x40);             //设置显示位置为第二行第1个字符
     m = 0;
     while(cdis2[m] != '\0')
      {
        lcd_wdat(cdis2[m]);      //显示字符
        m++;
      }
      delay(3000);               //延时        
      lcd_pos(0);                //设置显示位置为第一行的第1个字符
      m = 0;
      while(cdis3[m] != '\0')
        {                        //显示字符
          lcd_wdat(cdis3[m]);
          m++;
        }
      lcd_pos(0x40);             //设置显示位置为第二行第1个字符
      m = 0;
     while(cdis4[m] != '\0')
        {
          lcd_wdat(cdis4[m]);    //显示字符
          m++;
        }      
        for(m=0;m<2;m++)
          {
       lcd_pos(0x0c+m);    //显示方向符号
             lcd_wdat(0x3e);
    }
}
/********************************************************/
/*
/*数据转换子程序
/*
/********************************************************/
void  data_conv()
{
     data_temp1=data_temp/10;       //高位
  if(data_temp1==0)
  {data_temp1=0x20;}             //高位为0不显示
     else
  {data_temp1=data_temp1+0x30;}
   data_temp2=data_temp%10;       //低位
     data_temp2=data_temp2+0x30;
}
/********************************************************/
/*
/*数据显示子程序
/*
/********************************************************/
void  data_dis()
{
data_temp = tmp1;         //显示速率
    data_conv();
       lcd_pos(0x4d);
       lcd_wdat(data_temp1);
       lcd_pos(0x4e);
       lcd_wdat(data_temp2);
}
/********************************************************
/*
/* 显示运行方向符号
/*
/********************************************************/
void  motor_DR()
  {
       if(direction==1)           //正转方向标志
        { for(m=0;m<2;m++)
          {
      lcd_pos(0x0c+m);      //显示方向符号
            lcd_wdat(0x3e);
     }
   }
        else
         { for(m=0;m<2;m++)       //反转方向标志
           {
          lcd_pos(0x0c+m);     //显示方向符号
             lcd_wdat(0x3c);
     }
   }
  }
/********************************************************
/*
/* 显示运行状态
/*
/********************************************************/
void  motor_RUN()
{
      if(on_off==1)
    { TR0=1;
      lcd_pos(0);     //设置显示位置为第一行的第1个字符
         m = 0;
         while(cdis5[m] != '\0')
          { lcd_wdat(cdis5[m]);      //RUNNING
            m++;   }
            motor_DR();              //
    }  
      else  
    { TR0=0; P1 =0x0f;
   lcd_pos(0);     //设置显示位置为第一行的第1个字符
         m = 0;
         while(cdis3[m] != '\0')
          { lcd_wdat(cdis3[m]);      //STOP
            m++;   }
            motor_DR();              //
         }
  }
  void main()
{
   char i;
   LCD_init_DIS();
TMOD=0x02;        /*设定T0的工作模式为2*/
TH0=0x9B;         /*装入定时器的初值*/
TL0=0x9B;      
EA=1;             /*开中断*/
ET0=1;                          /*定时器0允许中断*/
TR0=1;                          /*启动定时器0*/
P1=0x0f;
   while(1)
    {  
       if(K1==0)
    {
      delay(20);
          if(K1==0)
          {  
      while(K1==0);       //等待键释放
      on_off=~on_off;      
         motor_RUN();
                 }
        }   //K1 end
/********************************************************/
        if(K3==0)   
      {
      delay(20);
          if(K3==0)
          {  
   direction=~direction;
         motor_DR();
      }
         delay(100);
          }//K3 end
        }
while(1)          /*电机实际控制演示*/
{
for(i=0;i<=100;i++)/*正转加速*/
{
motor_12(1,i);
motor_12(2,i);
delayA(5000);
}
for(i=100;i>0;i--)/*正转减速*/
{
motor_12(1,i);
motor_12(2,i);
delayA(5000);
}
for(i=0;i<=100;i++)/*反转加速*/
{
motor_12(1,-i);
motor_12(2,-i);
delayA(5000);
}
for(i=100;i>0;i--)/*反转减速*/
{
motor_12(1,-i);
motor_12(2,-i);
delayA(5000);
}
}
}
void timer0() interrupt 1/*T0中断服务程序*/
{
if(t==0)          /*1个PWM周期完成后才回接受新数值*/
{
tmp1=m1;
tmp2=m2;
}
if(t<tmp1) en1=1;else en1=0; /*产生电机1的PWM信号*/
if(t<tmp2) en2=1;else en2=0; /*产生电机2的PWM信号*/
t++;
if(t>=100) t=0;   /*1个PWM信号由100此中断产生*/
}


已退回5积分

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top