找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+ULN2003A步进电机控制系统仿真图与源码(正反转+加减速)

  [复制链接]
跳转到指定楼层
楼主
51单片机步进电机的正反转。加减速控制
电路原理图如下:


仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include<reg52.h>
  2. #include<stdio.h>
  3. #include<intrins.h>

  4. #define uchar unsigned char
  5. #define uint unsigned int

  6. sbit RS = P2^4;//1602数据/命令选择端(H:数据寄存器L:指令寄存器)
  7. sbit RW = P2^5;//1602读/写选择端
  8. sbit E  = P2^6;//1602使能信号端

  9. sbit key1=P3^0;//用户按键
  10. sbit key2=P3^1;
  11. sbit key3=P3^2;
  12. sbit key4=P3^3;
  13. sbit key5=P3^4;

  14. uchar code B_Rotation[8]={0x7f,0x3f,0xbf,0x9f,0xdf,0xcf,0xef,0x6f}; //反转表格
  15. uchar code F_Rotation[8]={0xef,0xcf,0xdf,0x9f,0xbf,0x3f,0x7f,0x6f}; //正转表格


  16. uchar table1[]="dir: +  spe:005";
  17. uchar table2[]="cir:000 ang:000";

  18. uchar num;
  19. uint key,flag,speed=5,zflag,znum,fflag,fnum,select,pp,qq;
  20. //1键值2键值标志3速度4正转标志5正转圈数6反转标志7反转圈数8正转角度9反转角度10选择
  21. float zang,fang;
  22. /******************************************************************/
  23. /*                    延时函数 Xms                                   */
  24. /******************************************************************/
  25. void delay(uint z)
  26. {
  27.         uint x,y;
  28.         for(x=z;x>0;x--)
  29.                 for(y=110;y>0;y--);
  30. }
  31. /******************************************************************/
  32. /*                   LCD1602写命令操作                            */
  33. /******************************************************************/
  34. void WriteCommand(uchar com)
  35. {
  36.         delay(5);//操作前短暂延时,保证信号稳定
  37.         E=0;
  38.         RS=0;
  39.         RW=0;
  40.         P0=com;
  41.         E=1;
  42.         delay(5);
  43.         E=0;
  44. }
  45. /******************************************************************/
  46. /*                   LCD1602写数据操作                            */
  47. /******************************************************************/
  48. void WriteData(uchar dat)
  49. {
  50.         delay(5);  //操作前短暂延时,保证信号稳定
  51.         E=0;
  52.         RS=1;
  53.         RW=0;
  54.         P0=dat;
  55.         E=1;
  56.         delay(5);
  57.         E=0;
  58. }
  59. /******************************************************************/
  60. /*                           1602初始化程序                       */
  61. /******************************************************************/
  62. void InitLcd()//1602初始化程序
  63. {
  64.         delay(15);
  65.         WriteCommand(0x38); //display mode
  66.         WriteCommand(0x38); //display mode
  67.         WriteCommand(0x38); //display mode
  68.         WriteCommand(0x06); //当读或写一个字符后地址指针加一,且光标加一
  69.         WriteCommand(0x0c); //显示开及光标不显示
  70.         WriteCommand(0x01); //清屏

  71.         WriteCommand(0x80);
  72.         for(num=0;num<15;num++)//第一行的显示
  73.         {
  74.                 WriteData(table1[num]);
  75.                 delay(15);
  76.         }
  77.         WriteCommand(0x80+0x40);//第二行的显示
  78.         for(num=0;num<15;num++)
  79.         {
  80.                 WriteData(table2[num]);
  81.                 delay(15);
  82.         }

  83. }
  84. /******************************************************************/
  85. /*              独立键盘扫描函数                                  */
  86. /******************************************************************/
  87. void keyscan()  
  88. {       
  89.        
  90.         P3=0xff;//拉高P3口,以读取P3口的值
  91.         if(key1==0)//键1被按下
  92.         {
  93.                 delay(5);//延时消抖
  94.                 if(key1==0)
  95.                 {
  96.                         flag=1;
  97.                 }
  98.                 while(!key1);
  99.                 delay(5);//延时消抖
  100.                 while(!key1);//松手检测
  101.         }
  102.         if(key2==0)
  103.         {
  104.                 delay(5);
  105.                 if(key2==0)
  106.                 {
  107.                         flag=2;
  108.                 }
  109.                 while(!key2);
  110.                 delay(5);
  111.                 while(!key2);
  112.         }
  113.         if(key3==0)//键1被按下
  114.         {
  115.                 delay(5);//延时消抖
  116.                 if(key3==0)
  117.                 {
  118.                         flag=3;
  119.                 }
  120.                 while(!key3);
  121.                 delay(5);//延时消抖
  122.                 while(!key3);//松手检测
  123.         }
  124.         if(key4==0)
  125.         {
  126.                 delay(5);
  127.                 if(key4==0)
  128.                 {
  129.                         flag=4;
  130.                 }
  131.                 while(!key4);
  132.                 delay(5);
  133.                 while(!key4);
  134.         }
  135.         if(key5==0)
  136.         {
  137.                 delay(5);
  138.                 if(key5==0)
  139.                 {
  140.                         flag=5;
  141.                 }
  142.                 while(!key5);
  143.                 delay(5);
  144.                 while(!key5);
  145.         }
  146. }
  147. /******************************************************************/
  148. /*                           1602显示3位数                       */
  149. /******************************************************************/
  150. void write_sfm(uchar add,uint date)//1602显示
  151. {
  152.         uchar bai,shi,ge;
  153.         bai=date/100;
  154.         shi=date%100/10;
  155.         ge=date%10;
  156.         WriteCommand(0x80+add);//设置数据地址指针
  157.         WriteData(0x30+bai);
  158.         WriteData(0x30+shi);
  159.         WriteData(0x30+ge);
  160.         WriteData(0x20);
  161. }
  162. /******************************************************************/
  163. /*                           键值处理                             */
  164. /******************************************************************/
  165. void handle_flag()
  166. {       

  167.         uchar select1;
  168.         if(TR0==0&&TR1==0)
  169.         {       
  170.                 if(flag==1) //正转
  171.                 {
  172.                         WriteCommand(0x80+0x05);
  173.                         WriteData('+');
  174.                         delay(20);
  175.                         select=0;
  176.                 }
  177.                 if(flag==2) //反转
  178.                 {
  179.                         WriteCommand(0x80+0x05);
  180.                         WriteData('-');
  181.                         delay(20);
  182.                         select=1;
  183.                 }
  184.                 if(flag==3)//转速加
  185.                 {
  186.                     speed++;
  187.                         if(speed>=12)
  188.                                 speed=12;
  189.                         write_sfm(0x0c,speed);//显示速度
  190.                         delay(20);
  191.             }
  192.                 if(flag==4)        //转速减
  193.                 {
  194.                         speed--;
  195.                         if(speed<=1)
  196.                                 speed=1;
  197.                         write_sfm(0x0c,speed);//显示速度
  198.                         delay(20);
  199.                 }
  200. }
  201.         if(flag==5)////关闭中断,停止电机
  202.         {
  203.                 select1++;
  204.                 select1%=2;
  205.                 if( select1==0)
  206.                 {
  207.                         TR0=0;
  208.                         TR1=0;
  209.                         if(select==0)//显示转动的角度
  210.                                 write_sfm(0x40+0x0c,zang);
  211.                         else
  212.                                 write_sfm(0x40+0x0c,fang);
  213.              }
  214.                 else
  215.                 {if(select==0)
  216.                 {
  217.                         TR0=1;//开定时器0,产生正转相序
  218.                         TR1=0;//关定时器1
  219.                 }
  220.                 else
  221.                 {       
  222.                         TR1=1;//开定时器1,产生反转相序
  223.                         TR0=0;//关定时器0       
  224.                 }
  225.                 }                       
  226.         }
  227.         flag=0;
  228. }


  229. void main()
  230. {
  231.        
  232.         pp=0;
  233.         qq=0;
  234.    
  235.         InitLcd();
  236.         TMOD=0x11;
  237.     EA=1;
  238.         ET0=1;
  239.         ET1=1;

  240.         TH0=(65536-(14648/speed))/256;
  241.         TL0=(65536-(14648/speed))%256;
  242.         TH1=(65536-(14648/speed))/256;
  243.         TL1=(65536-(14648/speed))%256;

  244.         TR0=0;
  245.         TR1=0;
  246.        
  247.         while(1)
  248.         {       
  249.                 keyscan();
  250.                 handle_flag();       
  251.         }

  252. }

  253. void time0() interrupt 1
  254. {       
  255.         uint zz;
  256.         TH0=(65536-(14648/speed))/256; // 360/(5.625/64)=4096   
  257.                                    //假设60秒转一圈,即60秒中断4096次,
  258.                                                                    //那么一次中断需要60000000/4096=14648个时钟
  259.                                                                    //60000000/(4096*speed)   zflag=4096时一圈
  260.         TL0=(65536-(14648/speed))%256;
  261.         zz%=8;
  262.         P1=F_Rotation[zz];  //输出对应的相
  263.         zz++;
  264.         zflag++;
  265.         if(zflag==4096) //正转了一圈
  266.         {       
  267.                 zflag=0;
  268.                 znum++;
  269.                 write_sfm(0x40+0x04,znum);
  270.         }
  271.         if(zflag%64==0)//计算正转动的角度
  272.         {
  273.                 pp++;
  274.                 zang=(uint)(pp*5.625);
  275.                 if(zang==360)
  276.                         pp=0;
  277.                 write_sfm(0x40+0x0c,zang);
  278.         }
  279.         //zang=0.088*zflag;
  280.         //write_sfm(0x40+0x0c,zang);
  281. }
  282. void time1() interrupt 3
  283. {       
  284.        
  285.         uint ff;
  286.         TH1=(65536-(14648/speed))/256;
  287.         TL1=(65536-(14648/speed))%256;
  288.     ff%=8;
  289.         P1=B_Rotation[ff]; //输出对应的相
  290.         ff++;
  291.         fflag++;
  292.         if(fflag==4096) //反转了一圈
  293.         {       
  294.                 fflag=0;
  295.                 fnum++;
  296.                 write_sfm(0x40+0x04,fnum);
  297.         }
  298.         if(fflag%64==0)//计算反转动的角度
  299.         {
  300.                 qq++;
  301.                 fang=(uint)(qq*5.625);
  302.                 if(fang==360)
  303.                 qq=0;
  304.                 write_sfm(0x40+0x0c,fang);
  305.         }
  306. }
