找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2841|回复: 10
收起左侧

STC单片机15W1K16S驱动伺服电机 几个小时后突然速度变慢

[复制链接]
回帖奖励 5 黑币 回复本帖可获得 5 黑币奖励! 每人限 1 次
ID:140644 发表于 2022-1-17 21:06 | 显示全部楼层 |阅读模式
从来木有遇到过的麻烦事。

  感觉整个单片机频率变慢了,凡是延时的动作都慢了。电机指令如下。
delay的变量都是固定的都没有用。
本来电机的速度我是要设置的。
简单的四个子程序,两个原点归零,外部中断0触发.
两个自动左移右移子程序,一个运行设定长度.
一个外中断停止,开机伺服电机速度600左右,
运行几个小时后有可能会一半速度,350左右.
莫名其妙.

/*************手动电机左移归零****/
               void Zero_Left()                   //
               {
                DOWN=0;      //顶退开启
              delay100ms(val3);      //顶退时间
               DOWN=1;      //顶退关闭
               DIR1=0;
               MOTORRUN=1;
                while(MOTORRUN) //外部中断关闭标志位
                {
                CP1=0;
               delay(2);
               CP1=1;
               delay(2);
               if(ZERO_FLAG==0)
              MOTORRUN=0;
              }
            }
/*************手动电机右移归零****/
              void Zero_Right()                   //
               {
              DOWN=0;      //顶退开启
             delay100ms(val3);      //顶退时间
             DOWN=1;      //顶退关闭
                DIR1=1;
                MOTORRUN=1;
                while(MOTORRUN)              //回原点释放按键电机停止
                {
                 CP1=0;
                delay(2); //
                CP1=1;
                 delay(2); //
                 if(ZERO_FLAG==0)
                MOTORRUN=0;
                }
              DIR1=1; //
               }   
/*************手动电机左移****/
               void Motor_Left()                   //
               {
                DIR1=0;
              MOTORRUN=1;
                while(MOTORRUN)
                {
                for(k=0;k<ScaleFactor;k++) //运行一个比例系数周期
               {
                 CP1=0;
                delay(2);
                CP1=1;
                delay(2);
               }
                 val6=val6+1;
                if(val6==val1) //等于0 限位
                MOTORRUN=0; //关电机循环标志
                }
                printf("n1.val=%d\xff\xff\xff",val6);//实际位置
              OUT9=1;
               }
/*************手动电机右移****************/
/*************外部中断0使能停止***********/
              void Motor_Right()                  //
               {
                DIR1=1;
                while(ZERO_FLAG) //零点标志
                {
                  CP1=0;
                  delay(2);
                 CP1=1;
                 delay(2);
                }
               val6=0;
              printf("n1.val=%d\xff\xff\xff",val6);//实际位置
              DIR1=1; //
              OUT9=1;
               }
回复

使用道具 举报

ID:96682 发表于 2022-1-18 04:30 来自手机 | 显示全部楼层
得看情况,如果用电池供电出现变慢很正常无关程序
回复

使用道具 举报

ID:140644 发表于 2022-1-18 06:17 | 显示全部楼层
用的双组开关电源啊,一组5V,一组24V,一个淘晶驰串口触摸屏。
控制板也换了,电源也换了,伺服电机改成了步进电机。
变慢的时候速度刚好差不多正常时候的一半速度。
正常伺服电机700转左右,变慢的时候速度350转左右,
重新开机又正常。每天不定时发生,偶尔一天好的。
咨询STC梁工说程序的问题,一共有四台机器。
另外三台正常,这一台有问题的多了两个继电器。
其他程序都



