设为首页收藏本站

腾控科技论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 7285|回复: 9

我写的PLC解释器

[复制链接]
steelen 发表于 2010-8-31 14:50:13 | 显示全部楼层 |阅读模式
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <bios.h>

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

/******* const *******/

#define   STEP_SIZE       2049     /* Step size */
#define   INPUT_SIZE      256      /* Input  size */
#define   OUTPUT_SIZE     256    /* Output  size */
#define   INNER_SIZE      256     /* Inner Relay  size */
#define   CNT_SIZE        64      /* Counter size */
#define   TMR_SIZE        64      /* Timer  size */
#define   DATA_SIZE       64      /* Data Size */
#define   SPECIAL_SIZE    512      /* Special relay  Size */
#define   LOAD            1

#define   CNT_TYPE        256
#define   TMR_TYPE        512
#define   BIT_TYPE        0
#define   BCD_TYPE        128
#define   CHR_TYPE        129
#define   INT_TYPE        130
#define   FLT_TYPE        132

/* #define   DADDR_SIZE    1024  */  /* increase for large programs */

#define   LINESIZE  121
#define   WORDSIZE  20

/*  Max Input 256, Output 256
    Inner Relay 256
    Counter 64 Timer 64
    DATA 64
    Special Relay 512
*/

typedef struct {
               int type;           /* Counter or Tmr */
               int control;        /* counter control */
               int input;          /* Input */
               int old_input;      /* Old Input */
               int output;        /* Output */
               int value;          /* counter */
               int reload;
               int tmr_stamp;
               char description [10] ;
               } OPR;

/******* type  *******/
/* OPRATOR
One Operator
--------------------------
    NOP
    END
    ANB
    ORB
-------------------------
   Two Operator

   RST   {Y|M|S|T|C}
   CJP,EJP {M}
   LD LDI { X|Y|M|S|T|C}
   ADD,ANI
   OR,ORI
---------------------------
   Three Operator

   OUT {Y|M|S}|{C,#CONSTANT|T,#CONSTANT}
   SET {Y|M|S}|{C,#CONSTANT|T,#CONSTANT}
*/

typedef enum {
   opclONE,                     /* reg operands r,s,t */
   opclTWO,                    /* reg r, mem d+s */
   opclTHREE                      /* reg r, int d+s */
   } OPCLASS;

typedef enum {
             opNOP ,
             opEND ,
             opORB ,
             opANB ,
             opSLIMIT,
             opLD  ,
             opLDI ,
             opAND ,
             opANI ,
             opOR ,
             opORI ,
             opRST ,
             opCJP ,
             opEJP ,
             opDLIMIT,
             opOUT ,
             opSET,
             opTLIMIT
           } OPCODE;

typedef enum {
   srOKAY,
   srHALT,
   srIMEM_ERR,
   srDMEM_ERR,
   srZERODIVIDE
            } STEPRESULT;

typedef struct {
      int iop  ;
      OPR *iarg1  ;
      int iarg2  ;
      int iarg3  ;
              } INSTRUCTION;

OPR     input[INPUT_SIZE-1];   /* X00-X..*/             /* Input Point */
OPR     output[OUTPUT_SIZE-1]; /* Y00-Y.. */         /* Output Point */
OPR     inner[INNER_SIZE-1];   /* M00-M.. */
OPR     tmr[TMR_SIZE-1];       /* T00-T.. */
OPR     cnt[CNT_SIZE-1];       /* C00-C.. */
OPR     data[DATA_SIZE -1];    /* D00-D.. */
OPR     special[SPECIAL_SIZE-1]; /* S00-S.. */

int acc ;
int anb_stack[256];
int orb_stack[256];
int pc  ;


/******** vars ********/
int iloc = 0 ;
int dloc = 0 ;
int traceflag = FALSE;
int icountflag = FALSE;

INSTRUCTION iMem [STEP_SIZE];

char * opCodeTab[]
        = {
            "NOP" ,
            "END" ,
            "BOR" ,
            "BAN" ,
            "SLIM",
/*------------------------------------------------------*/
            "LD" ,
            "LDI" ,
            "AND" ,
            "ANI" ,
            "OR ",
            "ORI" ,
            "RST" ,
            "CJP" ,
            "EJP" ,
            "DLIM",
/*------------------------------------------------------*/
            "OUT" ,
            "SET" ,
            "TLIM"

           };

char * stepResultTab[]
        = {"OK",
            "Halted",
            "Instruction Memory Fault",
            "Data Memory Fault",
            "Division by 0"
          };

char pgmName[20];
FILE *pgm  ;

