登录
首页 单片机论坛
回帖 发帖
正文

主题:大侠们救救小弟吧,单片机用于工控~

点击:1966 回复:10

各位大侠,我小弟是搞三菱PLC编程的,现在刚学单片机不久,我写了一程式,也试机了,动作要求是达到了,就是速度很慢,我用的AT89C52的芯片,程式如下:
/***********************************************************************************/
//                       _______
//      P1.0  su1 --|O         |-- VCC
//      P1.1  su2 --|           |-- P0.0   out1
//      P1.2  su3 --|   A      |-- P0.1   out2
//      P1.3  su4 --|   T      |-- P0.2   out3
//      P1.4  su5 --|   8      |-- P0.3   out4
//      P1.5  su6 --|   9      |-- P0.4   out5
//      P1.6  ok  --|   C       |-- P0.5   out6
//      P1.7  ng  --|   5       |-- P0.6   counter
//            reset --|   2       |-- P0.7   start_test_machine
//      P3.0  rxd --|            |-- EA
//      P3.1  txd --|            |-- ALE
//     P3.2 stop --|   M       |-- PSEN
//      P3.3start --|   C       |-- P2.7   hand2
//      P3.4rstpi --|   U        |-- P2.6 hand1
// P3.5 zi_dong --|            |-- P2.5   sd6
//      P3.6  led --|            |-- P2.4   sd5
//    P3.7 beep --|            |-- P2.3   sd4
//           OSC2 --|            |-- P2.2   sd3
//           OSC1 --|            |-- P2.1   sd2
//            GND --|_______|-- P2.0   sd1
/***********************************************************************************/
#include
#define uint unsigned int
sbit counter=P0^6;
sbit qi_dong=P3^3;
sbit zi_dong=P3^5;
sbit stop=P3^2;
sbit yuan_dian1=P1^0;
sbit yuan_dian2=P1^1;
sbit zhong_dian1=P2^0;
sbit zhong_dian2=P2^1;
sbit hand1=P2^6;
sbit hand2=P2^7;
sbit out1=P0^0;
sbit out2=P0^1;
sbit beep=P3^7;
int a=1;
int e=10;
int f=1;
int g=1;
int h=1;
int i=1;  
int j=1;
int n=1;
int o=1;
int p=1;
int b=0;
int c=0;
int r=1;
int s=1;
int t=1;
void delayms(uint);
void bao_jing_yuan1(void);
void bao_jing_zhong1(void);
void bao_jing_yuan2(void);
void bao_jing_zhong2(void);
void reset(void);
void main()
{
         
     beep=0; //开机响一下
   delayms(200);
 beep=1;
 delayms(50);
       
     while(1)

{
      reset();
      bao_jing_yuan1();//检查感应器是否在正常状态
              bao_jing_yuan2(); //检查感应器是否在正常状态
              bao_jing_zhong1(); //检查感应器是否在正常状态
              bao_jing_zhong2(); //检查感应器是否在正常状态

     if(zi_dong==0)
   {
                       s=1; //复位手动部分的辅助线圈
 if(o==1)
      {
         out1=1; //运行自动前复位
      out2=1; //运行自动前复位
       o=0;
      }

     if(qi_dong==0)
          {
          a=0;
       }
           if(a==0) //总开关
 {
     if(n==1)
     {
        if(yuan_dian1==0)//在第一个气缸原点时
         {
                                                   out1=0;      //第一个气缸起动
    f=0;       //执行下一个动作
   n=0;       //复位n(相当于复位自锁一样)
}
    }
          if(f==0)  
              {
                                if(yuan_dian2==0,zhong_dian1==0)//第一个气缸终点  并且第二个气缸原点时
                       {
                                                                          out2=0;  // 驱动第二个气缸
                  g=0;     //驱动下一个动作
                   f=1;  //复位f(相当于复位自锁一样)
                   }
             }
                         if(g==0)
                                                                  {
if(zhong_dian2==0)//第二个气缸终点
              {
  out2=1;//复位第二个气缸
   h=0; //驱动下一个动作
             g=1; //复位g(相当于复位自锁一样)
     }
             }
             if(h==0)
  {
                    if(yuan_dian2==0)//返回第二个气缸原点时
                            {
                                                                                                out1=1;//复位第一个气缸
                                            i=0;   //驱动下一个动作
                                                      h=1;  //复位h(相当于复位自锁一样)
           }
                    }
                                                        if(i==0)
         {
      if(yuan_dian1==0)//返回在第一个气缸原点时
                    {
                                                                                                 counter=0;//计数
                                                      delayms(30);
                                                                  counter=1;
delayms(10);
f=1;//复位
g=1;//复位
h=1;//复位
j=0;//驱动下一个动作
i=1;//复位
       
}
                                                           
}
                                                        if(j==0)
      {
     
  a=1;//复位  
                                                             
  }
     
        }
if(a==1)//复位总开关
{
n=1; //复位
j=1; //复位
}
}  
 
if(zi_dong==1) //手动部分
    {
        delayms(10);
    if(zi_dong==1) //消抖
   {
a=1; //复位自动部分的辅助线圈
                o=1; //复位自动部分的辅助线圈
n=1; //复位自动部分的辅助线圈
f=1; //复位自动部分的辅助线圈
g=1; //复位自动部分的辅助线圈
h=1; //复位自动部分的辅助线圈
i=1; //复位自动部分的辅助线圈
j=1; //复位自动部分的辅助线圈
                      o=1; //复位自动部分的辅助线圈
if(s==1)
   {
  out1=1;//运行手动前复位
  out2=1;//运行手动前复位
  s=0;
}
    if(hand1==0)
   {  
 delayms(10);
if(hand1==0)//消抖
                            {
       out1=~out1; //交替输出
while(!hand1);//等待释放按钮
  }
}
                  if(hand2==0)
  {
      delayms(10);
 if(hand2==0)//消抖
{
  out2=~out2;//交替输出
  while(!hand2);//等待释放按钮
}
}
}                        
           
}                                
}

}
 
