找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3274|回复: 1
收起左侧

单片机步进电机正反转加减速 LCD12864显示,Proteus仿真程序

[复制链接]
ID:614734 发表于 2020-10-15 19:02 | 显示全部楼层 |阅读模式
三个步进电机,需要自提
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png
51hei.png 51hei.png

单片机源程序如下:
  1. #include <AT89X51.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #define uc unsigned char
  5. #define ui unsigned int
  6. #define LCDPAGE 0xB8                                  //设置页指令。
  7. #define LCDLINE 0x40                                  //设置列指令。
  8. sbit E=        P3^5;
  9. sbit RW=P3^4;
  10. sbit RS=P3^2;
  11. sbit L=P3^1;                                                 //左半平面
  12. sbit R=P3^0;                                                 //右半平面
  13. sbit Busy=P2^7;//                                         //忙 判断位
  14. uc scan_key1,scan_key2;                        //按键功能选择,00 停止,01 正转 10 反转
  15. uc step1;step2;
  16. static  step_index;
  17. ui count1,count2;                                   //定时
  18. uc butter;                                                        //按键
  19. static  speed;                                                //速度参数
  20.   //;本文件为16×16点阵中文字库文件,字的横向8点构成一字节,左边点在字节的高                 
  21. //位,字符点阵四角按左上角→右上角→左下角→右下角取字
  22. //;如你想在以后继续用HZDotReader打开文件,追加汉字点阵数据,请不要修改或增删所有注释         
  23. uc code JIANG[]=
  24. {
  25. //;江   CBDAD                                                               
  26. 0x10,0x60,0x01,0xC6,0x30,0x00,0x04,0x04,
  27. 0x04,0xFC,0x04,0x04,0x04,0x04,0x00,0x00,
  28. 0x04,0x04,0x7E,0x01,0x20,0x20,0x20,0x20,
  29. 0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x00,
  30. };
  31. uc code XI[]=
  32. {

  33. uc code DI[]=                                                           //低
  34. {                                 
  35. 0x40,0x20,0xF0,0x0C,0x07,0x02,0xFC,0x44,
  36. 0x44,0x42,0xFE,0x43,0x43,0x42,0x40,0x00,
  37. 0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x20,
  38. 0x10,0x28,0x43,0x0C,0x10,0x20,0x78,0x00,
  39. };
  40. //////////////////函数声明 **************////////
  41. //************************************************
  42. void iniLCD(void);                                                           
  43. void chkbusy(void);
  44. void wcode(uc cd) ;
  45. void wdata(uc dat);
  46. void disrow(uc page,uc col,uc *temp);
  47. void display( uc page,uc col,uc *temp);
  48. void ground(step);                                     //转步
  49. void run1();                                     //正转
  50. void run2();
  51. void stop();
  52. void delay(ui time);
  53. //************************************
  54. //**************LCD初始化 ***************
  55. //*********************************
  56. void iniLCD(void)                               //初始化
  57. { L=1;R=1;
  58.   wcode(0x38);
  59.   wcode(0x0f);                                        //开显示 设置
  60.   wcode(0xc0);                                          //设置显示启动为第一行
  61.   wcode(0x01);                                            //清屏
  62.   wcode(0x06);                                                 //画面不动,光标右移。
  63. }
  64. //******************LCD判断忙的子程序**********
  65. //**********************************************8
  66. void chkbusy(void)                                 //   测LCD忙状态
  67. {
  68.   E=1;                                                               //使能LCD
  69.   RS=0;                                                               //读写指令
  70.   RW=1;                                                                  //读
  71.   P2=0xff;                                                       //读操作前先进行一次空读操作 ,接下来才能读到数据
  72.   while(!Busy);                                                 //等待,不忙退出
  73. }
  74. //*****************************************
  75. //*****************写指令代码*****************
  76. //***********************************************
  77. void wcode(uc cd)                                        //写指令 代码
  78. {
  79.   chkbusy();                                                             //写等待
  80.   P2=0xff;                                                                          //使能LCD
  81.   RW=0;                                                                             //读禁止
  82.   RS=0;                                                                              //输出 设置
  83.   P2=cd;                                                                     //写数据代码
  84.   E=1;                                                                               //以下两句产生下降沿
  85.   E=0;                                                 //
  86. }
  87. //*******************把显示数据写到内存单元中 *****************
  88. void wdata(uc dat)                                           //写显示数据
  89. {
  90.   chkbusy();                                                                //写等待
  91.   P2=0xff;                                                                             //使能LCD
  92.   RW=0;                                                                                   //读禁止
  93.   RS=1;                                                                                  //输出 设置
  94.   P2=dat;                                                                        //写数据代码
  95.   E=1;                                                                                 //以下两句产生下降沿
  96.   E=0;                                                         //
  97. }
  98. //***********************************************
  99. //****************显示LCD程序********************
  100. //*****************可以更改程序中的64变为32就可以输出数字了**********
  101. //****************************************************************
  102. //*************还可以换成生成图片的形式,具体****************
  103. ///****************************************************
  104. void  disrow(uc page,uc col,uc *temp)
  105. {
  106.   uc i;
  107.   if(col<64)                                                // 左半平面
  108.   {
  109.     L=1;R=0;
  110.         wcode(LCDPAGE+page);                               // 写指令 页
  111.         wcode(LCDLINE+col);                                       //写指令行
  112.         if((col+16)<64)                                              //如果字在左半平面显示不了,转到右半平面去
  113.         {
  114.          for(i=0;i<16;i++)                                      //写字
  115.          wdata(*(temp+i));
  116.          }
  117.          else                                                              //右半平面
  118.          {
  119.            for(i=0;i<64-col;i++)                                 //减去左边数,从右半平面第一位开始显示
  120.          wdata(*(temp+i));                                         //写字 显示
  121.          L=0;R=1;                                                         //右半平面
  122.      wcode(LCDPAGE+page);                            // 写指令 页
  123.      wcode(LCDLINE);                                       //写指令行
  124.            for(i=64-col;i<16;i++)                                 //写字 右半平面
  125.          wdata(*(temp+i));
  126.      }
  127.    }
  128.    else
  129.    {  
  130.      L=0;R=1;
  131.      wcode(LCDPAGE+page);                          // 写指令 页
  132.      wcode(LCDLINE+col-64);                              //写指令行
  133.           for(i=0;i<16;i++)                                      //写字
  134.          wdata(*(temp+i));
  135.         }
  136. }
  137. //*********************供调用 ****子程序 *************
  138. //****************************************
  139. void  display( uc page,uc col,uc *temp)
  140. {
  141.         disrow( page, col, temp);                               //显示上半字
  142.                 disrow( page+1, col, temp+16);                     //显示下半字
  143. }
  144. //***********************主***控****程********序********************
  145. //******************************************************************
  146. //***************程序完成于2008年6月 1日,儿童节********************
  147. //***************程序员:韩福伟************************************
  148. //**********江西理工大学应用科学学院机电学部自动化******************
  149. //******************************************************************
  150. //*********
  151. void main(void)
  152. {  
  153.    P2=0xff;
  154.    iniLCD();                                      //初始化 LCD
  155.    display(0,0x00,&JIANG);                         //    江
  156.    display(0,0x10,&XI);                                   //    西
  157.    display(0,0x20,&LI);                                   //   理
  158.    display(0,0x30,&GONG);                         //   工
  159.    display(0,0x40,&DA);                                   //  大
  160.    display(0,0x50,&XUE);                            //        学
  161.    step2=0;
  162.    step1=0;
  163.    P1=0xff;
  164.    P0=0;
  165.    EX1=1;
  166.    EA=1;                                               //开中断
  167.    speed=2010;
  168.    while(1)
  169.   {  
  170.      if((scan_key1==1)&(scan_key2==0))             // 正转
  171.          {  
  172.             display(6,0x00,&ZHENG);                     //  LCD显示
  173.         display(6,0x10,&ZHUAN);
  174.             ground(step_index);
  175.             delay(speed);
  176.                step_index++;                                                   //大于7,从头再来
  177.             if(step_index>7)
  178.                    step_index=0;
  179.           }
  180.          if((scan_key1==0)&(scan_key2==1))                   //反转
  181.          {                                                                    
  182.            ground(step_index);
  183.            display(6,0x00,&FAN);                      //         LCD显示
  184.        display(6,0x10,&ZHUAN);
  185.            delay(speed);
  186.               step_index--;
  187.            if(step_index<0)                                                        //小于0,从头再来。
  188.                    step_index=7;
  189.           }
  190.          if(scan_key1==0&scan_key2==0)
  191.           {
  192.            display(6,0x00,&TING);                     //        停止
  193.        display(6,0x10,&ZHI);
  194.            display(6,0x20,&BAI);
  195.            display(6,0x30,&BAI);
  196.            P0=0xff;
  197.           }
  198.          if(step1==1&step2==0)
  199.           {
  200.             speed=speed-100;
  201.                 if(speed<200|speed==200)                                   //小于话,说明电机的速度不能再提高了。
  202.                 { speed=200;                                                           //speed参数自己设定,以下遇到也是一样的。我只是一个乱写的值
  203.                   display(6,0x20,&ZHENG);                                 //正常运行
  204.                   display(6,0x30,&CHANG);
  205.                   display(6,0x40,&YUN);
  206.                   display(6,0x50,&XING);
  207.                  }
  208.                  else                                                //加速
  209.                 {
  210.                  display(6,0x20,&JIA);
  211.                  display(6,0x30,&SU);
  212.                 }
  213.           }
  214.           if(step1==0&step2==1)
  215.           {
  216.             speed=speed+100;                               //这里面的参数,论实际情况更改
  217.                 if(speed>2500|speed==2500)                          //如果 小于了,就说明到饿低速,可以用停止按键停止。
  218.                  { speed=2500;                                                   //低速运行
  219.                   display(6,0x20,&DI);
  220.                   display(6,0x30,&SU);
  221.                   display(6,0x40,&YUN);
  222.                   display(6,0x50,&XING);
  223.                  }
  224.                   else
  225.                   {
  226.                   display(6,0x20,&JIAN);                    //减速
  227.                   display(6,0x30,&SU);
  228.                   }
  229.           }
  230. }
  231. }
  232. //***************************************************
  233. //*************************        延时子程序**************
  234. //**************************************************
  235. void delay(ui time)                                    ///延时程序
  236. { for (count1=0;count1<time;count1++ )                        //此处可以用中断进行准确定时。我只是瞎定了几个参数
  237.   for(count2=0;count2<3;count2++);
  238. }
  239. //*********************************************************
  240. //******************按键处理程序****************************
  241. //************************************************************
  242. void key(void) interrupt 2
  243. {
  244.   uc i;
  245.   for(i=0;i<200;i++);                                                   //延时防抖
  246.   if(P3_3==0)                                                        
  247.    {
  248.     butter=~P1;
  249.     switch(butter)
  250.          {case 0x01:    scan_key1=1;scan_key2=0; break;        //正常运行 ,用两个数字进行选择,是不错的办法
  251.            case 0x02:    scan_key1=0;scan_key2=0;break;        //停止
  252.           case 0x04:    scan_key1=0 ;scan_key2=1; break;      //加速
  253.           case 0x08:    step1=1;step2=0;break;               //减速
  254.           case 0x10:    step1=0;step2=1;break;              //正转
  255.           default :                     ;                             //其它值返回
  256.          }
  257.    }
  258.    P1=0XFF;
  259. }
  260. //**************************************************
  261. //**********************转步************************
  262. //**************************************************
  263. void ground(step_index)         //转步
  264. {
  265. switch(step_index)
  266.    {
  267.      case 0://0            // 这里就说明了同步电机是怎么转的。我本来是用了代码的,
  268.       P0_0 = 1;                   //但是后来考虑了一些初学者不懂同步电机到底怎么转的
  269.       P0_1 = 0;                   //我就换成这个了, 知道怎么转的人,就换成代码把,一样的
  270.       P0_2 = 0;
  271.       P0_3 = 0;
  272.       break;
  273.           case 1://0,1  
  274.       P0_0 = 1;
  275.       P0_1 = 1;
  276.       P0_2 = 0;
  277.       P0_3 = 0;
  278.       break;
  279.           case 2://1
  280.       P0_0 = 0;
  281.       P0_1 = 1;
  282.       P0_2 = 0;
  283.       P0_3 = 0;
  284.       break;
  285.           case 3://1,2
  286.       P0_0 = 0;
  287.       P0_1 = 1;
  288.       P0_2 = 1;
  289.       P0_3 = 0;
  290.       break;
  291.           case 4://2
  292.       P0_0 = 0;
  293.       P0_1 = 0;
  294.       P0_2 = 1;
  295.       P0_3 = 0;
  296.       break;
  297.           case 5://2,3
  298.       P0_0 = 0;
  299. ……………………

  300. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

Keil代码与Proteus仿真下载:
仅供参考.7z (98.74 KB, 下载次数: 51)
回复

使用道具 举报

ID:143767 发表于 2020-10-16 13:18 | 显示全部楼层
两个文件这么小压缩成一个就好了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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