char in_Line[LINESIZE] ;
int lineLen ;
int inCol  ;
int num  ;
char word[WORDSIZE] ;
char ch  ;
int done  ;

/* ==================================== */

int opClass( int c )
{
  if      ( c <= opSLIMIT) return ( opclONE );
  else if ( c <= opDLIMIT) return ( opclTWO );
  else                    return ( opclTHREE);

} /* opClass */

/********************************************/
void writeInstruction ( int loc )
{
  printf( "%5d: ", loc) ;
  if ( (loc >= 0) && (loc < STEP_SIZE) )
    {
      printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
      switch ( opClass(iMem[loc].iop) )
    {
       case opclONE: printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
                   break;
      case opclTWO:
      case opclTHREE: printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
                   break;
    }
    printf ("\n") ;
  }
} /* writeInstruction */

/********************************************/
void getCh (void)
{
   if (++inCol < lineLen)
  ch = in_Line[inCol] ;
  else ch = ' ' ;
} /* getCh */

/********************************************/
int nonBlank (void)
{
  while ((inCol < lineLen)
         && (in_Line[inCol] == ' ') )
    inCol++ ;
  if (inCol < lineLen)
  {
   ch = in_Line[inCol] ;
    return TRUE ; }
  else
  {
    ch = ' ' ;
    return FALSE ; }
} /* nonBlank */

/********************************************/
int getNum (void)
{
  int sign;
  int term;
  int temp = FALSE;
  num = 0 ;
  do
  {
    sign = 1;
    while ( nonBlank() && ((ch == '+') || (ch == '-')) )
    {
      temp = FALSE ;
      if (ch == '-')  sign = - sign ;
      getCh();
    }
    term = 0 ;
    nonBlank();
    while (isdigit(ch))
    {
      temp = TRUE ;
      term = term * 10 + ( ch - '0' ) ;
      getCh();
    }
    num = num + (term * sign) ;
  } while ( (nonBlank()) && ((ch == '+') || (ch == '-')) ) ;
  return temp;
} /* getNum */

/********************************************/
int getWord (void)
{
  int temp = FALSE;
  int length = 0;
  if (nonBlank ())
  {
    while (isalnum(ch))
    {
    if (length < WORDSIZE-1) word [length++] =  ch ;
      getCh() ;
    }
    word[length] = '\0';
    temp = (length != 0);
  }
  return temp;
} /* getWord */

/********************************************/
int skipCh ( char c  )
{
  int temp = FALSE;
  if ( nonBlank() && (ch == c) )
  {
    getCh();
    temp = TRUE;
  }
  return temp;
} /* skipCh */

/********************************************/
int atEOL(void)
{
return ( ! nonBlank ());
} /* atEOL */

/********************************************/
int error( char * msg, int lineNo, int instNo)
{
  printf("Line %d",lineNo);
  if (instNo >= 0) printf(" (Instruction %d)",instNo);
  printf("   %s\n",msg);
  return FALSE;
} /* error */

int strnCmp( char * source,char *dest)
{
int char_lenth,result;
char_lenth=strlen(dest);
result=strncmp(source,dest,char_lenth) ;
return  result ;
}
/****************************/
OPR  *getVar(void)
{ int tmp ;
  OPR *var;
if (nonBlank()==TRUE )
{
   switch ((int)ch)
   {
    case 'X':
    case 'x':
    skipCh(ch);
    if (getNum())
      if((num>=0) && (num<=INPUT_SIZE-1)) var=&input[num];
    break;

    case 'Y':
    case 'y':
    skipCh(ch);
    if (getNum())
      if((num>=0) && (num<=OUTPUT_SIZE-1)) var=&output[num];
    break;

    case 'M':
    case 'm':
    skipCh(ch);
    if (getNum())
      if((num>=0) && (num<=INNER_SIZE-1)) var=&inner[num];
    break;

    case 'C':
    case 'c':
    skipCh(ch);
    if (getNum())
      if((num>=0) && (num<=CNT_SIZE-1)) var=&cnt[num];
    break;

    case 'T':
    case 't':
    skipCh(ch);
    if (getNum())
      if((num>=0) && (num<=TMR_SIZE-1)) var=&tmr[num];
    break;

    case 'D':
    case 'd':
    skipCh(ch);
    if (getNum())
      if((num>=0) && (num<=DATA_SIZE-1)) var=&data[num];
    break;

    case 'S':
    case 's':
    skipCh(ch);
    if (getNum())
      if((num>=0) && (num<=SPECIAL_SIZE-1)) var=&special[num];
    break;

    default:
    var=NULL;
   }
  return var;
}
return NULL;
}
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
 楼主| steelen 发表于 2010-8-31 14:50:33 | 显示全部楼层