/***机械手自动调试L716  CODE 3614  2021 12 25********/
/***原点进料,右移回原点 进料检测8次消抖动 ***********/       
              #include     <REG52.H>                      //开自动先顶退
              #include     <intrins.h>                    //保压时间
                          #include     <string.h>
                          #include     "stdio.h"
                          #include     <stdlib.h>
              #define      uint unsigned int
              #define      uchar unsigned char
                          bit          Up_XData=0;                         //原点更新标志,X发生中断置一,回主程序更新X轴位置
                          sbit         Led=P5^4;                     //EEPROM写指示
                          sbit         Auto_Led=P5^5;                 //自动运行指示
                          sbit         CP1=P2^6;             //
                          sbit         DIR1=P2^7;            //
                          sbit         UP=P1^0;                                 /****顶进输出信号****/
                          sbit         DOWN=P1^1;                         /****顶退输出信号****/
                          sbit         Valve=P1^2;                         /****料闸****/
                          sbit         OUT5=P1^3;                     //
                          sbit         OUT6=P1^4;                     //
                          sbit         OUT7=P1^5;                      //
                          sbit         OUT8=P1^6;                     //
                          sbit         OUT9=P1^7;                     //
                          sbit               S1=P3^2;                                 /***伺服电机零点赋值****/
                          sbit               S2=P3^3;                                 /***伺服电机右限位****/
                          sbit               INTPUTA=P3^4;                 /***工位A进料检测****/
                          sbit               INTPUTB=P3^5;                 /***工位B进料检测****/
                          sbit               INTPUTA1=P3^6;                 /***工位A1空位检测****/
                          sbit               INTPUTB1=P3^7;                 /***工位B1空位检测****/
                          sbit               INTPUT1=P2^0;                 /***按钮开自动****/
                          bit          ZERO_FLAG;            /*零点标志01*/
                          uchar        i,k;                  //循环总变量i
                          #define      CMD_IDLE    0         //空闲模式
              #define      CMD_READ    1         //IAP字节读命令
              #define      CMD_PROGRAM 2         //IAP字节编程命令
              #define      CMD_ERASE   3         //IAP扇区擦除命令
              #define      ENABLE_IAP  0x82      //if SYSCLK<20MHz
              #define      IAP_ADDRESS 0x0400    //时间 EEPROM首地址
                          bit                    manu;                                 /****手动标志位 0 1****/
                          bit                   MOTORRUN=0;                         //电机运行标志
                          bit                    Signauto;                     //*检测接近开关自动运行标志*/
                          typedef      unsigned char BYTE;
              typedef      unsigned int WORD;
                          uint         FLAG_S;
                          static       uint         ScaleFactor; //比例系数
                          static       uint         vala;        //归零位置
              static       uint         val0,val1,val2,val3,val4;  /*0产量计数器1设定间距2顶进时间3顶退时间4电机速度*/
                          static       uint         val5,val7;  /*5开闸时间7缓冲*/
                          static       uint         val6;                //6实际位置
                          static       uint         val8;                //开闸延时,推进轮子进模具
                          bit                   Receive_Flag;
                          uchar        kcounter,kstatus;     //按键计数标志 按键状态标志
                          uint         a[10];                //定义数组a 存储串口数据串
/*------------------------------------------*/
              void delay(uint t)
              {
              uint i,j;
              for(i=0;i<t;i++)
              for(j=0;j<2;j++);
              }
/*------------------延时子程序------------------------*/
               void delay10ms(uint x)
               {
               uint i, j;
               for (i=0;i<x;i++)
               for (j=0;j<500;j++);
               }
/*------------------延时子程序------------------------*/
               void delay100ms(uint x)
               {
               uint i, j;
               for (i=0;i<x;i++)
               for (j=0;j<11000;j++);
               }
/*----关闭IAP----------------------------*/
              void IapIdle()
              {
              IAP_CONTR = 0;                  //关闭IAP功能
              IAP_CMD = 0;                    //清除命令寄存器
              IAP_TRIG = 0;                   //清除触发寄存器
              IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
              IAP_ADDRL = 0;
              }
/*-从ISP/IAP/EEPROM区域读取一字节-*/
              BYTE IapReadByte(WORD addr)
              {
              BYTE dat;                       //数据缓冲区
              IAP_CONTR = ENABLE_IAP;         //使能IAP
              IAP_CMD = CMD_READ;             //设置IAP命令
              IAP_ADDRL = addr;               //设置IAP低地址
              IAP_ADDRH = addr >> 8;          //设置IAP高地址
              IAP_TRIG = 0x5a;                //写触发命令(0x5a)
              IAP_TRIG = 0xa5;                //写触发命令(0xa5)
              _nop_();                        //等待ISP/IAP/EEPROM操作完成
              dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
              IapIdle();                      //关闭IAP功能
              return dat;                     //返回
              }
/*-写一字节数据到ISP/IAP/EEPROM区域-*/
              void IapProgramByte(WORD addr, BYTE dat)
              {
              IAP_CONTR = ENABLE_IAP;         //使能IAP
              IAP_CMD = CMD_PROGRAM;          //设置IAP命令
              IAP_ADDRL = addr;               //设置IAP低地址
              IAP_ADDRH = addr >> 8;          //设置IAP高地址
              IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
              IAP_TRIG = 0x5a;                //写触发命令(0x5a)
              IAP_TRIG = 0xa5;                //写触发命令(0xa5)
              _nop_();                        //等待ISP/IAP/EEPROM操作完成
              IapIdle();
              }
