找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3816|回复: 0
收起左侧

LCD1602液晶显示步进电机控制的单片机程序

[复制链接]
ID:419893 发表于 2018-11-3 22:09 | 显示全部楼层 |阅读模式
LCD1602显示 步进电机控制器速度方向圈数可调            
*K1-启动与停止步进电机运行;K2-设定步进电机运行圈数 (1-20圈)            
*K3-设定步进电机转动方向;K4-设定步进电机运行速度                          
*步进电机的转速控制分16档,数字越小,转速越快。                              
*7.5度步进电机;周期7.5×4=30度,电机转动一圈需12个周                    
P1.0-P1.3接输入ULN2003,2003输出再接步进电机
p3.7接小喇叭提供按键音      
*p1.4-p1.7接端口按              


程序:
  1. #include <reg51.h>       //51芯片管脚定义头文件
  2. #include <intrins.h>         //内部包含延时函数 _nop_();

  3. #define uchar unsigned char
  4. #define uint  unsigned int
  5. #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};


  6. uchar code FFW[8]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9};
  7. uchar code REV[8]={0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0xf3,0xf1};

  8. sbit  K1   = P1^4;       //运行与停止
  9. sbit  K2   = P1^5;       //设定圈数
  10. sbit  K3   = P1^6;       //方向转换
  11. sbit  K4   = P1^7;       //速率调整
  12. sbit  BEEP = P3^7;       //蜂鸣器

  13. sbit  LCD_RS = P2^0;            
  14. sbit  LCD_RW = P2^1;
  15. sbit  LCD_EN = P2^2;

  16. bit  on_off=0;            //运行与停止标志
  17. bit  direction=1;         //方向标志
  18. bit  rate_dr=1;           //速率标志
  19. bit  snum_dr=1;           //圈数标志

  20. uchar code  cdis1[ ] = {" STEPPING MOTOR "};
  21. uchar code  cdis2[ ] = {"CONTROL  PROCESS"};
  22. uchar code  cdis3[ ] = {"    STOP        "};
  23. uchar code  cdis4[ ] = {"NUM:    RATE:   "};
  24. uchar code  cdis5[ ] = {"  RUNNING       "};

  25. uchar   m,v=0,q=0;

  26. uchar   number=0,number1=0;
  27. uchar   snum=5,snum1=5;       //预设定圈数
  28. uchar   rate=8;               //预设定速率
  29. uchar   data_temp,data_temp1,data_temp2;   

  30. /********************************************************/
  31. /*                                                  
  32. /* 延时t毫秒
  33. /* 11.0592MHz时钟,延时约1ms                                    
  34. /*                                                      
  35. /********************************************************/
  36. void delay(uint t)
  37. {                           
  38.    uchar k;
  39.    while(t--)
  40.    {
  41.      for(k=0; k<125; k++)
  42.      { }
  43.    }
  44. }

  45. /********************************************************/
  46. void delayB(uchar x)    //x*0.14MS
  47. {
  48.    uchar i;
  49.    while(x--)
  50.    {
  51.      for (i=0; i<13; i++)
  52.      { }
  53.    }
  54. }

  55. /********************************************************/
  56. void beep()
  57. {
  58.    uchar j;
  59.    for (j=0;j<100;j++)
  60.     {
  61.      delayB(4);
  62.      BEEP=!BEEP;                 //BEEP取反
  63.     }
  64.      BEEP=1;                    //关闭蜂鸣器
  65.          delay(170);
  66. }

  67. /********************************************************/
  68. /*                                                               
  69. /*检查LCD忙状态                                                   
  70. /*lcd_busy为1时,忙,等待。为0时,闲,可写指令与数据。     
  71. /*                                                               
  72. /********************************************************/

  73. bit lcd_busy()
  74. {                          
  75.     bit result;
  76.     LCD_RS = 0;
  77.     LCD_RW = 1;
  78.     LCD_EN = 1;
  79.     delayNOP();
  80.     result = (bit)(P0&0x80);
  81.     LCD_EN = 0;
  82.     return(result);
  83. }

  84. /********************************************************/
  85. /*                                                                 
  86. /*写指令数据到LCD                                                
  87. /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                             
  88. /*                                                               
  89. /********************************************************/

  90. void lcd_wcmd(uchar cmd)

  91. {                          
  92.    while(lcd_busy());
  93.     LCD_RS = 0;
  94.     LCD_RW = 0;
  95.     LCD_EN = 0;
  96.     _nop_();
  97.     _nop_();
  98.     P0 = cmd;
  99.     delayNOP();
  100.     LCD_EN = 1;
  101.     delayNOP();
  102.     LCD_EN = 0;  
  103. }

  104. /********************************************************/
  105. /*                                                               
  106. /*写显示数据到LCD                                                  
  107. /*RS=H,RW=L,E=高脉冲,D0-D7=数据。                              
  108. /*                                                               
  109. /********************************************************/

  110. void lcd_wdat(uchar dat)
  111. {                          
  112.    while(lcd_busy());
  113.     LCD_RS = 1;
  114.     LCD_RW = 0;
  115.     LCD_EN = 0;
  116.     P0 = dat;
  117.     delayNOP();
  118.     LCD_EN = 1;
  119.     delayNOP();
  120.     LCD_EN = 0;
  121. }

  122. /********************************************************/
  123. /*                                                               
  124. /*  LCD初始化设定                                                
  125. /*                                                               
  126. /********************************************************/

  127. void lcd_init()
  128. {
  129.     delay(30);                  
  130.     lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据
  131.     delay(5);
  132.     lcd_wcmd(0x38);         
  133.     delay(5);
  134.     lcd_wcmd(0x38);         
  135.     delay(5);

  136.     lcd_wcmd(0x0c);      //显示开,关光标
  137.     delay(5);
  138.     lcd_wcmd(0x06);      //移动光标
  139.     delay(5);
  140.     lcd_wcmd(0x01);      //清除LCD的显示内容
  141.     delay(5);
  142. }

  143. /********************************************************/
  144. /*                                                                 
  145. /*  设定显示位置                                                  
  146. /*                                                               
  147. /********************************************************/

  148. void lcd_pos(uchar pos)
  149. {                          
  150.   lcd_wcmd(pos | 0x80);  //数据指针=80+地址变量
  151. }

  152. /********************************************************/
  153. /*                                                      
  154. /* LCD1602初始显示子程序                                             
  155. /*                                                      
  156. /********************************************************/
  157. void  LCD_init_DIS()
  158. {            
  159.      delay(10);                 //延时
  160.      lcd_init();                //初始化LCD            

  161.      lcd_pos(0);                //设置显示位置为第一行的第1个字符
  162.      m = 0;
  163.      while(cdis1[m] != '\0')
  164.       {                         //显示字符
  165.         lcd_wdat(cdis1[m]);
  166.         m++;
  167.       }

  168.      lcd_pos(0x40);             //设置显示位置为第二行第1个字符
  169.      m = 0;
  170.      while(cdis2[m] != '\0')
  171.       {
  172.         lcd_wdat(cdis2[m]);      //显示字符
  173.         m++;
  174.       }

  175.       delay(3000);               //延时        

  176.       lcd_pos(0);                //设置显示位置为第一行的第1个字符
  177.       m = 0;
  178.       while(cdis3[m] != '\0')
  179.         {                        //显示字符
  180.           lcd_wdat(cdis3[m]);
  181.           m++;
  182.         }

  183.       lcd_pos(0x40);             //设置显示位置为第二行第1个字符
  184.       m = 0;
  185.      while(cdis4[m] != '\0')
  186.         {
  187.           lcd_wdat(cdis4[m]);    //显示字符
  188.           m++;
  189.         }      

  190.         for(m=0;m<2;m++)
  191.           {
  192.                      lcd_pos(0x0c+m);    //显示方向符号
  193.              lcd_wdat(0x3e);
  194.                   }

  195. }
  196. /********************************************************/
  197. /*
  198. /*数据转换子程序
  199. /*
  200. /********************************************************/
  201. void  data_conv()
  202. {
  203.      data_temp1=data_temp/10;       //高位
  204.          if(data_temp1==0)
  205.          {data_temp1=0x20;}             //高位为0不显示
  206.      else
  207.          {data_temp1=data_temp1+0x30;}

  208.           data_temp2=data_temp%10;       //低位
  209.      data_temp2=data_temp2+0x30;
  210. }

  211. /********************************************************/
  212. /*
  213. /*数据显示子程序
  214. /*
  215. /********************************************************/
  216. void  data_dis()
  217. {
  218.            data_temp = snum;        //显示圈数
  219.            data_conv();
  220.        lcd_pos(0x44);
  221.        lcd_wdat(data_temp1);
  222.        lcd_pos(0x45);
  223.        lcd_wdat(data_temp2);
  224.            
  225.            data_temp = rate;         //显示速率
  226.            data_conv();
  227.        lcd_pos(0x4d);
  228.        lcd_wdat(data_temp1);
  229.        lcd_pos(0x4e);
  230.        lcd_wdat(data_temp2);
  231. }
  232. /********************************************************
  233. /*
  234. /* 显示运行方向符号
  235. /*
  236. /********************************************************/
  237. void  motor_DR()
  238.   {
  239.        if(direction==1)           //正转方向标志
  240.         { for(m=0;m<2;m++)
  241.           {
  242.                     lcd_pos(0x0c+m);      //显示方向符号
  243.             lcd_wdat(0x3e);
  244.                    }
  245.                  }
  246.         else
  247.          { for(m=0;m<2;m++)       //反转方向标志
  248.            {
  249.                  lcd_pos(0x0c+m);     //显示方向符号
  250.              lcd_wdat(0x3c);
  251.                    }
  252.                  }
  253.   }

  254. /********************************************************
  255. /*
  256. /* 显示运行状态
  257. /*
  258. /********************************************************/
  259. void  motor_RUN()
  260. {
  261.       if(on_off==1)
  262.            { TR0=1;
  263.              lcd_pos(0);     //设置显示位置为第一行的第1个字符
  264.          m = 0;
  265.          while(cdis5[m] != '\0')
  266.           { lcd_wdat(cdis5[m]);      //RUNNING
  267.             m++;   }
  268.             motor_DR();              //
  269.            }  
  270.       else  
  271.            { TR0=0; P1 =0xf0;
  272.                  lcd_pos(0);     //设置显示位置为第一行的第1个字符
  273.          m = 0;
  274.          while(cdis3[m] != '\0')
  275.           { lcd_wdat(cdis3[m]);      //STOP
  276.             m++;   }
  277.             motor_DR();              //
  278.                         snum=snum1;             //
  279.                         number1=0;              //清圈数计数器
  280.          }
  281.   }

  282. /********************************************************
  283. *                                                      
  284. *  主程序                                               
  285. *                                                      
  286. *********************************************************/

  287. main()
  288. {
  289.          LCD_init_DIS();
  290.                
  291.                  TMOD = 0x01;       //T0定时方式1
  292.                  TL0  = 0x33;
  293.          TH0  = 0xf5;
  294.                  EA   = 1;
  295.                  ET0  = 1;
  296.                  P1   = 0xf0;
  297.                
  298.    while(1)
  299.     {  
  300.        if(K1==0)
  301.            {
  302.          beep();
  303.              while(K1==0);       //等待键释放
  304.              on_off=~on_off;      
  305.          motor_RUN();               
  306.         }   //K1 end
  307. /********************************************************/
  308.       if(K2==0)   
  309.        {
  310.              beep();
  311.                  if(snum_dr==1)
  312.                   { snum++;
  313.                       snum1=snum;
  314.                     if(snum==0x14)
  315.             { snum_dr=~snum_dr;}
  316.                   }
  317.                  else  
  318.                    {snum--;
  319.                         snum1=snum;
  320.                     if(snum==0x01)
  321.                         { snum_dr=~snum_dr; }
  322.                    }
  323.                  
  324.            } //K2  end
  325. /********************************************************/
  326.         if(K3==0)   
  327.       {
  328.              beep();
  329.                  direction=~direction;
  330.          motor_DR();
  331.       }//K3 end

  332. /********************************************************/
  333.         if(K4==0)   
  334.        {
  335.              beep();
  336.                  if(rate_dr==1)
  337.                   { rate++;
  338.                     if(rate==0x10)
  339.             { rate_dr=~rate_dr;}
  340.                   }
  341.                   else  
  342.                    {
  343.                     rate--;
  344.                     if(rate==0x01)
  345.                         { rate_dr=~rate_dr; }
  346.                    }
  347.                 } //K4 end

  348. /********************************************************/
  349.       if(number1==snum1)   //与设定圈数是否相等  
  350.             { number1=0;
  351.          on_off=0;
  352.          TR0=0;
  353.                snum=snum1;
  354.                  P1 =0xf0;
  355.                   motor_RUN();
  356.            }         
  357.          data_dis();
  358.         }  // while(1) end
  359. }  //main end

  360. /********************************************************/
  361. /*
  362. /*  定时器 0 中断
  363. /*
  364. /********************************************************/

  365. void  motor_onoff()  interrupt  1  
  366. {     
  367.        TL0  = 0x33;
  368.        TH0  = 0xf5;
  369.        q++;
  370.            if(q < rate)
  371.         { return; }
  372.            else
  373.        {  q=0;   
  374.               number++;                  //脉冲计数

  375.              if(number==96)              //96个脉冲电机转一圈
  376.               { snum--;
  377.                     number=0;
  378.             number1++; }                 //电机转动圈数
  379.                   

  380.          if(direction==1)            //方向标志
  381.               { if(v<8)  
  382.                 {P1 = FFW[v];v++;}       //取数据,正转
  383.                if(v==8)
  384.                { v=0; }
  385.           }
  386.          
  387.              else
  388.               { if(v<8)  
  389.                 {P1 = REV[v];v++;}       //取数据,反转
  390.                 if(v==8)
  391.                 { v=0; }
  392.           }
  393.            }
  394. }

  395. /********************************************************/
复制代码




回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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