/********************************************/
int readInstructions (void)
{
  OPCODE op;
  OPR * arg1;
  int arg2, arg3;
  int loc, regNo, lineNo;

  for (loc=0;loc<INPUT_SIZE-1;loc++)
  {
       input[loc].type=BIT_TYPE;
       input[loc].control=0;
       input[loc].input=0;
       input[loc].old_input=0;
       input[loc].output=0;
       input[loc].value=0;
       input[loc].reload=0;
       input[loc].tmr_stamp=0;
  }
  for (loc=0;loc<OUTPUT_SIZE-1;loc++)
  {
       output[loc].type=BIT_TYPE;
       output[loc].control=0;
       output[loc].input=0;
       output[loc].old_input=0;
       output[loc].output=0;
       output[loc].value=0;
       output[loc].reload=0;
       output[loc].tmr_stamp=0;
  }
  for (loc=0;loc<INNER_SIZE-1;loc++)
  {
       inner[loc].type=BIT_TYPE;
       inner[loc].control=0;
       inner[loc].input=0;
       inner[loc].old_input=0;
       inner[loc].output=0;
       inner[loc].value=0;
       inner[loc].reload=0;
       inner[loc].tmr_stamp=0;
  }
  for (loc=0;loc<CNT_SIZE-1;loc++)
  {
       cnt[loc].type=CNT_TYPE;
       cnt[loc].control=0;
       cnt[loc].input=0;
       cnt[loc].old_input=0;
       cnt[loc].output=0;
       cnt[loc].value=0;
       cnt[loc].reload=0;
       cnt[loc].tmr_stamp=0;
  }
  for (loc=0;loc<TMR_SIZE-1;loc++)
  {
       tmr[loc].type=TMR_TYPE;
       tmr[loc].control=0;
       tmr[loc].input=0;
       tmr[loc].old_input=0;
       tmr[loc].output=0;
       tmr[loc].value=0;
       tmr[loc].reload=0;
       tmr[loc].tmr_stamp=0;
  }
  for (loc=0;loc<DATA_SIZE-1;loc++)
  {
       data[loc].type=CNT_TYPE;
       data[loc].control=0;
       data[loc].input=0;
       data[loc].old_input=0;
       data[loc].output=0;
       data[loc].value=0;
       data[loc].reload=0;
       data[loc].tmr_stamp=0;
   }
  for (loc=0;loc<SPECIAL_SIZE-1;loc++)
  {
       special[loc].type=BIT_TYPE;
       special[loc].control=0;
       special[loc].input=0;
       special[loc].old_input=0;
       special[loc].output=0;
       special[loc].value=0;
       special[loc].reload=0;
       special[loc].tmr_stamp=0;
  }
  for (loc = 0 ; loc < STEP_SIZE-2 ; loc++)             /*  Instruction<=NOP */
  {
    iMem[loc].iop = opNOP ;
    iMem[loc].iarg1 = NULL;
    iMem[loc].iarg2 = 0 ;
    iMem[loc].iarg3 = 0 ;
  }
    iMem[loc].iop=opEND;                                 /* THE LAST INSTRUCTION MUST BE END*/

  lineNo = 0 ;
  loc= -1;
  while (! feof(pgm))
  {
    fgets( in_Line, LINESIZE-2, pgm  ) ;
    inCol = 0 ;
    lineNo++;
    lineLen = strlen(in_Line)-1 ;

    if (in_Line[lineLen]=='\n') in_Line[lineLen] = '\0' ;
    else in_Line[++lineLen] = '\0';

    if ( (nonBlank()) && (in_Line[inCol] != '*') )    /* Not Blank and Not for comment  */
    {
       loc++;

      if (loc > STEP_SIZE)
         return error("Location too large",lineNo,loc);

      if (! getWord ())
        return error("Missing opcode", lineNo,loc);

      op = opNOP ;

      while ((op < opTLIMIT)
             && (strnCmp(opCodeTab[op], word) != 0) )
          op++ ;

      if (strnCmp(opCodeTab[op], word) != 0)
          return error("Illegal opcode", lineNo,loc);

      switch ( opClass(op) )
      {
        case opclONE:
        arg1=NULL;
        arg2=NULL;
        arg3=NULL;
        break;

        case opclTWO :  /* LD X001 */
        arg1=getVar();
        arg2=NULL;
        arg3=NULL;
        break;

        case opclTHREE:  /* out T001,#25 */
        arg2=NULL;
        arg3=NULL;
        arg1=getVar();
        if(nonBlank()&&skipCh(',')&&nonBlank() && skipCh('#'))        getNum();
        if(arg1->type==CNT_TYPE)
         {  arg1->value=0;
            arg1->reload=num;
            arg1->control=LOAD;
         }
        if (arg1->type==TMR_TYPE)
        {  arg1->value=num;
            arg1->reload=num;
            arg1->control=LOAD;
         }
        break;

      }

      iMem[loc].iop = op;
      iMem[loc].iarg1 = arg1;
      iMem[loc].iarg2 = 0;
      iMem[loc].iarg3 = 0;
    }
  }
  return TRUE;
} /* readInstructions */