/*---扇区擦除---------------*/
              void IapEraseSector(WORD addr)
              {
              IAP_CONTR = ENABLE_IAP;         //使能IAP val=IapReadByte(IAP_ADDRESS+1);
              IAP_CMD = CMD_ERASE;            //设置IAP命令
              IAP_ADDRL = addr;               //设置IAP低地址
              IAP_ADDRH = addr >> 8;          //设置IAP高地址
              IAP_TRIG = 0x5a;                //写触发命令(0x5a)
              IAP_TRIG = 0xa5;                //写触发命令(0xa5)
              _nop_();                        //等待ISP/IAP/EEPROM操作完成
              IapIdle();
              }
/***********************************/
                          void red_eeprom(void)
              {
                          uint m,n;                 
                          m=IapReadByte(IAP_ADDRESS+0);  //设定间距高八位
                          n=IapReadByte(IAP_ADDRESS+1);  //设定间距低八位
                          val1=m*256+n;                                 //设定间距
                          m=IapReadByte(IAP_ADDRESS+2);  //电机速度高八位
                          n=IapReadByte(IAP_ADDRESS+3);  //电机速度低八位
                          val4=m*256+n;                                 //电机速度
                          m=IapReadByte(IAP_ADDRESS+4);  //比例系数高八位
                          n=IapReadByte(IAP_ADDRESS+5);  //比例系数低八位
                          ScaleFactor=m*256+n;                         //比例系数
              m=IapReadByte(IAP_ADDRESS+6);  //顶进时间高八位
                          n=IapReadByte(IAP_ADDRESS+7);  //顶进时间低八位
                          val2=m*256+n;                                 //顶进时间
                          m=IapReadByte(IAP_ADDRESS+8);  //顶退时间高八位
                          n=IapReadByte(IAP_ADDRESS+9);  //顶退时间低八位
                          val3=m*256+n;                                         //顶退时间
                          m=IapReadByte(IAP_ADDRESS+10); //开闸时间高八位
                          n=IapReadByte(IAP_ADDRESS+11); //开闸时间低八位
                          val5=m*256+n;                                         //开闸时间
                          m=IapReadByte(IAP_ADDRESS+12); //归零位置高八位
                          n=IapReadByte(IAP_ADDRESS+13); //归零位置低八位
              vala=m*256+n;       
                          val8=IapReadByte(IAP_ADDRESS+14); //
                          Led=1;
              }
/*************写参数到EEPROM*******************************/
                          void Write_EepromTime()
                          {
                           IapEraseSector(IAP_ADDRESS); //扇区擦除
                           IapProgramByte(IAP_ADDRESS+0,val1/256);       /*设定间距高八位*/       
                           IapProgramByte(IAP_ADDRESS+1,val1%256);       /*设定间距低八位*/

                           IapProgramByte(IAP_ADDRESS+2,val4/256);       /*电机速度高八位*/  
                           IapProgramByte(IAP_ADDRESS+3,val4%256);       /*电机速度低八位*/

                           IapProgramByte(IAP_ADDRESS+4,ScaleFactor/256);/*比例系数高八位*/
                           IapProgramByte(IAP_ADDRESS+5,ScaleFactor%256);/*比例系数低八位*/

                           IapProgramByte(IAP_ADDRESS+6,val2/256);       /*顶进时间高八位*/       
                           IapProgramByte(IAP_ADDRESS+7,val2%256);       /*顶进时间低八位*/

                           IapProgramByte(IAP_ADDRESS+8,val3/256);       /*顶退时间高八位*/  
                           IapProgramByte(IAP_ADDRESS+9,val3%256);       /*顶退时间低八位*/

                           IapProgramByte(IAP_ADDRESS+10,val5/256);      /*开闸时间高八位*/  
                           IapProgramByte(IAP_ADDRESS+11,val5%256);      /*开闸时间低八位*/

                           IapProgramByte(IAP_ADDRESS+12,vala/256);      /*归零位置高八位*/  
                           IapProgramByte(IAP_ADDRESS+13,vala%256);      /*归零位置低八位*/          

                           IapProgramByte(IAP_ADDRESS+14,val8%256);      /*开闸延时低八位*/
                           Led=1;
                           }
/*************关所有输出*******************************/            
                           void reset_io()
                           {
                           P1M0=0X00;
                           P1M1=0X00;
                           P2M0=0X00;
                           P2M1=0X00;
                           P3M0=0X00;
                           P3M1=0X00;
                           P5M0=0X00;
                           P5M1=0X00;
                           CP1=1;                            //
                           DIR1=1;                           //
               UP=1;                                             /****顶进输出信号****/
                           DOWN=1;                                             /****顶退输出信号****/
                           S1=1;                                             /***伺服电机限位*2016 5 14 5.5改1.7****/
                           S2=1;
                           INTPUT1=1;                                                 //
                           }