void delayms(uint z)//延时部分
{
      uint k,m;  
  for(k=z;k>0;k--)
     for(m=110;m>0;m--);
}
void bao_jing_zhong1(void) //感应器报警部分1
{
  if(out1==0) //当第一个气缸动作时
     {
   delayms(e);
 if(zhong_dian1==1) //正常情况下此时终点1是等0的
     {
delayms(2000);//当延时2秒后还没有到终点则报警
if(zhong_dian1==1)
{
 beep=0; //  蜂鸣器响200ms
 delayms(200);
 beep=1;
 delayms(100);
}
             }
beep=1;//复位 蜂鸣器  
}
}
void bao_jing_zhong2(void) //感应器报警部分2
{
    if(out2==0)
   {
  delayms(e);
     if(zhong_dian2==1)
     {
     delayms(2000);
          if(zhong_dian2==1)
             {
                 beep=0;
                 delayms(200);
                             beep=1;
                 delayms(100);
             }
   }
 beep=1;    
}
}
void bao_jing_yuan1(void) //感应器报警部分3
{
if(out1==1)
{
       delayms(e);
    if(yuan_dian1==1)
           {
 delayms(2000);
 if(yuan_dian1==1)
    {
 beep=0;
 delayms(200);
 beep=1;
 delayms(100);
           }
                               
}
beep=1;
}
}
void bao_jing_yuan2(void) //感应器报警部分4
{
     if(out2==1)
 {
        delayms(e);
if(yuan_dian2==1)
delayms(2000);
    if(yuan_dian2==1)
{
      beep=0;
  delayms(200);
  beep=1;
  delayms(100);
}

  }
beep=1;
}
void reset(void)  //急停部分
{
    if(stop==0)
      {
    delayms(10);
  if(stop==0)
{
     out1=1;
 out2=1;
     (*((void(*)(void))0))(); //复位单片机
    }
  }
}
11-03-11 23:01
delayms()
函数用得太泛滥了,不行啊这样子......
能换成定时器的换定时器吧;
能换成累加的换累加吧;
能换成中断的换中断吧;
看到你延时那么多,一个循环下来就几秒了.....
这样的程序不能达到工艺要求的,程序在那里瞎循环做延时,其他的响应就死翘翘了....
11-03-11 23:55
谢谢指导~
11-03-12 00:21
逻辑控制中严禁使用delayms(10);等待消抖;
逻辑控制中严禁使用delayms(10);等待延时;
思路要用PLC的流水循环扫描控制思路;
消抖示例:
//按键使用流水扫描式消抖,
//严禁使用delay()延时判断消抖
/sbit KK1=P1_0
//bit K1;
//K1=1,表示按键按下,=0表示松开
if(KK1==0) {if(K1_XD>=200)K1=1;else K1_XD++;}//200个扫描周期
else {K1=0;K1_XD=0;}
if(K1==1)LED=~LED; //按下输出LED状态取反;
最好你的输入输出定义为PLC一样的X Y M,这样比较方便对照梯形图编程;
如:梯形图
LD X0
LD X1
OUT Y0
END
单片机动作程序:
void PLC_Task(void)
{    
        if(X0==0  && X1==0) Y0=0;         //如果X0与X1同时按下条件成立,Y0动作
            else Y0=1;                               //if条件不成立 Y0停止。
     
}
如:梯形图
LDI X0
OUT M1
LD M1
OUT Y0
END
单片机动作程序:
void PLC_Task(void)
{    
   if(X0==1)M1=0;                  //如果X0断开,辅助继电器M0动作
   else M1=1;                      //如果X0接通,辅助继电器M0复位
   if(M1==0)Y0=0;                 //如果辅助继电器M0动作,Y0输出动作。
   else Y0=1;                     //如果辅助继电器M0复位,Y0输出断开。
}
11-03-12 01:54
来个定时器的;
如:梯形图
LD X0
OUT T0 K15
LD T0
OUT Y0
LD X1
RST T0
END
单片机动作程序:
void PLC_Task(void)
{
 //虚拟定时器函数在单片机定时器中断中处理,这样不会影响逻辑控制速度
  if(X0==0) Time_Set(0,1,15);//虚拟定时器0打开,设定15
  if(T0==1)Y0=0;
  else        Y0=1;
  if(X0==0) Time_Set(0,0,0);//虚拟定时器0关闭,设定复位    
}
11-03-12 02:08
更正:if(X1==0) Time_Set(0,0,0);//虚拟定时器0关闭,设定复位
11-03-12 02:09
int a=1;
int e=10;
int f=1;
int g=1;
int h=1;
int i=1;  
int j=1;
int n=1;
int o=1;
int p=1;
int b=0;
int c=0;
int r=1;
int s=1;
int t=1;
这样定义占用很大的内存
如果是标志位可定义为bit类型;
如果是数据<255可定义单字节数据类型;
如:bit M0,M1,M2,M3,M4,M5,M6,M7,M8,M9;
11-03-12 02:12
按键使用扫描式消抖,
//严禁使用delay()延时判断消抖
/sbit KK1=P1_0
//bit K1;
//K1=1,表示按键按下,=0表示松开
if(KK1==0) {if(K1_XD>=200)K1=1;else K1_XD++;}//200个扫描周期
else   {K1=0;K1_XD=0;}
if(K1==1)LED=~LED; //按下输出LED状态取反
点子不错,真不是盖的! bit 可以定义成位  unsigned char 定义0~255 unsigned int 0~65535,非常欣赏yueliang150所说!
最后修改:2011/3/12 14:03:16
11-03-12 13:59
我是这样做的,在定时中定义了一个位,让它10MS倒转一次,主程序中只要对它记数就可以延时!
最后修改:2011/3/12 14:11:33
11-03-12 14:10
感谢各位高人指点~
在此,小弟我深感谢意!!
11-03-13 10:04

上一页下一页

工控新闻

更多新闻资讯