复制代码

所有资料51hei提供下载:
步进电机protus仿真.rar (75.49 KB, 下载次数: 809)



评分

参与人数 2黑币 +60 收起 理由
dww465757120 + 10
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:419310 发表于 2018-12-7 12:07 | 只看该作者
感谢分享
回复

使用道具 举报

板凳
ID:496108 发表于 2019-3-22 14:23 | 只看该作者
想要学习单片机控制,请多多分享资料哦
回复

使用道具 举报

地板
ID:467912 发表于 2019-3-26 12:16 | 只看该作者

感谢分享
感谢分享
回复

使用道具 举报

5#
ID:498802 发表于 2019-3-26 23:00 来自手机 | 只看该作者
sidhc 发表于 2018-12-7 12:07
感谢分享

THX a lot
回复

使用道具 举报

6#
ID:511290 发表于 2019-4-20 21:07 | 只看该作者
谢谢分享
回复

使用道具 举报

7#
ID:505406 发表于 2019-5-7 10:51 | 只看该作者
为什么电机只抖动不转?
回复

使用道具 举报

8#
ID:318987 发表于 2019-5-10 21:35 | 只看该作者
select1 是起什么作用的
回复

使用道具 举报

9#
ID:549166 发表于 2019-5-31 10:06 | 只看该作者
有参考价值,感谢
回复