/****************按键计数器状态寄存器归零*************/
               void RstKey()
               {
               kcounter=0;                       //按键计数器归零
               kstatus=0;                        //状态寄存器归零
               }
/*****************按键低电平检测函数*****************/
               void   LowVoltKey(void)           //按键计数器状态标志加一
               {
               kcounter++;                       
               kstatus++;     
               _nop_();                         //延时                  
               }
/*****************按键高电平检测函数*****************/
               void    HighVoltKey(void)         //按键计数器加一 状态标志归零
               {
               kcounter++;                       //按键计数器加一
               kstatus=0;                        //按键状态标志归零
               _nop_();                          //延时
               }
/*------------page 0页面显示---------------------*/          //page0  n0设定间距 n3电机速度
                           void disdata_a()//
                           {
                            red_eeprom();
                                printf("n0.val=%d\xff\xff\xff",val1);        //设定间距
                                printf("n0.val=%d\xff\xff\xff",val1);        //设定间距
                                printf("n2.val=%d\xff\xff\xff",val0);        //产量
                                printf("n3.val=%d\xff\xff\xff",val4);        //电机速度
                                if(ZERO_FLAG==1)
                                {
                                 val6=9999;
                                }
                                printf("n1.val=%d\xff\xff\xff",val6);        //实际位置
               }
/*------------page 1页面显示---------------------*/
                           void disdata_b()//                                                    
                           {
                            red_eeprom();
                                printf("n0.val=%d\xff\xff\xff",ScaleFactor);        //比例系数
                            printf("n0.val=%d\xff\xff\xff",ScaleFactor);        //比例系数
                                printf("n1.val=%d\xff\xff\xff",val2);                //顶进时间
                                printf("n2.val=%d\xff\xff\xff",val3);                //顶退时间         
                                printf("n3.val=%d\xff\xff\xff",val5);                //开闸时间       
                                printf("n5.val=%d\xff\xff\xff",vala);                //归零位置         
                           }
/*------------page 2页面显示---------------------*/
                           void disdata_c()//                                                    
                           {
                            printf("n1.val=%d\xff\xff\xff",val6);               //实际位置
                            printf("n1.val=%d\xff\xff\xff",val6);               //实际位置         
                                printf("n0.val=%d\xff\xff\xff",val8);               //开闸延时时间
                           }
/*************手动电机左移归零****/
              void Zero_Left()                  //
              {
                           DOWN=0;                                                     //顶退开启
                           delay100ms(val3);                             //顶退时间
                           DOWN=1;                                                     //顶退关闭
               DIR1=0;
                           MOTORRUN=1;
               while(MOTORRUN)                                         //外部中断关闭标志位
               {
                            CP1=0;
                                delay(2);
                                CP1=1;
                delay(2);
                                if(ZERO_FLAG==0)
                                MOTORRUN=0;
                           }
                          }
/*************手动电机右移归零****/
                          void Zero_Right()                  //
              {
                           DOWN=0;                                                     //顶退开启
                           delay100ms(val3);                             //顶退时间
                           DOWN=1;                                                     //顶退关闭
               DIR1=1;
               MOTORRUN=1;
               while(MOTORRUN)                             //回原点释放按键电机停止
               {
                            CP1=0;
                            delay(2);                                         //
                            CP1=1;
                delay(2);                                         //
                                if(ZERO_FLAG==0)
                                MOTORRUN=0;
                           }
                           DIR1=1;                                                         //
              }                          
/*************手动电机左移****/
              void Motor_Left()                  //
              {
               DIR1=0;
                           MOTORRUN=1;
               while(MOTORRUN)
               {
                            for(k=0;k<ScaleFactor;k++)                 //运行一个比例系数周期
                                {
                CP1=0;
                                delay(2);
                                CP1=1;
                delay(2);
                                }
                val6=val6+1;
                                if(val6==val1)                                                 //等于0 限位
                                MOTORRUN=0;                                                 //关电机循环标志
               }
                           printf("n1.val=%d\xff\xff\xff",val6);        //实际位置
                           OUT9=1;
              }
/*************手动电机右移****************/
/*************外部中断0使能停止***********/

void Motor_Right()                 //
              {
               DIR1=1;
               while(ZERO_FLAG)                                         //零点标志
               {
                            CP1=0;
                            delay(2);
                            CP1=1;
                delay(2);
                           }
                           val6=0;
                           printf("n1.val=%d\xff\xff\xff",val6);        //实际位置
                           DIR1=1;                                                         //
                           OUT9=1;
              }
/*----------产量加一-----------------*/                                                                                           
                           void  totaladd( )
                           {
                                val0=val0+1;
                                if(val0>9999)                         /*大于999*/
                                {
                                val0=0;                                 /*归零*/
                                }  
                           }