/********************************************/
STEPRESULT step (void)
{

    return 1;
}
/********************************************/
int doCommand (void)
{  for ( ; ; )
  { switch(iMem[pc].iop)
    {
            case opNOP:
              pc++;
            break;

            case opEND:
             pc=0;
             acc=0;
            return TRUE;


            case opORB:
             pc++;
            break;

            case opANB:
             pc++;
            break;

            case opLD:
             acc= iMem[pc].iarg1->output;
             pc++;
            break;

            case opLDI:
             acc=~iMem[pc].iarg1->output;
             pc++;
            break;

            case opAND:
              acc=acc && iMem[pc].iarg1->output;
              pc++;
            break;

            case opANI:
              acc=acc && (~iMem[pc].iarg1->output);
              pc++;
            break;

            case opOR:
             acc=acc||iMem[pc].iarg1->output;
             pc++;
            break;

            case opORI:
             acc=acc||(~iMem[pc].iarg1->output);
             pc++;
            break;

            case opRST:
            pc++;
            break;

            case opCJP:
            pc++;
            break;

            case opEJP:
            pc++;
            break;

            case opDLIMIT:
            pc++;
            break;


            case opOUT:
            if(!iMem[pc].iarg1->type)
            {
             iMem[pc].iarg1->output=acc;
             pc++;
            }
            else
            { iMem[pc].iarg1->input=acc;
              pc++;
            }
            break;

            case opSET:
            iMem[pc].iarg1->output=acc;
            pc++;
            break;

            default:
            pc++;

        }

   }
} /* doCommand */

void cnt_process(void)

{
int i;

for (i=0;i<CNT_SIZE-1;i++)
{
     if (cnt[i].control==LOAD)
     {
     if( (cnt[i].input^cnt[i].old_input) && cnt[i].input)
       {
        if( cnt[i].value==cnt[i].reload)
        {
         cnt[i].value=1;
         cnt[i].output=1;
        }
        else
        { cnt[i].value++;
          cnt[i].output=0;
        }
       }
    }
}

}
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
 楼主| steelen 发表于 2010-8-31 14:51:18 | 显示全部楼层

PLC代码举例

LDI X211
OR  X001
OUT Y003
LDI X001
LDI M002
OUT M002
OUT C21 ,#33
OUT C00,#34
OUT c01,#16384
LDI  X001
OUT T1 ,#64
END
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
skymaxu 发表于 2011-10-25 09:28:19 | 显示全部楼层
能看懂的举手
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
zhangxiaorui 发表于 2011-10-25 10:52:27 | 显示全部楼层
看不懂啊~~~
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
小甜甜不理你 发表于 2011-10-26 12:37:43 | 显示全部楼层
看不懂:(
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
工控菜鸟 发表于 2020-8-2 22:44:08 | 显示全部楼层
确实不知道怎么玩啊!专家给普及一下
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
 楼主| steelen 发表于 2020-8-3 14:03:12 | 显示全部楼层
很多年前我写的
腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
 楼主| steelen 发表于 2020-8-3 14:04:36 | 显示全部楼层
【群主】腾控PLC/RTU()  14:18:29
@    独自等待 很多年前我写的

【群主】腾控PLC/RTU(56)  14:18:43
解释运行PLC IL指令的

【群主】腾控PLC/RTU()  14:19:50
和我们目前的PLC无关

腾控T919宽温以太网PLC上市,集成4路热电阻(PT100),同时集成8路DI,4路DO(晶体管输出),8路AI,3个串口
您需要登录后才可以回帖 登录 | 注册

本版积分规则

产品样机试用申请

QQ|小黑屋|手机版|Archiver|腾控科技|腾控科技 ( 京ICP备09109731号  

GMT+8, 2020-10-25 06:34 , Processed in 0.128651 second(s), 19 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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