/**
|
******************************************************************************
|
* @file : PLCfunctions.c
|
* @brief : PLC funcstions program body
|
******************************************************************************
|
*/
|
//#include "globaldef.h"
|
#include "PLCfunctions.h"
|
#include "string.h"
|
#include "stm32f0xx_hal.h"
|
#include <core_cmInstr.h>
|
|
extern __IO uint32_t uwTick;
|
|
//unsigned short WDFs[TOTAL_WDFS];
|
|
inline unsigned int GetTick(void)
|
{
|
// unsigned short Clk1=SysTick->VAL;
|
return uwTick;
|
}
|
|
//unsigned char CurVAL;
|
//unsigned char CurVALs[TOTAL_CurVAL];
|
//stTimer Timers[TOTALTIMERS];
|
|
//unsigned short WX[13];
|
//unsigned short WY[13];
|
//unsigned short WR[64];
|
//unsigned short DT[256];
|
|
//unsigned short SDT[256];
|
|
stPLCMem PLCMem;
|
|
int InitTimer(int nIndex, int nType)
|
{
|
if (nIndex >= TOTALTIMERS) return -1;
|
PLCMem.Timers[nIndex].StatByte = 0x0010 | nType;
|
// Timers[nIndex].nType = 0;
|
PLCMem.Timers[nIndex].SV = 0;
|
PLCMem.Timers[nIndex].EV = 0;
|
PLCMem.Timers[nIndex].LastActTime = GetTick();
|
return 0;
|
}
|
|
int StartTimer(int nIndex , int SV)
|
{
|
if (nIndex >= TOTALTIMERS) return -1;
|
if (!PLCMem.Timers[nIndex].bSet)
|
{
|
PLCMem.Timers[nIndex].SV = SV;
|
PLCMem.Timers[nIndex].EV = 0;
|
PLCMem.Timers[nIndex].LastActTime = GetTick();
|
PLCMem.Timers[nIndex].bSet = 1;
|
}
|
return 0;
|
}
|
|
int StopTimer(int nIndex)
|
{
|
if (nIndex >= TOTALTIMERS) return -1;
|
if (PLCMem.Timers[nIndex].bSet)
|
{
|
PLCMem.Timers[nIndex].EV = 0;
|
PLCMem.Timers[nIndex].LastActTime = GetTick();
|
PLCMem.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();
|
return 0;
|
}
|
|
int SetTimerValue(int nIndex, int bSet, int SV)
|
{
|
if (nIndex >= TOTALTIMERS) return -1;
|
if (bSet) {StartTimer(nIndex, SV);}
|
else {StopTimer(nIndex);}
|
return PLCMem.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 (!PLCMem.Timers[nIndex].bTon)
|
{
|
int TimeDiff = GetTick() - PLCMem.Timers[nIndex].LastActTime;
|
int nScale = TICK_OF_MS;
|
if (PLCMem.Timers[nIndex].nScale == 0)
|
{nScale = TICK_OF_MS;
|
}else if (PLCMem.Timers[nIndex].nScale == 1)
|
{nScale = TICK_OF_RS;
|
}else if (PLCMem.Timers[nIndex].nScale == 2)
|
{nScale = TICK_OF_XS;
|
}else if (PLCMem.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;
|
|
if (NextEV >= PLCMem.Timers[nIndex].SV)
|
{
|
NextEV = PLCMem.Timers[nIndex].SV;
|
PLCMem.Timers[nIndex].bTon =1;
|
}
|
PLCMem.Timers[nIndex].EV = NextEV;
|
}
|
}
|
}else //bSet=0;
|
{
|
if(PLCMem.Timers[nIndex].bTon)
|
{
|
PLCMem.Timers[nIndex].bTon = 0;
|
}
|
}
|
return PLCMem.Timers[nIndex].bTon;
|
}
|
|
int IsTimerOn(int nIndex)
|
{
|
if (nIndex >= TOTALTIMERS) return 0;
|
ProcessTimer(nIndex);
|
return PLCMem.Timers[nIndex].bTon;
|
|
}
|
|
int GetTimerSV(int nIndex)
|
{
|
if (nIndex >= TOTALTIMERS) return 0;
|
// ProcessTimer(nIndex);
|
return PLCMem.Timers[nIndex].SV;
|
// return 0;
|
}
|
int GetTimerEV(int nIndex)
|
{
|
if (nIndex >= TOTALTIMERS) return 0;
|
// ProcessTimer(nIndex);
|
return PLCMem.Timers[nIndex].EV;
|
// 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--)
|
{
|
PLCMem.CurVALs[i]=PLCMem.CurVALs[i-1];
|
}
|
PLCMem.CurVALs[0]=PLCMem.CurVAL;
|
return PLCMem.CurVAL;
|
}
|
|
int PopOutVal(void)
|
{
|
unsigned char theVAL=PLCMem.CurVALs[0];
|
for (int i=0;i<TOTAL_CurVAL-1;i++)
|
{
|
PLCMem.CurVALs[i]=PLCMem.CurVALs[i+1];
|
}
|
return theVAL;
|
}
|
|
int ANS(int bValue)
|
{
|
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,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_POPS,0,0},
|
{OP_AN,Addr_Y,1},
|
{OP_TML,6,25},
|
{OP_RESET,Addr_Y,1},
|
{OP_SET,Addr_Y,2},
|
|
};
|
|
/*
|
|
{OP_ST,Addr_R,1},
|
{OP_PSHS,0,0},
|
{OP_AN_,Addr_Y,1},
|
{OP_TMR,5,200},
|
{OP_SET,Addr_Y,1},
|
{OP_POPS,0,0},
|
{OP_AN,Addr_Y,1},
|
{OP_TMR,6,200},
|
{OP_RESET,Addr_Y,1},
|
|
*/
|
int nSizeProg1=sizeof(prog1)/sizeof(stPLCPROG);
|
|
char * PLCPRG=
|
{
|
"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()
|
{
|
return 0;
|
}
|
|
unsigned char GetAddrValue(unsigned char AddrType, unsigned short Addr)
|
{
|
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;
|
}
|
int SetAddrValue(unsigned char AddrType, unsigned short Addr, unsigned char Value)
|
{
|
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;
|
}
|
int ProcessPLCPROG(const stPLCPROG * prog,int nSize)
|
{
|
for (int i=0;i<nSize;i++)
|
{
|
unsigned char thisOP=prog[i].OP;
|
unsigned char thisAddrType=prog[i].AddrType;
|
unsigned short thisAddr=prog[i].Addr;
|
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_NOT:
|
PLCMem.CurVAL = ! PLCMem.CurVAL;
|
break;
|
case OP_PSHS:
|
PushInVal();
|
break;
|
case OP_POPS:
|
PLCMem.CurVAL = PopOutVal();
|
break;
|
case OP_ANS:
|
PLCMem.CurVAL = PLCMem.CurVAL && PopOutVal();
|
break;
|
case OP_ORS:
|
PLCMem.CurVAL = PLCMem.CurVAL || PopOutVal();
|
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;
|
}
|
}
|
return 0;
|
}
|