/*----------------自动运行程序----------------*/
//1:原点归零,赋值中断位置参数,机器回A点
//2:自动,检测A点轴承到位,未到位开气针,关气针
//3:移动台板到B点,开气针,检测B点轴承到位,未到位开气针,关气针。
//4:待机 检测两个轴承接近开关,都失电开始第二步动作
//5:检测B点轴承到位,未到位开气针,关气针。
//6:移动台板到A点,开气针,检测A点轴承到位,未到位开气针,关气针。
//7:待机 检测两个轴承接近开关,都失电开始循环
                           void autorun()
                           {
                                DOWN=0;                                                     //顶退开启
                                delay100ms(val3);                             //顶退时间
                                DOWN=1;                                                     //顶退关闭
                                while(manu)                                                 //自动循环,检测到手动中断退出循环
                                {
                                 Signauto=1;                     /*工位A进料低电平检测无输入为1,永久循环*/
                                 FLAG_S=5;                    //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
                 while(Signauto)                 /*工位一检测标志无输入为1,永久循环*/
                  {
//工位A进料检测
                  Valve=0;                                             //开气阀
                                  RstKey();
                  for(;kcounter<8;)              //按键循环8次
                  {
                   if(!INTPUTA)                  //工位A进料低电平检测
                   {
                   LowVoltKey();                                 //低电平检测到物料
                                   delay(2);
                   }
                   else if(~!INTPUTA)            //工位B进料高电平检测
                   {
                   HighVoltKey();
                                   delay(2);
                                   }
                  }
                  if(kstatus>=3) /*按键状态标志大于等于3为有效值*/
                  {                                                                 //检测到低电平,工位料满
                              delay100ms(val8);                //延时等输送带推进到位
                  Signauto=0; /*行程输入信号连续检测到3次Signauto=0退出循环*/
                  }
                                 }
                 OUT5=0;                                                         //输送带反转
                                 delay100ms(val8);                //输送带反转延时
                                 OUT5=1;
                                 FLAG_S=6;                      //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
                                 Valve=1;                                                  //关气阀
                                 FLAG_S=1;                        //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
//工位A进料检测结束
                                 Motor_Left();                                   //左 移          DIR1=1;
//工位B进料检测开始
                 Valve=0;                                                 //开气阀
                                 RstKey();                       //按键复位
                                 Signauto=1;                     /*行程输入信号检测标志无输入为1,永久循环*/
                                 FLAG_S=6;                        //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
                 while(Signauto)                 /*工位B检测标志无输入为1,永久循环*/
                  {
                  RstKey();
                  for(;kcounter<8;)              //按键循环8次
                  {
                   if(!INTPUTB)                  //工位B进料低电平检测
                   {
                   LowVoltKey();                                 //低电平kcounter大于5退出循环
                                   delay(2);
                   }
                   else if(~!INTPUTB)            //工位B进料高电平检测
                   {
                                        HighVoltKey();
                                        delay(2);
                                   }
                  }
                  if(kstatus>=3) /*按键状态标志大于等于3为有效值*/
                  {
                                  delay100ms(val8);                //延时等输送带推进到位
                              Signauto=0; /*行程输入信号连续检测到3次Signauto=0退出循环*/
                  }
                                 }
                             OUT5=0;                                                         //输送带反转
                                 delay100ms(val8);                //输送带反转延时
                                 OUT5=1;
                                 Valve=1;                                                 //关气阀
                                 FLAG_S=2;                        //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
//右 移 使用外中断
EX0=1;                          //开外部中断0
ZERO_FLAG=1;                                         //
                                 FLAG_S=2;                        //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
                 Motor_Right();
                                 FLAG_S=3;                        //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
                                 delay100ms(val2);                             //顶出时间
                                 UP=0;                                                         //顶出轴承
                                 DOWN=1;                                                 //
                                 delay100ms(val2);                             //顶出时间
//工位AB轴承取出检测,都是低电平物料取出,顶退左移  常闭开关
                                 RstKey();                                                 //
                                 for(;kcounter<8;)               //按键循环8                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                次
                                 {
                                  if(!INTPUTA1&&!INTPUTB1)           //工位AB顶出轴承信号检测
                                  {                                                                 //常闭开关
                   LowVoltKey();
                   }
                                  else
                                  kcounter=0;                    //无限循环
                                 }
                                 FLAG_S=4;                        //1 左 移 2右 移 3顶 进 4顶 退 5开 闸 6关 闸 7待 机
                 printf("va0.val=%d\xff\xff\xff",FLAG_S); //
                                 UP=1;                                                         //顶出关闭
                                 DOWN=0;                                                 //顶退开启
                                 delay100ms(val3);                             //顶退时间
                                 DOWN=1;                                                 //顶退关闭
                 totaladd();
                                 printf("n2.val=%d\xff\xff\xff",val0/2);        //产量
                     }
                           }