使用道具 举报

10#
ID:476527 发表于 2019-5-31 11:04 | 只看该作者
楼主的键值处理函数写得太长了,我帮你优化一下:
回复

使用道具 举报

11#
ID:476527 发表于 2019-5-31 11:04 | 只看该作者
楼主的键值扫描函数写得太长了,帮你优化一下
/******************************************************************/
/*              独立键盘扫描函数                                  */
/******************************************************************/
void keyscan()
{
    uchar key_data;
   
    P3 = 0xff; //拉高P3口,以读取P3口的值
    if( (P3 & 0x1f) !=0x1f)
    {
        key_data = P3 & 0x1f;
        delay(5);//延时消抖
        P3 = 0xff;
        if( (P3 & 0x1f) == key_data;)
        {
            switch(key_data)
            {
                case 0x0f: flag = 5;
                    break;
                case 0x17: flag = 4;
                    break;
                case 0x1b: flag = 3;
                    break;
                case 0x1d: flag = 2;
                    break;
                case 0x1e: flag = 1;
                    break;
                default:
                    //do you want to do here; such as error_flag;or nothing;
                    break;
            }
            do{
                P3 = 0xff;
            }while((P3 & 0x1f)!= 0x1f); //等待松键
        }
    }
}
回复

使用道具 举报

