| | |
| | | int InitTimer(int nIndex, int nType)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return -1;
|
| | | PLCMem.Timers[nIndex].StatByte = 0x0010 | nType;
|
| | | KMem.Timers[nIndex].StatByte = 0x0010 | nType;
|
| | | // Timers[nIndex].nType = 0;
|
| | | PLCMem.Timers[nIndex].SV = 0;
|
| | | PLCMem.Timers[nIndex].EV = 0;
|
| | | PLCMem.Timers[nIndex].LastActTime = GetTick();
|
| | | KMem.SV[nIndex] = 0;
|
| | | KMem.EV[nIndex] = 0;
|
| | | KMem.Timers[nIndex].LastActTime = GetTick();
|
| | | return 0;
|
| | | }
|
| | |
|
| | | int StartTimer(int nIndex , int SV)
|
| | | int RunTimer(int nIndex , int SV)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return -1;
|
| | | if (!PLCMem.Timers[nIndex].bSet)
|
| | | if (!KMem.Timers[nIndex].bSet)
|
| | | {
|
| | | PLCMem.Timers[nIndex].SV = SV;
|
| | | PLCMem.Timers[nIndex].EV = 0;
|
| | | PLCMem.Timers[nIndex].LastActTime = GetTick(); |
| | | PLCMem.Timers[nIndex].bSet = 1;
|
| | | KMem.SV[nIndex] = SV;
|
| | | KMem.EV[nIndex]= 0;
|
| | | KMem.Timers[nIndex].LastActTime = GetTick(); |
| | | KMem.Timers[nIndex].bSet = 1;
|
| | | }
|
| | | return 0;
|
| | | }
|
| | |
| | | int StopTimer(int nIndex)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return -1;
|
| | | if (PLCMem.Timers[nIndex].bSet)
|
| | | if (KMem.Timers[nIndex].bSet)
|
| | | {
|
| | | PLCMem.Timers[nIndex].EV = 0;
|
| | | PLCMem.Timers[nIndex].LastActTime = GetTick(); |
| | | PLCMem.Timers[nIndex].bSet = 0; |
| | | KMem.EV[nIndex] = 0;
|
| | | KMem.Timers[nIndex].LastActTime = GetTick(); |
| | | KMem.Timers[nIndex].bSet = 0; |
| | | }
|
| | | return 0;
|
| | | }
|
| | | int ResetTimer(int nIndex)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return -1;
|
| | | PLCMem.Timers[nIndex].EV = 0;
|
| | | PLCMem.Timers[nIndex].bTon = 0;
|
| | | PLCMem.Timers[nIndex].LastActTime=GetTick();
|
| | | KMem.EV[nIndex] = 0;
|
| | | KMem.Timers[nIndex].bTon = 0;
|
| | | KMem.Timers[nIndex].LastActTime=GetTick();
|
| | | return 0;
|
| | | }
|
| | |
|
| | | int SetTimerValue(int nIndex, int bSet, int SV)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return -1;
|
| | | if (bSet) {StartTimer(nIndex, SV);}
|
| | | if (bSet) {RunTimer(nIndex, SV);}
|
| | | else {StopTimer(nIndex);}
|
| | | return PLCMem.Timers[nIndex].bTon;
|
| | | return KMem.Timers[nIndex].bTon;
|
| | | }
|
| | |
|
| | | int ProcessTimer(int nIndex)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return -1;
|
| | | if (!PLCMem.Timers[nIndex].nInited) return 0;
|
| | | if (PLCMem.Timers[nIndex].bSet) // bSet =1;
|
| | | if (!KMem.Timers[nIndex].nInited) return 0;
|
| | | if (KMem.Timers[nIndex].bSet) // bSet =1;
|
| | | {
|
| | | if (!PLCMem.Timers[nIndex].bTon)
|
| | | if (!KMem.Timers[nIndex].bTon)
|
| | | {
|
| | | int TimeDiff = GetTick() - PLCMem.Timers[nIndex].LastActTime;
|
| | | int TimeDiff = GetTick() - KMem.Timers[nIndex].LastActTime;
|
| | | int nScale = TICK_OF_MS;
|
| | | if (PLCMem.Timers[nIndex].nScale == 0)
|
| | | if (KMem.Timers[nIndex].nScale == 0)
|
| | | {nScale = TICK_OF_MS;
|
| | | }else if (PLCMem.Timers[nIndex].nScale == 1)
|
| | | }else if (KMem.Timers[nIndex].nScale == 1)
|
| | | {nScale = TICK_OF_RS;
|
| | | }else if (PLCMem.Timers[nIndex].nScale == 2)
|
| | | }else if (KMem.Timers[nIndex].nScale == 2)
|
| | | {nScale = TICK_OF_XS;
|
| | | }else if (PLCMem.Timers[nIndex].nScale == 3)
|
| | | }else if (KMem.Timers[nIndex].nScale == 3)
|
| | | {nScale = TICK_OF_YS;
|
| | | }else {}
|
| | |
|
| | |
| | | if (TimeDiff >= nScale)
|
| | | {
|
| | | int TimeDiffmS = TimeDiff / nScale;
|
| | | unsigned short NextEV = PLCMem.Timers[nIndex].EV + TimeDiffmS;
|
| | | PLCMem.Timers[nIndex].LastActTime += TimeDiffmS*nScale;
|
| | | unsigned short NextEV = KMem.EV[nIndex] + TimeDiffmS;
|
| | | KMem.Timers[nIndex].LastActTime += TimeDiffmS*nScale;
|
| | |
|
| | | if (NextEV >= PLCMem.Timers[nIndex].SV) |
| | | if (NextEV >= KMem.SV[nIndex]) |
| | | {
|
| | | NextEV = PLCMem.Timers[nIndex].SV;
|
| | | PLCMem.Timers[nIndex].bTon =1;
|
| | | NextEV = KMem.SV[nIndex];
|
| | | KMem.Timers[nIndex].bTon =1;
|
| | | }
|
| | | PLCMem.Timers[nIndex].EV = NextEV;
|
| | | KMem.EV[nIndex] = NextEV;
|
| | | }
|
| | | }
|
| | | }else //bSet=0;
|
| | | {
|
| | | if(PLCMem.Timers[nIndex].bTon) |
| | | if(KMem.Timers[nIndex].bTon) |
| | | {
|
| | | PLCMem.Timers[nIndex].bTon = 0;
|
| | | KMem.Timers[nIndex].bTon = 0;
|
| | | }
|
| | | }
|
| | | return PLCMem.Timers[nIndex].bTon;
|
| | | SetCoilValue(KLCoilTypeT, nIndex, KMem.Timers[nIndex].bTon); |
| | | return KMem.Timers[nIndex].bTon;
|
| | | }
|
| | |
|
| | | int IsTimerOn(int nIndex)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return 0;
|
| | | ProcessTimer(nIndex);
|
| | | return PLCMem.Timers[nIndex].bTon;
|
| | | return KMem.Timers[nIndex].bTon;
|
| | |
|
| | | }
|
| | |
|
| | |
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return 0;
|
| | | // ProcessTimer(nIndex);
|
| | | return PLCMem.Timers[nIndex].SV;
|
| | | return KMem.SV[nIndex];
|
| | | // return 0;
|
| | | }
|
| | | int GetTimerEV(int nIndex)
|
| | | {
|
| | | if (nIndex >= TOTALTIMERS) return 0;
|
| | | // ProcessTimer(nIndex);
|
| | | return PLCMem.Timers[nIndex].EV;
|
| | | return KMem.EV[nIndex];
|
| | | // return 0;
|
| | | }
|
| | | const unsigned short bitMasks[16]=
|
| | | {
|
| | | 0x1<<0,
|
| | | 0x1<<1,
|
| | | 0x1<<2,
|
| | | 0x1<<3,
|
| | | 0x1<<4,
|
| | | 0x1<<5,
|
| | | 0x1<<6,
|
| | | 0x1<<7,
|
| | | 0x1<<8,
|
| | | 0x1<<9,
|
| | | 0x1<<10,
|
| | | 0x1<<11,
|
| | | 0x1<<12,
|
| | | 0x1<<13,
|
| | | 0x1<<14,
|
| | | 0x1<<15,
|
| | | |
| | | };
|
| | |
|
| | | inline void SetAddrBit(unsigned short * pW, unsigned char bitAddr)
|
| | | {
|
| | | (*pW)|=bitMasks[bitAddr&0xf];
|
| | | }
|
| | |
|
| | | inline void ResetBit(unsigned short * pW, unsigned char bitAddr)
|
| | | {
|
| | | (*pW)&=~bitMasks[bitAddr&0xf];
|
| | | }
|
| | |
|
| | | static inline void SetBitValue(unsigned short * pW, unsigned char bitAddr, unsigned char Value)
|
| | | {
|
| | | if (Value) { SetAddrBit(pW, bitAddr);}
|
| | | else {ResetBit(pW, bitAddr);}
|
| | | }
|
| | |
|
| | | static inline unsigned char GetBitValue(unsigned short W, unsigned char bitAddr)
|
| | | {
|
| | | if (W&bitMasks[bitAddr&0xf]) return 1;
|
| | | else return 0;
|
| | | }
|
| | |
|
| | | int InitAllDFs()
|
| | | {
|
| | | for (int i=0;i<TOTAL_WDFS;i++)
|
| | | {
|
| | | PLCMem.WDFs[i]=0;
|
| | | }
|
| | | return TOTAL_WDFS;
|
| | | }
|
| | |
|
| | | int IsDF(int nIndex, int bSet)
|
| | | {
|
| | | unsigned short addr1 = (nIndex&0xff0)>>4;
|
| | | unsigned char bitAddr=nIndex&0xf;
|
| | | |
| | | if (addr1 >= TOTAL_WDFS) return 0;
|
| | | if (!GetBitValue( PLCMem.WDFs[addr1],bitAddr) && bSet)
|
| | | {
|
| | | SetBitValue(&PLCMem.WDFs[addr1],bitAddr,1);
|
| | | return 1;
|
| | | }else
|
| | | {
|
| | | SetBitValue(&PLCMem.WDFs[addr1],bitAddr,bSet);
|
| | | }
|
| | | return 0;
|
| | | }
|
| | |
|
| | | int PushInVal(void)
|
| | | {
|
| | | for (int i=TOTAL_CurVAL;i>0;i--)
|
| | | for (int i=TOTAL_CurVAL -1 ;i>0;i--)
|
| | | {
|
| | | PLCMem.CurVALs[i]=PLCMem.CurVALs[i-1];
|
| | | KMem.CurVALs[i]=KMem.CurVALs[i-1];
|
| | | }
|
| | | PLCMem.CurVALs[0]=PLCMem.CurVAL;
|
| | | return PLCMem.CurVAL;
|
| | | KMem.CurVALs[0]=KMem.CurVAL;
|
| | | return KMem.CurVAL;
|
| | | }
|
| | |
|
| | | int PopOutVal(void)
|
| | | {
|
| | | unsigned char theVAL=PLCMem.CurVALs[0];
|
| | | unsigned char theVAL=KMem.CurVALs[0];
|
| | | for (int i=0;i<TOTAL_CurVAL-1;i++)
|
| | | {
|
| | | PLCMem.CurVALs[i]=PLCMem.CurVALs[i+1];
|
| | | KMem.CurVALs[i]=KMem.CurVALs[i+1];
|
| | | }
|
| | | return theVAL;
|
| | | }
|
| | |
|
| | | int ANS(int bValue)
|
| | | stBinProg1 const prog1[]= //__attribute__((at(0X8008000)))
|
| | | {
|
| | | return PLCMem.CurVAL;
|
| | | }
|
| | | int ORS(int bValue)
|
| | | {
|
| | | return PLCMem.CurVAL;
|
| | | }
|
| | |
|
| | | int ST(int nAddr)
|
| | | {
|
| | | return 0;
|
| | | }
|
| | |
|
| | | int AN(int nAddr)
|
| | | {
|
| | | return 0;
|
| | | }
|
| | |
|
| | | int OR(int nAddr)
|
| | | {
|
| | | return 0;
|
| | | }
|
| | |
|
| | | int AN_(int nAddr)
|
| | | {
|
| | | return 0;
|
| | | }
|
| | |
|
| | | int OR_(int nAddr)
|
| | | {
|
| | | return 0;
|
| | | }
|
| | |
|
| | | stPLCPROG const prog1[]= //__attribute__((at(0X8008000)))
|
| | | {
|
| | | {OP_ST,Addr_X,0},
|
| | | {OP_OR,Addr_Y,0},
|
| | | {OP_AN_,Addr_X,1},
|
| | | {OP_OUT,Addr_Y,0},
|
| | | {OP_ST,KLCoilTypeSR,13},
|
| | | {OP_MV,0,50}, {KLDataTypeDEC,KLDataTypeDT,1},
|
| | | {OP_MV,0,20}, {KLDataTypeDEC,KLDataTypeDT,2},
|
| | | {OP_MV,0,30}, {KLDataTypeDEC,KLDataTypeDT,3},
|
| | | {OP_MV,0,40}, {KLDataTypeDEC,KLDataTypeDT,4},
|
| | | {OP_SET,KLCoilTypeR,0},
|
| | | // {OP_SET,KLCoilTypeY,0},
|
| | |
|
| | | {OP_ST,Addr_X,2},
|
| | | {OP_SET,Addr_R,1},
|
| | | {OP_ST,Addr_X,3},
|
| | | {OP_RESET,Addr_R,1},
|
| | | |
| | | {OP_ST,Addr_R,1},
|
| | | {OP_PSHS,0,0}, |
| | | {OP_AN_,Addr_Y,1}, |
| | | {OP_TML,5,25},
|
| | | {OP_SET,Addr_Y,1}, |
| | | {OP_RESET,Addr_Y,2}, |
| | | {OP_ST,KLCoilTypeR,0},
|
| | | {OP_TMX,1,1}, {KLDataTypeDT,0,0},
|
| | | {OP_DF},
|
| | | {OP_SET,KLCoilTypeR,10},
|
| | | |
| | | {OP_ST,KLCoilTypeX,0},
|
| | | {OP_DF},
|
| | | {OP_SET,KLCoilTypeR,10},
|
| | |
|
| | | {OP_POPS,0,0},
|
| | | {OP_AN,Addr_Y,1},
|
| | | {OP_TML,6,25},
|
| | | {OP_RESET,Addr_Y,1},
|
| | | {OP_SET,Addr_Y,2},
|
| | | {OP_ST,KLCoilTypeX,1},
|
| | | {OP_DF},
|
| | | {OP_RESET,KLCoilTypeR,10},
|
| | | /* |
| | | {OP_ST,KLCoilTypeR,10},
|
| | | {OP_AN,KLCoilTypeR,51}, |
| | | {OP_AN,KLCoilTypeR,52}, |
| | | {OP_AN,KLCoilTypeR,53}, |
| | | {OP_ADD3,0,21}, {KLDataTypeDT,KLDataTypeDT,31}, {0,KLDataTypeDT,32}, |
| | |
|
| | | {OP_ST,KLCoilTypeR,10},
|
| | | {OP_AN,KLCoilTypeR,54}, |
| | | {OP_AN,KLCoilTypeR,55}, |
| | | {OP_AN,KLCoilTypeR,56}, |
| | | {OP_ADD3,0,23}, {KLDataTypeDT,KLDataTypeDT,33}, {0,KLDataTypeDT,34}, |
| | | */
|
| | | {OP_ST,KLCoilTypeSR,1},
|
| | | {OP_PSHS}, |
| | | {OP_AN,KLCoilTypeR,51}, |
| | | {OP_OUT,KLCoilTypeY,1}, |
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,52}, |
| | | {OP_OUT,KLCoilTypeY,2}, |
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,53}, |
| | | {OP_OUT,KLCoilTypeY,3}, |
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,54}, |
| | | {OP_OUT,KLCoilTypeY,4}, |
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,55}, |
| | | {OP_OUT,KLCoilTypeY,5}, |
| | | {OP_POPS}, |
| | | {OP_AN,KLCoilTypeR,56}, |
| | | {OP_OUT,KLCoilTypeY,6}, |
| | |
|
| | | {OP_ST,KLCoilTypeR,10},
|
| | | {OP_DF},
|
| | | {OP_PSHS}, |
| | | {OP_MV,0,150}, {KLDataTypeDEC,KLDataTypeDT,11},
|
| | | {OP_MV,0,30}, {KLDataTypeDEC,KLDataTypeDT,12},
|
| | | {OP_RDS}, |
| | | {OP_MV,0,150}, {KLDataTypeDEC,KLDataTypeDT,13},
|
| | | {OP_MV,0,30}, {KLDataTypeDEC,KLDataTypeDT,14},
|
| | | {OP_POPS}, |
| | | {OP_AN_,KLCoilTypeR,11}, |
| | | {OP_AN_,KLCoilTypeR,12}, |
| | | {OP_AN_,KLCoilTypeR,13}, |
| | | {OP_AN_,KLCoilTypeR,14}, |
| | | {OP_SET,KLCoilTypeR,14},
|
| | |
|
| | | {OP_ST,KLCoilTypeR,10},
|
| | | {OP_PSHS}, |
| | | {OP_AN,KLCoilTypeR,11}, |
| | | {OP_DF},
|
| | | {OP_SET,KLCoilTypeR,51},
|
| | | {OP_RESET,KLCoilTypeR,52},
|
| | | {OP_RESET,KLCoilTypeR,53},
|
| | | {OP_RESET,KLCoilTypeR,54},
|
| | | {OP_RESET,KLCoilTypeR,55},
|
| | | {OP_SET,KLCoilTypeR,56},
|
| | |
|
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,11}, |
| | |
|
| | | {OP_PSHS}, |
| | | {OP_TMX,11,11}, {KLDataTypeDT,0,0},
|
| | | {OP_RESET,KLCoilTypeR,11},
|
| | | {OP_SET,KLCoilTypeR,12},
|
| | | {OP_POPS},
|
| | | {OP_SUB3,0,11}, {KLDataTypeSV,KLDataTypeEV,11}, {0,KLDataTypeDT,21}, |
| | | {OP_AN_LE,0,21},{KLDataTypeDT,KLDataTypeDEC,30},
|
| | | {OP_PSHS}, |
| | | {OP_DIV,0,21}, {KLDataTypeDT,KLDataTypeDEC,10}, {0,KLDataTypeDT,31}, |
| | | {OP_RDS}, |
| | | {OP_AN_GE,0,32},{KLDataTypeDT,KLDataTypeDEC,5},
|
| | | {OP_SET,KLCoilTypeR,51},
|
| | | {OP_POPS},
|
| | | {OP_AN_LT,0,32},{KLDataTypeDT,KLDataTypeDEC,5},
|
| | | {OP_RESET,KLCoilTypeR,51},
|
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,12}, |
| | | {OP_DF},
|
| | | {OP_RESET,KLCoilTypeR,51},
|
| | | {OP_SET,KLCoilTypeR,52},
|
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,12}, |
| | | {OP_TMX,12,12}, {KLDataTypeDT,0,0},
|
| | | {OP_RESET,KLCoilTypeR,12},
|
| | | {OP_SET,KLCoilTypeR,13},
|
| | | {OP_POPS},
|
| | | {OP_AN,KLCoilTypeR,12}, |
| | | {OP_OUT,KLCoilTypeR,52}, |
| | |
|
| | | {OP_ST,KLCoilTypeR,10},
|
| | | {OP_PSHS}, |
| | | {OP_AN,KLCoilTypeR,13}, |
| | | {OP_DF},
|
| | | {OP_RESET,KLCoilTypeR,52},
|
| | | {OP_SET,KLCoilTypeR,53},
|
| | | {OP_SET,KLCoilTypeR,54},
|
| | | {OP_RESET,KLCoilTypeR,56},
|
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,13}, |
| | | {OP_TMX,13,13}, {KLDataTypeDT,0,0},
|
| | | {OP_RESET,KLCoilTypeR,13},
|
| | | {OP_SET,KLCoilTypeR,14},
|
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,13}, |
| | | {OP_SUB3,0,13}, {KLDataTypeSV,KLDataTypeEV,13}, {0,KLDataTypeDT,23}, |
| | | {OP_AN_LE,0,23},{KLDataTypeDT,KLDataTypeDEC,30},
|
| | | {OP_PSHS}, |
| | | {OP_DIV,0,23}, {KLDataTypeDT,KLDataTypeDEC,10}, {0,KLDataTypeDT,33}, |
| | | {OP_RDS}, |
| | | {OP_AN_GE,0,34},{KLDataTypeDT,KLDataTypeDEC,5},
|
| | | {OP_SET,KLCoilTypeR,54},
|
| | | {OP_POPS},
|
| | | {OP_AN_LT,0,34},{KLDataTypeDT,KLDataTypeDEC,5},
|
| | | {OP_RESET,KLCoilTypeR,54},
|
| | | {OP_RDS}, |
| | | {OP_AN,KLCoilTypeR,14}, |
| | | {OP_DF},
|
| | | {OP_RESET,KLCoilTypeR,54},
|
| | | {OP_SET,KLCoilTypeR,55},
|
| | | {OP_POPS},
|
| | | {OP_AN,KLCoilTypeR,14}, |
| | | {OP_TMX,14,14}, {KLDataTypeDT,0,0},
|
| | | {OP_RESET,KLCoilTypeR,14},
|
| | | {OP_SET,KLCoilTypeR,11},
|
| | | };
|
| | |
|
| | | /*
|
| | |
| | | {OP_RESET,Addr_Y,1},
|
| | |
|
| | | */
|
| | | int nSizeProg1=sizeof(prog1)/sizeof(stPLCPROG);
|
| | | int nSizeProg1=sizeof(prog1)/sizeof(stBinProg1);
|
| | |
|
| | | char * PLCPRG=
|
| | | int InitPLC()
|
| | | {
|
| | | "ST X0\n\
|
| | | AN X1\n\
|
| | | ST Y0\n\
|
| | | AN Y1\n\
|
| | | ORS\n\
|
| | | AN/ X2\n\
|
| | | AN/ X3\n\
|
| | | OT Y0\n\
|
| | | OT Y1\n\
|
| | | "
|
| | | };
|
| | |
|
| | | int InitPLCPROGStat()
|
| | | {
|
| | | PLCMem.nScanCount=0;
|
| | | for (int i=0;i<1024;i++){PLCMem.ProgTrace[i]=0;}
|
| | | for (int i=0;i<16;i++) {
|
| | | KMem.WR[i]=0;
|
| | | }
|
| | | for (int i=0;i<256;i++) {
|
| | | KMem.DT[i]=0;
|
| | | }
|
| | | return 0;
|
| | | }
|
| | |
|
| | | unsigned char GetAddrValue(unsigned char AddrType, unsigned short Addr)
|
| | | int StartPLC()
|
| | | {
|
| | | unsigned char thisValue;
|
| | | unsigned short Addr1=(Addr&0xff0)>>4;
|
| | | unsigned char bitAddr=Addr&0xf;
|
| | | switch(AddrType)
|
| | | {
|
| | | case Addr_None:
|
| | | break;
|
| | | case Addr_X:
|
| | | thisValue=GetBitValue( KMem.WX[Addr1],bitAddr);
|
| | | break;
|
| | | case Addr_Y:
|
| | | thisValue=GetBitValue( KMem.WY[Addr1],bitAddr);
|
| | | break;
|
| | | case Addr_R:
|
| | | thisValue=GetBitValue( KMem.WR[Addr1],bitAddr);
|
| | | break;
|
| | | case Addr_T:
|
| | | thisValue=PLCMem.Timers[Addr].bTon;
|
| | | break;
|
| | | case Addr_L:
|
| | | break;
|
| | | default:
|
| | | break;
|
| | | } |
| | | return thisValue;
|
| | | PLCMem.nScanCount = 0;
|
| | | for (int i=0;i<1024;i++){PLCMem.ProgTrace[i]=0;}
|
| | | for (int i=0;i<16;i++) {
|
| | | KMem.WR[i]=0;
|
| | | }
|
| | | for (int i=0;i<256;i++) {
|
| | | KMem.DT[i]=0;
|
| | | }
|
| | | PLCMem.bPLCRunning=1;
|
| | | return 0;
|
| | | }
|
| | | int SetAddrValue(unsigned char AddrType, unsigned short Addr, unsigned char Value)
|
| | |
|
| | | int StopPLC()
|
| | | {
|
| | | unsigned short Addr1=(Addr&0xff0)>>4;
|
| | | unsigned char bitAddr=Addr&0xf;
|
| | | switch(AddrType)
|
| | | {
|
| | | case Addr_None:
|
| | | break;
|
| | | case Addr_X:
|
| | | SetBitValue(&KMem.WX[Addr1],bitAddr,Value);
|
| | | break;
|
| | | case Addr_Y:
|
| | | SetBitValue(&KMem.WY[Addr1],bitAddr,Value);
|
| | | break;
|
| | | case Addr_R:
|
| | | SetBitValue(&KMem.WR[Addr1],bitAddr,Value);
|
| | | break;
|
| | | case Addr_T:
|
| | | PLCMem.Timers[Addr].bTon=Value;
|
| | | break;
|
| | | case Addr_L:
|
| | | break;
|
| | | default:
|
| | | break;
|
| | | } |
| | | return Value;
|
| | | PLCMem.bPLCRunning=0;
|
| | | return 0;
|
| | | }
|
| | | int ProcessPLCPROG(const stPLCPROG * prog,int nSize)
|
| | |
|
| | | int ProcessPLCBinProg(const stBinProg1 * pBinprog, int nStepSize)
|
| | | {
|
| | | for (int i=0;i<nSize;i++)
|
| | | if (!PLCMem.bPLCRunning) return 0;
|
| | | |
| | | if (PLCMem.nScanCount == 0) {
|
| | | SetCoilValue(KLCoilTypeSR, 13, 1);
|
| | | SetCoilValue(KLCoilTypeSR, 0, 0);
|
| | | SetCoilValue(KLCoilTypeSR, 1, 1);
|
| | | }
|
| | | else
|
| | | {
|
| | | unsigned char thisOP=prog[i].OP;
|
| | | unsigned char thisAddrType=prog[i].AddrType;
|
| | | unsigned short thisAddr=prog[i].Addr;
|
| | | SetCoilValue(KLCoilTypeSR, 13, 0);
|
| | | SetCoilValue(KLCoilTypeSR, 0, 0);
|
| | | SetCoilValue(KLCoilTypeSR, 1, 1);
|
| | | }
|
| | | for (int i = 0; i < TOTAL_CurVAL; i++) {
|
| | | KMem.CurVALs[i] = 0;
|
| | | }
|
| | | int CurPos = 0;
|
| | | // stBinProg1 * pBinProg1;
|
| | | stBinProg15 * pBinProg15;
|
| | | stBinProg2 * pBinProg2;
|
| | | stBinProg3 * pBinProg3;
|
| | |
|
| | | int lastScanInputVal = 1;//??????,????????,? ?? ???
|
| | |
|
| | | while (CurPos < nStepSize)
|
| | | {
|
| | | unsigned int nNextPos = 1;
|
| | | unsigned int thisOP = pBinprog[CurPos].nOp;
|
| | | // unsigned int nParamCount = 0
|
| | | unsigned char thisAddrType = pBinprog[CurPos].nParamType;
|
| | | unsigned short thisAddr = pBinprog[CurPos].nParamAddr;
|
| | |
|
| | |
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_None:
|
| | | break;
|
| | | case OP_ST:
|
| | | PushInVal();
|
| | | PLCMem.CurVAL=GetAddrValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_ST_:
|
| | | PushInVal();
|
| | | PLCMem.CurVAL=!GetAddrValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_AN:
|
| | | PLCMem.CurVAL = PLCMem.CurVAL&&GetAddrValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_AN_:
|
| | | PLCMem.CurVAL = PLCMem.CurVAL && (!GetAddrValue(thisAddrType, thisAddr));
|
| | | break;
|
| | | case OP_OR:
|
| | | PLCMem.CurVAL = PLCMem.CurVAL || GetAddrValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_OR_:
|
| | | PLCMem.CurVAL = PLCMem.CurVAL || (!GetAddrValue(thisAddrType, thisAddr));
|
| | | break;
|
| | | // case OP_NONE:
|
| | | // break;
|
| | | case OP_NOP:
|
| | | break;
|
| | | //??? ??
|
| | | case OP_NOT:
|
| | | case OP_ANS:
|
| | | case OP_ORS:
|
| | | case OP_PSHS:
|
| | | case OP_RDS:
|
| | | case OP_POPS:
|
| | | case OP_DF:
|
| | | case OP_DF_:
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_NOT:
|
| | | PLCMem.CurVAL = ! PLCMem.CurVAL;
|
| | | KMem.CurVAL = !KMem.CurVAL;
|
| | | break;
|
| | | case OP_ANS:
|
| | | KMem.CurVAL = PopOutVal() && KMem.CurVAL;
|
| | | break;
|
| | | case OP_ORS:
|
| | | KMem.CurVAL = PopOutVal() || KMem.CurVAL;
|
| | | break;
|
| | | case OP_PSHS:
|
| | | PushInVal();
|
| | | break;
|
| | | case OP_RDS:
|
| | | KMem.CurVAL = KMem.CurVALs[0] != 0;
|
| | | break;
|
| | | case OP_POPS:
|
| | | PLCMem.CurVAL = PopOutVal();
|
| | | KMem.CurVAL = PopOutVal();
|
| | | break;
|
| | | case OP_ANS:
|
| | | PLCMem.CurVAL = PLCMem.CurVAL && PopOutVal();
|
| | | case OP_DF:
|
| | | KMem.CurVAL = KMem.CurVAL && !lastScanInputVal;
|
| | | break;
|
| | | case OP_ORS:
|
| | | PLCMem.CurVAL = PLCMem.CurVAL || PopOutVal();
|
| | | case OP_DF_:
|
| | | KMem.CurVAL = !KMem.CurVAL && lastScanInputVal;
|
| | | break;
|
| | |
|
| | | case OP_OUT:
|
| | | SetAddrValue(thisAddrType,thisAddr,PLCMem.CurVAL);
|
| | | break;
|
| | | case OP_SET:
|
| | | if (PLCMem.CurVAL) SetAddrValue(thisAddrType,thisAddr,1);
|
| | | break;
|
| | | case OP_RESET:
|
| | | if (PLCMem.CurVAL) SetAddrValue(thisAddrType,thisAddr,0);
|
| | | break;
|
| | | case OP_DF: |
| | | break;
|
| | | case OP_TML:
|
| | | if (!PLCMem.Timers[thisAddrType].nInited) InitTimer(thisAddrType,0);
|
| | | if (PLCMem.CurVAL) StartTimer(thisAddrType,thisAddr);
|
| | | else StopTimer(thisAddrType);
|
| | | PLCMem.CurVAL = ProcessTimer(thisAddrType);
|
| | | |
| | | break;
|
| | | case OP_TMR:
|
| | | if (!PLCMem.Timers[thisAddrType].nInited) InitTimer(thisAddrType,1);
|
| | | if (PLCMem.CurVAL) StartTimer(thisAddrType,thisAddr);
|
| | | else StopTimer(thisAddrType);
|
| | | PLCMem.CurVAL = ProcessTimer(thisAddrType);
|
| | | |
| | | break;
|
| | | |
| | | |
| | | default:
|
| | | break;
|
| | | }
|
| | | break;
|
| | | // 1????
|
| | | case OP_ST:
|
| | | case OP_ST_:
|
| | | case OP_AN:
|
| | | case OP_AN_:
|
| | | case OP_OR:
|
| | | case OP_OR_:
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_ST:
|
| | | PushInVal();
|
| | | KMem.CurVAL = GetCoilValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_ST_:
|
| | | PushInVal();
|
| | | KMem.CurVAL = !GetCoilValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_AN:
|
| | | KMem.CurVAL = KMem.CurVAL&&GetCoilValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_AN_:
|
| | | KMem.CurVAL = KMem.CurVAL && (!GetCoilValue(thisAddrType, thisAddr));
|
| | | break;
|
| | | case OP_OR:
|
| | | KMem.CurVAL = KMem.CurVAL || GetCoilValue(thisAddrType, thisAddr);
|
| | | break;
|
| | | case OP_OR_:
|
| | | KMem.CurVAL = KMem.CurVAL || (!GetCoilValue(thisAddrType, thisAddr));
|
| | | break;
|
| | | default:
|
| | | break;
|
| | | }
|
| | | break;
|
| | | // 1 ?? ??
|
| | | case OP_OUT:
|
| | | case OP_SET:
|
| | | case OP_RESET:
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_OUT:
|
| | | SetCoilValue(thisAddrType, thisAddr, KMem.CurVAL);
|
| | | break;
|
| | | case OP_SET:
|
| | | if (KMem.CurVAL) SetCoilValue(thisAddrType, thisAddr, 1);
|
| | | break;
|
| | | case OP_RESET:
|
| | | if (KMem.CurVAL) SetCoilValue(thisAddrType, thisAddr, 0);
|
| | | break;
|
| | | default:
|
| | | break;
|
| | | }
|
| | | break;
|
| | | // ????
|
| | | case OP_ST_EQ:
|
| | | case OP_ST_NE:
|
| | | case OP_ST_LT:
|
| | | case OP_ST_GT:
|
| | | case OP_ST_LE:
|
| | | case OP_ST_GE:
|
| | | case OP_AN_EQ:
|
| | | case OP_AN_NE:
|
| | | case OP_AN_LT:
|
| | | case OP_AN_GT:
|
| | | case OP_AN_LE:
|
| | | case OP_AN_GE:
|
| | | case OP_OR_EQ:
|
| | | case OP_OR_NE:
|
| | | case OP_OR_LT:
|
| | | case OP_OR_GT:
|
| | | case OP_OR_LE:
|
| | | case OP_OR_GE:
|
| | | pBinProg2 = (stBinProg2 *)&pBinprog[CurPos];
|
| | | thisAddrType = pBinProg2->nParamType1;
|
| | |
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_ST_EQ:
|
| | | PushInVal();
|
| | | KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) == GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_ST_NE:
|
| | | PushInVal();
|
| | | KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) != GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_ST_LT:
|
| | | PushInVal();
|
| | | KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) < GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_ST_GT:
|
| | | PushInVal();
|
| | | KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) > GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_ST_LE:
|
| | | PushInVal();
|
| | | KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) <= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_ST_GE:
|
| | | PushInVal();
|
| | | KMem.CurVAL = (GetVarData(thisAddrType, thisAddr) >= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_AN_EQ:
|
| | | KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) == GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_AN_NE:
|
| | | KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) != GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_AN_LT:
|
| | | KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) < GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_AN_GT:
|
| | | KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) > GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_AN_LE:
|
| | | KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) <= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_AN_GE:
|
| | | KMem.CurVAL = KMem.CurVAL && (GetVarData(thisAddrType, thisAddr) >= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | |
|
| | | case OP_OR_EQ:
|
| | | KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) == GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_OR_NE:
|
| | | KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) != GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_OR_LT:
|
| | | KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) < GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_OR_GT:
|
| | | KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) > GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_OR_LE:
|
| | | KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) <= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | | case OP_OR_GE:
|
| | | KMem.CurVAL = KMem.CurVAL || (GetVarData(thisAddrType, thisAddr) >= GetVarData(pBinProg2->nParamType2, pBinProg2->nParamAddr2));
|
| | | break;
|
| | |
|
| | | default:
|
| | | break;
|
| | | }
|
| | | nNextPos = 2;
|
| | | break;
|
| | | // ???
|
| | | case OP_TML:
|
| | | case OP_TMR:
|
| | | case OP_TMX:
|
| | | case OP_TMY:
|
| | | pBinProg15 = (stBinProg15 *)(&pBinprog[CurPos]);
|
| | | {
|
| | | unsigned char thisNum= pBinProg15->nOpNum;
|
| | | thisAddrType = pBinProg15->nParamType1;
|
| | | thisAddr = pBinProg15->nParamAddr1;
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_TML:
|
| | | if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 0);
|
| | | if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
|
| | | else StopTimer(thisNum);
|
| | | KMem.CurVAL = ProcessTimer(thisNum);
|
| | |
|
| | | break;
|
| | | case OP_TMR:
|
| | | if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 1);
|
| | | if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
|
| | | else StopTimer(thisNum);
|
| | | KMem.CurVAL = ProcessTimer(thisNum);
|
| | | break;
|
| | | case OP_TMX:
|
| | | if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 2);
|
| | | if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
|
| | | else StopTimer(thisNum);
|
| | | KMem.CurVAL = ProcessTimer(thisNum);
|
| | |
|
| | | break;
|
| | | case OP_TMY:
|
| | | if (!KMem.Timers[thisNum].nInited) InitTimer(thisNum, 3);
|
| | | if (KMem.CurVAL) RunTimer(thisNum, GetVarData(thisAddrType, thisAddr));
|
| | | else StopTimer(thisNum);
|
| | | KMem.CurVAL = ProcessTimer(thisNum);
|
| | | break;
|
| | | default:
|
| | | break;
|
| | | }
|
| | |
|
| | | }
|
| | | nNextPos = 2;
|
| | | break;
|
| | | // 1 ??????
|
| | | case OP_INC:
|
| | | case OP_DEC:
|
| | | pBinProg15 = (stBinProg15 *)(&pBinprog[CurPos]);
|
| | | thisAddrType = pBinProg15->nParamType1;
|
| | | thisAddr = pBinProg15->nParamAddr1;
|
| | | nNextPos = 2;
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_INC:
|
| | | if (KMem.CurVAL) SetVarData(thisAddrType, thisAddr, GetVarData(thisAddrType, thisAddr) + 1);
|
| | | break;
|
| | | case OP_DEC:
|
| | | if (KMem.CurVAL) SetVarData(thisAddrType, thisAddr, GetVarData(thisAddrType, thisAddr) - 1);
|
| | | break;
|
| | |
|
| | | default:
|
| | | break;
|
| | | }
|
| | | break;
|
| | | // 2??????
|
| | | case OP_MV:
|
| | | case OP_ADD2:
|
| | | case OP_SUB2:
|
| | | pBinProg2 = (stBinProg2 *)(&pBinprog[CurPos]);
|
| | | {
|
| | | int nParamType2, nParamAddr2;
|
| | | thisAddrType = pBinProg2->nParamType1;
|
| | | thisAddr = pBinProg2->nParamAddr1;
|
| | | nParamType2 = pBinProg2->nParamType2;
|
| | | nParamAddr2 = pBinProg2->nParamAddr2;
|
| | |
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_MV:
|
| | | if (KMem.CurVAL) SetVarData(nParamType2, nParamAddr2, GetVarData(thisAddrType, thisAddr));
|
| | | break;
|
| | | case OP_ADD2:
|
| | | if (KMem.CurVAL) SetVarData(nParamType2, nParamAddr2, GetVarData(thisAddrType, thisAddr) + GetVarData(nParamType2, nParamAddr2));
|
| | | break;
|
| | | case OP_SUB2:
|
| | | if (KMem.CurVAL) SetVarData(nParamType2, nParamAddr2, GetVarData(nParamType2, nParamAddr2) - GetVarData(thisAddrType, thisAddr));
|
| | | break;
|
| | |
|
| | | default:
|
| | | break;
|
| | | }
|
| | |
|
| | | }
|
| | | nNextPos = 2;
|
| | | break;
|
| | | // 3 ??????
|
| | | case OP_ADD3:
|
| | | case OP_SUB3:
|
| | | case OP_MUL:
|
| | | case OP_DIV:
|
| | | pBinProg3 = (stBinProg3 *)(&pBinprog[CurPos]);
|
| | | int nParamType2, nParamAddr2;
|
| | | int nParamType3, nParamAddr3;
|
| | | thisAddrType = pBinProg3->nParamType1;
|
| | | thisAddr = pBinProg3->nParamAddr1;
|
| | | nParamType2 = pBinProg3->nParamType2;
|
| | | nParamAddr2 = pBinProg3->nParamAddr2;
|
| | | nParamType3 = pBinProg3->nParamType3;
|
| | | nParamAddr3 = pBinProg3->nParamAddr3;
|
| | | switch (thisOP)
|
| | | {
|
| | | case OP_ADD3:
|
| | | if (KMem.CurVAL) SetVarData(nParamType3, nParamAddr3, GetVarData(thisAddrType, thisAddr) + GetVarData(nParamType2, nParamAddr2));
|
| | | break;
|
| | | case OP_SUB3:
|
| | | if (KMem.CurVAL) SetVarData(nParamType3, nParamAddr3, GetVarData(thisAddrType, thisAddr) - GetVarData(nParamType2, nParamAddr2));
|
| | | break;
|
| | | case OP_MUL:
|
| | | if (KMem.CurVAL) {
|
| | | short multiplicand = GetVarData(thisAddrType, thisAddr);
|
| | | short multiplier = GetVarData(nParamType2, nParamAddr2);
|
| | | int product = multiplicand * multiplier;
|
| | | SetVarData(nParamType3, nParamAddr3, product);
|
| | | SetVarData(nParamType3, nParamAddr3 + 1, product >> 16);
|
| | | }
|
| | | break;
|
| | | case OP_DIV:
|
| | | if (KMem.CurVAL) {
|
| | | short dividend = GetVarData(thisAddrType, thisAddr);
|
| | | short divisor = GetVarData(nParamType2, nParamAddr2);
|
| | | short quotient = dividend / divisor;
|
| | | short remainder = dividend % divisor;
|
| | | SetVarData(nParamType3, nParamAddr3, quotient);
|
| | | SetVarData(nParamType3, nParamAddr3 + 1, remainder);
|
| | | }
|
| | | break;
|
| | |
|
| | | default:
|
| | | break;
|
| | | }
|
| | | nNextPos = 3;
|
| | | break;
|
| | |
|
| | | default:
|
| | | break;
|
| | | }
|
| | |
|
| | | lastScanInputVal = PLCMem.ProgTrace[CurPos];
|
| | | PLCMem.ProgTrace[CurPos] = KMem.CurVAL;
|
| | | CurPos += nNextPos;
|
| | | }
|
| | | PLCMem.nScanCount++;
|
| | | return 0;
|
| | | }
|