/*------------初始化串口---------------------*/
              void InitUart()
              {
              SCON=0X50;                  
      //8位数据,可变波特率
              AUXR|=0x01;                        //串口1选择定时器2为波特率发生器
              AUXR|=0X04;                        //定时器2时钟为Fosc,即1T
              T2L=0XE0;                          //设置定时器处置  110592》9600
              T2H=0XFE;                          //设置定时器处置  110592》9600
              AUXR|=0X10;                        //启动定时器2
              TI=1;                                                                 //
                          ES=1;                                                         //
              EA=1;                                                                 //
              }
/*×--------UART 中断服务程序-------------------**/
/**×**把接收到的数据存进数组a[i]**i开机初始化****/
/***×*接收到触摸屏结束码Receive_Flag标志位置1****/
/****×主程序检测到标志码=1判断指令功能***********/
              void Uart() interrupt 4 using 1
              {
               if(RI)
               {
                            if(SBUF==0XFA||SBUF==0XFF)                 //触摸屏结束码
                                {
                                Receive_Flag=1;                             //接收数据标志置一
                                RI=0;                                             //
                            i=0;                                         //数组计数器归零
                                }
                            else
                            {
                            a[i]=SBUF;                       //数组下标位置的数据等于SBUF
                RI=0;                                             //
                                i++;
                            }
               }
                           if(Receive_Flag==1)                                 //关手动伺服电机工作
                            {
                             if(a[0]==0XE0)                         //触摸屏放开左移右移归零键
                             {
                              if(a[1]==0XA8)                     //
                                   {
                              Receive_Flag=0;                                 //串口中断接收标志置零
                                  i=0;                                         //数组计数器归零
                                  MOTORRUN=0;                                         //关伺服电机
                                  OUT9=0;                        //运行标志manu 置0
                  }
                                 }
                                 else if(a[0]==0XA0&&a[1]==0X00)         //触摸屏发手动信号
                                 {
                                 manu=0;
                                 }
                            }
                          }
/**************原点归零**************************/
              void exint0() interrupt 0          //INT0中断入口
              {
               RstKey();                         //按键复位
               if(ZERO_FLAG==1)
               {
                if(!S1)                          //中断入口
                {
                 for(;kcounter<5;)               //按键循环5次
                 {
                  if(!S1)                        //中断入口低电平
                  {
                  LowVoltKey();                                         //按键低电平 计数器加一状态标志加一
                  }
                  else if(~!S1)                  //中断入口高电平
                  {
                  HighVoltKey();                 //按键计数器加一        状态标志归零
                  }
                 }
                 if(kstatus>=3)                  /*按键状态标志大于等于3为有效值*/
                 {     
                 EX0=0;                          //关外部中断0
                 ZERO_FLAG=0;
                 val6=vala;                      //伺服电机零点        实际位置
                 delay(200);
                                 Up_XData=1;                                         //原点更新标志
                 }
                }
                RstKey();                        //按键复位
               }
              }
