找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6207|回复: 12
收起左侧

单片机控制三相步进电极(C 语言程序)

  [复制链接]
ID:72705 发表于 2015-1-24 16:07 | 显示全部楼层 |阅读模式
因为这是第一次接触步进电机以及电机驱动器,所以编了个简单的程序,其实是改过来的,有兴趣的朋友可以参考一下,喜欢交流的朋友也可以回帖.
这是l连接好的图片:
我用p1口的0、1、2、3分别接驱动器的+、PU、+、DR接线端,其中PU的脉冲提供了转速的变化,DR电平的改变决定了旋转方向下面给出程序,大家有什么不懂的到群里讨论。
  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[4]={0xf5,0xf7,0xf5,0xf7} ;
  7. uchar code REV[4]={0xfd,0xff,0xfd,0xff} ;

  8. sbit   K1    = P3^3 ;        //运行与停止
  9. sbit   K2    = P3^2 ;        //设定圈数
  10. sbit   K3    = P3^5 ;        //方向转换
  11. sbit   K4    = P3^4 ;        //速率调整

  12. sbit   BEEP = P2^4 ;        //蜂鸣器

  13. sbit   LCD_RS = P2^6 ;            
  14. sbit   LCD_RW = P3^6 ;
  15. sbit   LCD_EN = P2^7 ;

  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. int    number=0,number1=0;
  27. char    snum=1,snum1=1 ;        //预设定圈数
  28. char    rate=1 ;                //预设定速率
  29. char    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.         
  162.       lcd_pos(0) ;                 //设置显示位置为第一行的第1个字符
  163.       m = 0 ;
  164.       while(cdis1[m] != '\0')
  165.        {                          //显示字符
  166.          lcd_wdat(cdis1[m]) ;
  167.          m++ ;
  168.        }

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

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

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

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

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

  210.     data_temp2=data_temp%10 ;        //低位
  211.       data_temp2=data_temp2+0x30 ;
  212. }

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

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

  284. /********************************************************
  285. *                                                      
  286. *   主程序                                               
  287. *                                                      
  288. *********************************************************/

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

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

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

  364. /********************************************************/
  365. /*
  366. /*   定时器 0 中断
  367. /*
  368. /********************************************************/

  369. void   motor_onoff()   interrupt   1  
  370. {     
  371.         TL0   = 0xff ;
  372.         TH0   = 0xff ;
  373.         q++ ;
  374.      if(q < rate)
  375.          { return ; }
  376. else
  377.         { q=0 ;   
  378.         number++ ;                   //脉冲计数
  379.    
  380.          if(number==800)               //2*400个脉冲电机转一圈
  381.            { snum-- ;
  382.             number=0 ;
  383.             number1++ ;
  384.      }           //电机转动圈数
  385.    

  386.           if(direction==1)             //方向标志
  387.           { if(v<4)  
  388.             {P1 = FFW[v] ;v++ ;}        //取数据,正转
  389.             if(v==4)
  390.             { v=0 ; }
  391.           }
  392.    
  393.           else
  394.           { if(v<4)  
  395.             {P1 = REV[v] ;v++ ;}        //取数据,反转
  396.           if(v==4)
  397.             { v=0 ; }
  398.          
  399.    }
  400.   
  401.   
  402.      }
  403. }
复制代码

以上程序本人运行正常。
回复

使用道具 举报

ID:72901 发表于 2015-1-28 12:15 | 显示全部楼层
不错,值得学习
回复

使用道具 举报

ID:68477 发表于 2015-4-12 15:07 | 显示全部楼层
这个不错。
回复

使用道具 举报

ID:76929 发表于 2015-4-14 14:28 | 显示全部楼层
感谢分享
回复

使用道具 举报

ID:76952 发表于 2015-4-14 18:37 | 显示全部楼层
很有用处的帖子,先收藏了
回复

使用道具 举报

ID:81489 发表于 2015-6-15 12:25 | 显示全部楼层
驱动器是什么型号的
回复

使用道具 举报

ID:82813 发表于 2015-6-18 15:14 | 显示全部楼层
我也准备做个反馈程序用到步进电机,到时候向你请教。
回复

使用道具 举报

ID:114869 发表于 2016-4-18 14:49 | 显示全部楼层
好难啊
回复

使用道具 举报

ID:137360 发表于 2016-8-23 09:48 | 显示全部楼层
怎么1602液晶不显示转速和方向?????????????????????
回复

使用道具 举报

ID:235962 发表于 2017-9-27 11:02 | 显示全部楼层
赞一个,感谢分享
回复

使用道具 举报

ID:249545 发表于 2017-11-24 16:57 | 显示全部楼层
三相步进电机我买错了2个,没找到驱动就一直放,现在变废铁啦
回复

使用道具 举报

ID:274274 发表于 2018-1-29 14:52 | 显示全部楼层
非常好,谢谢分享!
回复

使用道具 举报

ID:320226 发表于 2019-3-17 21:26 | 显示全部楼层
楼主  你好单片机接到什么电器来控制电机的可以讲解下下吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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