12#
ID:552098 发表于 2019-6-5 11:41 来自手机 | 只看该作者
Similarv 发表于 2019-5-31 11:04
楼主的键值扫描函数写得太长了,帮你优化一下
/******************************************************* ...

怎么再加一个显示电机运行时间的啊
回复

使用道具 举报

13#
ID:476527 发表于 2019-6-6 10:57 | 只看该作者
zys1998 发表于 2019-6-5 11:41
怎么再加一个显示电机运行时间的啊

定义一个全局变量time_moto,初始化为0;
在定时器中断里,当电机开启你就++time_moto;
电机没开就不管他;
在lcd1602的显示函数里把time_moto显示出来即可。
回复

使用道具 举报

14#
ID:425288 发表于 2019-6-7 11:34 | 只看该作者
请问LM7805稳压电路在步进电机驱动里面起什么作用?为什么要加一个稳压电路呢?
回复

使用道具 举报

15#
ID:557163 发表于 2019-6-7 14:29 | 只看该作者
饿了喝露水 发表于 2019-6-7 11:34
请问LM7805稳压电路在步进电机驱动里面起什么作用?为什么要加一个稳压电路呢?

仿真可以没有,实际使用时如果电机功率较大,需要单独供电。所以有些开发板提供单独的电机电源供选择。用uln2003这类达林顿驱动时,电压也可以不是5V,可以更高一些和电机配套。
回复

使用道具 举报

16#
ID:557241 发表于 2019-6-7 16:15 | 只看该作者
有汇编的吗
回复

使用道具 举报

17#
ID:557241 发表于 2019-6-8 17:26 | 只看该作者
求汇编啊
回复

使用道具 举报

18#
ID:557193 发表于 2019-6-8 19:59 | 只看该作者
怎么用单片机控制三个电机呢
回复

使用道具 举报

19#
ID:564933 发表于 2019-6-27 19:36 | 只看该作者
2956905260 发表于 2019-5-7 10:51
为什么电机只抖动不转?

你解决了没有,我这也是只抖不转
回复

使用道具 举报

20#
ID:16462 发表于 2019-12-11 09:21 | 只看该作者
定时器控制转速的正好想看看,谢谢分享
回复

使用道具 举报

21#
ID:669441 发表于 2019-12-20 22:01 | 只看该作者
楼主,能把你这个程序的全部代码给我吗?
回复

使用道具 举报

22#
ID:670994 发表于 2019-12-23 10:12 | 只看该作者
谢谢分享
回复

使用道具 举报

23#
ID:670994 发表于 2019-12-23 10:16 | 只看该作者
设计的非常好
回复

使用道具 举报

24#
ID:670994 发表于 2019-12-24 10:24 | 只看该作者
为什么电机不转,加减转速也无法操控
回复

使用道具 举报

25#
ID:340256 发表于 2019-12-30 16:34 | 只看该作者
感谢分享 但是感觉代码还可以再精简一点
回复

使用道具 举报

26#
ID:682467 发表于 2020-1-6 21:10 | 只看该作者
为什么我的会显示
LINK/LOCATE RUN COMPLETE.  2 WARNING(S),  28 ERROR(S)
回复

使用道具 举报

27#
ID:697653 发表于 2020-2-26 12:31 | 只看该作者
有温度控制步进电机的吗,我自己改了,可是电机不转动
回复

使用道具 举报

28#
ID:697653 发表于 2020-2-26 12:36 | 只看该作者
谢谢分享
回复

使用道具 举报

29#
ID:761534 发表于 2020-5-26 16:39 | 只看该作者
谢谢分享
回复

使用道具 举报

30#
ID:754663 发表于 2020-5-26 18:07 来自手机 | 只看该作者
为什么编译没有错误,重建却有警告
回复

使用道具 举报

31#
ID:776223 发表于 2020-6-15 15:56 | 只看该作者
如果加上看门狗的话应该怎么加
回复

使用道具 举报

32#
ID:776223 发表于 2020-6-16 20:06 | 只看该作者
Similarv 发表于 2019-5-31 11:04
楼主的键值扫描函数写得太长了,帮你优化一下
/******************************************************* ...

为什么电机只抖不转,求解
回复

使用道具 举报

33#
ID:875327 发表于 2021-1-23 11:11 来自手机 | 只看该作者
楼主好,想问一下,电机是不是会抖动,不能很好转动?还有电机转速大致范围方便说一下吗?
回复

使用道具 举报

34#
ID:120672 发表于 2021-1-28 18:34 | 只看该作者
饿了喝露水 发表于 2019-6-7 11:34
请问LM7805稳压电路在步进电机驱动里面起什么作用?为什么要加一个稳压电路呢?

图上不是有写么,输入电压是9V,单片机工作电压是5V ,所以需要加7850做电压转换。
回复

使用道具 举报

35#
ID:369050 发表于 2021-4-1 16:24 | 只看该作者
直接仿真不能用?一直抖动,
回复

使用道具 举报

36#
ID:793311 发表于 2021-4-12 10:30 | 只看该作者
Build target 'Target 1'
assembling STARTUP.A51...
A51 MACRO ASSEMBLER V8.02 - SN: T1PMC-AH696C
COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2008
"D:\Keil\C51\BIN\A51.EXE" "F:\My C51\步进电机标准\STARTUP.A51" SET (SMALL) DEBUG PRINT(.\STARTUP.lst) OBJECT(.\STARTUP.obj) EP
A51 FATAL ERROR -
  FILE:       F:\My C51\步进电机标准\STARTUP.A51
  ERROR:      FILE DOES NOT EXIST
A51 TERMINATED.
Target not created

这是为什么
回复

使用道具 举报

37#
ID:1067962 发表于 2023-3-30 10:11 | 只看该作者
请教一下,这个步进电机一档到十二档的转速怎么算呢
回复

使用道具 举报

38#
ID:1067962 发表于 2023-5-15 17:44 来自手机 | 只看该作者
Similarv 发表于 2019-5-31 11:04
楼主的键值扫描函数写得太长了,帮你优化一下
/******************************************************* ...

你好,请教一下,为什仿真图中电机转好几圈,显示圈数才加一,怎么更改程序呢
回复

使用道具 举报

39#
ID:97678 发表于 2023-5-16 18:10 | 只看该作者
compiling 电机调速 2.c...
linking...
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?_WRITE_SFM?_________2
    CALLER1: ?PR?TIME0?_________2
    CALLER2: ?PR?TIME1?_________2
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?_WRITE_SFM?_________2
    CALLER1: ?PR?TIME1?_________2
    CALLER2: ?C_C51STARTUP
Program Size: data=84.0 xdata=0 code=2569
creating hex file from ".\Objects\222"...
".\Objects\222" - 0 Error(s), 2 Warning(s).
Build Time Elapsed:  00:00:00

怎么会有这样的错误?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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