/*************************************************/
                          void   main( )                      /*主程序开始*/
              {
                           reset_io();
                           IT0=1;                            //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
               EX0=1;                            //使能INT0中断
                           Led=0;
                           OUT7=0;                                      //
                           delay10ms(3000);                  //延时(30)等触摸屏先启动
                           AUXR=0X80;                        //STC系列的1T 设置
               TMOD=0X01;
                           P_SW1=0x00;                       //RXD/P3.0, TXD/P3.1
                           Receive_Flag=0;       
               InitUart();                       //初始化串口
                           printf("0XFF,0XFF,0XFF");
                           delay10ms(30);                   //延时
                           disdata_a();
                           delay10ms(30);                   //延时
                           disdata_a();
                           i=0;                              //数据接收计数器等于0
                           OUT7=1;                                      //
                           val6=9999;                                                  //未回原点,禁止自动
                           printf("n1.val=%d\xff\xff\xff",val6);
                           ZERO_FLAG=1;
                           while(1)                        //INTPUT1
                           {
                           if(Up_XData==1)                             //X轴原点更新标志为1,刷新X轴位置
                                {
                                 Up_XData=0;
                                 printf("n1.val=%d\xff\xff\xff",val6);          //伺服电机零点        实际位置
                            }
/***********************************************/
                           if(Receive_Flag==1)
                           {
                            Receive_Flag=0;                                 //重新接收
                 if(a[0]==0XE0)                
                             {
                                  if(a[1]==0XA1)                         //给单片机发顶 进信号
                                  {
                                   UP=0;                                         //顶 进
                                  }
                                  else if(a[1]==0XA2)                     //给单片机发顶 退信号
                                  {
                                   DOWN=0;  
                                  }
                                  else  if(a[1]==0XA3)                     //开 闸
                                  {
                                   Valve=0;
                                  }
                                   else if(a[1]==0XA4)                     //关 闸
                                  {
                                   Valve=1;
                                  }
                                  else if(a[1]==0XA5)                     //右移
                                  {
                                   OUT9=0;
                                   Motor_Right();
                                  }
                                  else if(a[1]==0XA6)                     //左移
                                  {
                                   OUT9=0;
                                   Motor_Left();
                                  }
                                  else if(a[1]==0XA7)                     //关顶进顶退
                                  {
                                   UP=1;                                         //顶 进
                                   DOWN=1;
                                  }                                                                 //
                                  else if(a[1]==0XBA)                     //右移归零
                                  {
                                   Zero_Right();
                                  }                                                                 //
                                  else if(a[1]==0XBB)                     //左移归零
                                  {
                                   Zero_Left();
                  }
                                 }
                                 else if(a[0]==0XE1)                 //出厂数据恢复
                             {
                                  if(a[1]==0XA1)                         //
                                  {
                                   delay10ms(1);
                                   disdata_a();                                     //page0  n0设定间距 n3电机速度
                                  }
                                  else if(a[1]==0XA2)                     //
                                  {
                                   delay10ms(1);
                                   disdata_b();                                     //page1 n0比例系数 n1顶进时间 n2顶退时间 n3开闸时间
                                  }
                                  else if(a[1]==0XA3)                     //
                                  {
                                   delay10ms(1);
                                   disdata_c();                                     //page2 n0           实际位置
                                  }
                                 }
                                else if(a[0]==0XC0)                     //
                            {
                                 if(a[1]==0X01)                             //
                                 {
                                 val1=a[3]*256+a[2];                 //设定间距
                                 printf("n4.val=%d\xff\xff\xff",val1);        //返回数据核对
                                 }
                                 else  if(a[1]==0X02)                     //
                                 {
                                 val4=a[3]*256+a[2];                 //电机速度
                                 printf("n4.val=%d\xff\xff\xff",val4);        //返回数据核对
                                 }
                                 else  if(a[1]==0X03)                     //
                                 {
                                 ScaleFactor=a[3]*256+a[2];             //比例系数
                                 printf("n4.val=%d\xff\xff\xff",ScaleFactor);        //返回数据核对
                 }
                                 else  if(a[1]==0X04)                     //
                                 {
                                 val2=a[3]*256+a[2];                 //顶进时间
                                 printf("n4.val=%d\xff\xff\xff",val2);        //返回数据核对
                 }
                                 else  if(a[1]==0X05)                     //
                                 {
                                 val3=a[3]*256+a[2];                 //顶退时间
                                 printf("n4.val=%d\xff\xff\xff",val3);        //返回数据核对
                 }
                                 else  if(a[1]==0X06)                     //
                                 {
                                 val5=a[3]*256+a[2];                 //顶出距离
                                 printf("n4.val=%d\xff\xff\xff",val5);        //返回数据核对
                 }
                                 else  if(a[1]==0X07)                     //
                                 {
                                 vala=a[3]*256+a[2];                 //归零位置
                                 printf("n4.val=%d\xff\xff\xff",vala);        //返回数据核对
                 }
                                 else  if(a[1]==0X08)                     //
                                 {
                                 val8=a[3]*256+a[2];                 //开闸延时         触摸屏page2
                                 printf("n2.val=%d\xff\xff\xff",val8);        //返回数据核对
                 }
                                 Led=0;
                                 Write_EepromTime();
                                 delay10ms(500);                  //
                                }
                            else  if(a[0]==0XB0)                 //手动半自动全自动
                                 {
                                 if(a[1]==0XA1)                             //手动
                                 {
                                 Auto_Led=1;                                         //
                                 manu=0;                                         //       
                                 }
                                else  if(a[1]==0XA2)                     //半自动
                                {
                                 if(ZERO_FLAG==0)                                 //
                                 {
                                 Auto_Led=1;                                         //
                                 manu=1;                                 //
                                 autorun();                                             //半自动自动运行
                                 }
                                }
                           }
              }
///////////////////////////
                           RstKey();                                                 //按键自动
                           for(;kcounter<5;)                 //按键循环5次
                {
                 if(!INTPUT1)                    //按键低电平
                 {
                 LowVoltKey();                   //按键低电平 计数器加一状态标志加一
                 }
                 else if(~!INTPUT1)              //按键高电平
                 {
                 HighVoltKey();                  //按键计数器加一    状态标志归零
                 }
                }
                if(kstatus>=3)                   /*按键状态标志大于等于3为有效值*/
                {
                                Auto_Led=0;                                             //
                                manu=1;                                             //自动循环        运行标志置1
                autorun();
                }
                          }     
                        }                                    //L716  CODE 3614  2021 12 25               

回复

使用道具 举报

ID:807591 发表于 2022-1-18 09:34 | 显示全部楼层
多半是干扰问题,且程序不能恢复,不能说程序完全没问题,各打50大板,退堂
回复

使用道具 举报

ID:161164 发表于 2022-1-18 11:39 | 显示全部楼层
如果变慢之后触摸屏的显示和控制都没有问题代表了内部定时器没受到影响
可以把脉冲输出代码改作用定时器控制
示范代码如下
void Timer0Init(void)                //7微秒@11.0592MHz
{
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0xB1;                //设置定时初始值
        TH0 = 0xFF;                //设置定时初始值
        TF0 = 0;                //清除TF0标志
        TR0 = 0;                //定时器0停止计时
}

void Zero_Left()                  //
{
    DOWN = 0;                                                   //顶退开启
    delay100ms(val3);                             //顶退时间
    DOWN = 1;                                                   //顶退关闭
    DIR1 = 0;
    MOTORRUN = 1;
        CP = 0;
        TR0 = 1;                //定时器0开始计时
    while(MOTORRUN)                                         //外部中断关闭标志位
    {
                if(TF0)//定时器0溢出
                {
                        CP ^= 1;
                        TF0 = 0;//清除TF0标志
                }               
        if(ZERO_FLAG == 0)
            MOTORRUN = 0;
    }
        CP = 1;
        TR0 = 0;                //定时器0停止计时
}
/*************手动电机左移****/
void Motor_Left()                  //
{
    DIR1 = 0;
    MOTORRUN = 1;
        CP = 1;
        TR0 = 1;                //定时器0开始计时
        k = 0;
    while(MOTORRUN)
    {
                if(TF0)//定时器0溢出
                {
                        CP ^= 1;
                        TF0 = 0;//清除TF0标志
                        if(k < ScaleFactor * 2)           //运行一个比例系数周期
                        {
                                k++;                       
                        }else(
                                val6 = val6 + 1;
                                k = 0;                               
                        )
                }               
        if(val6 == val1)                                               //等于0 限位
            MOTORRUN = 0;                                               //关电机循环标志
    }
        CP = 1;
        TR0 = 0;                //定时器0停止计时
    printf("n1.val=%d\xff\xff\xff", val6);       //实际位置
    OUT9 = 1;
}
最好就是改CP 为定时器0输出脚

评分

参与人数 1黑币 +10 收起 理由
czhaii + 10 赞一个!

查看全部评分

回复

使用道具 举报

ID:844772 发表于 2022-1-18 15:40 | 显示全部楼层
是不是串口通信受到干扰导致延迟时间长了,降点通讯速度和处理一下串口线(比如弄短点)?其实你也不管电机转多少圈,也不管速度,何必用步进电机呢,就普通电机算了,把行程开关前移一点也不用加刹车。
回复

使用道具 举报

ID:230742 发表于 2022-1-19 03:01 | 显示全部楼层
楼上说得对,应该是有干扰。或者串口速率低点。
也可以用PLC,或者一个叫多轴控制器的。
工业上还是PLC用得多一点。就是稳定。不影响生产。毕竟机器运行运行停一下,有损失的。
回复

使用道具 举报

ID:140644 发表于 2022-1-19 18:22 | 显示全部楼层
szb314 发表于 2022-1-18 09:34
多半是干扰问题,且程序不能恢复,不能说程序完全没问题,各打50大板,退堂

葫芦僧乱判葫芦案
回复

使用道具 举报

ID:140644 发表于 2022-3-15 07:29 | 显示全部楼层
继电器改固态继电器,故障解决
回复

使用道具 举报

ID:584814 发表于 2022-3-15 08:25 | 显示全部楼层
czhaii 发表于 2022-3-15 07:29
继电器改固态继电器,故障解决

STC说程序问题呵呵,有问题没可能前期运行正常,多半是抗干扰不行但又不认帐。
回复

使用道具 举报

ID:140644 发表于 2022-3-15 08:57 | 显示全部楼层
前面三条机器没有用继电器,这次要拖动几个调速电机。
所以并了两个继电器,过了春节去把继电器换了,当天就好了,二十多天没有出现故障
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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