提交 | 用户 | age
|
bfc108
|
1 |
/**
|
Q |
2 |
******************************************************************************
|
|
3 |
* @file : PLCfunctions.c
|
|
4 |
* @brief : PLC funcstions program body
|
|
5 |
******************************************************************************
|
|
6 |
*/
|
|
7 |
//#include "globaldef.h"
|
|
8 |
#include "PLCfunctions.h"
|
|
9 |
#include "string.h"
|
|
10 |
#include "stm32f0xx_hal.h"
|
|
11 |
#include <core_cmInstr.h>
|
|
12 |
|
|
13 |
extern __IO uint32_t uwTick;
|
|
14 |
|
|
15 |
//unsigned short WDFs[TOTAL_WDFS];
|
|
16 |
|
|
17 |
inline unsigned int GetTick(void)
|
|
18 |
{
|
|
19 |
// unsigned short Clk1=SysTick->VAL;
|
|
20 |
return uwTick;
|
|
21 |
}
|
|
22 |
|
|
23 |
//unsigned char CurVAL;
|
|
24 |
//unsigned char CurVALs[TOTAL_CurVAL];
|
|
25 |
//stTimer Timers[TOTALTIMERS];
|
|
26 |
|
|
27 |
//unsigned short WX[13];
|
|
28 |
//unsigned short WY[13];
|
|
29 |
//unsigned short WR[64];
|
|
30 |
//unsigned short DT[256];
|
|
31 |
|
|
32 |
//unsigned short SDT[256];
|
|
33 |
|
|
34 |
stPLCMem PLCMem;
|
|
35 |
|
|
36 |
int InitTimer(int nIndex, int nType)
|
|
37 |
{
|
|
38 |
if (nIndex >= TOTALTIMERS) return -1;
|
|
39 |
PLCMem.Timers[nIndex].StatByte = 0x0010 | nType;
|
|
40 |
// Timers[nIndex].nType = 0;
|
|
41 |
PLCMem.Timers[nIndex].SV = 0;
|
|
42 |
PLCMem.Timers[nIndex].EV = 0;
|
|
43 |
PLCMem.Timers[nIndex].LastActTime = GetTick();
|
|
44 |
return 0;
|
|
45 |
}
|
|
46 |
|
|
47 |
int StartTimer(int nIndex , int SV)
|
|
48 |
{
|
|
49 |
if (nIndex >= TOTALTIMERS) return -1;
|
|
50 |
if (!PLCMem.Timers[nIndex].bSet)
|
|
51 |
{
|
|
52 |
PLCMem.Timers[nIndex].SV = SV;
|
|
53 |
PLCMem.Timers[nIndex].EV = 0;
|
|
54 |
PLCMem.Timers[nIndex].LastActTime = GetTick();
|
|
55 |
PLCMem.Timers[nIndex].bSet = 1;
|
|
56 |
}
|
|
57 |
return 0;
|
|
58 |
}
|
|
59 |
|
|
60 |
int StopTimer(int nIndex)
|
|
61 |
{
|
|
62 |
if (nIndex >= TOTALTIMERS) return -1;
|
|
63 |
if (PLCMem.Timers[nIndex].bSet)
|
|
64 |
{
|
|
65 |
PLCMem.Timers[nIndex].EV = 0;
|
|
66 |
PLCMem.Timers[nIndex].LastActTime = GetTick();
|
|
67 |
PLCMem.Timers[nIndex].bSet = 0;
|
|
68 |
}
|
|
69 |
return 0;
|
|
70 |
}
|
|
71 |
int ResetTimer(int nIndex)
|
|
72 |
{
|
|
73 |
if (nIndex >= TOTALTIMERS) return -1;
|
|
74 |
PLCMem.Timers[nIndex].EV = 0;
|
|
75 |
PLCMem.Timers[nIndex].bTon = 0;
|
|
76 |
PLCMem.Timers[nIndex].LastActTime=GetTick();
|
|
77 |
return 0;
|
|
78 |
}
|
|
79 |
|
|
80 |
int SetTimerValue(int nIndex, int bSet, int SV)
|
|
81 |
{
|
|
82 |
if (nIndex >= TOTALTIMERS) return -1;
|
|
83 |
if (bSet) {StartTimer(nIndex, SV);}
|
|
84 |
else {StopTimer(nIndex);}
|
|
85 |
return PLCMem.Timers[nIndex].bTon;
|
|
86 |
}
|
|
87 |
|
|
88 |
int ProcessTimer(int nIndex)
|
|
89 |
{
|
|
90 |
if (nIndex >= TOTALTIMERS) return -1;
|
|
91 |
if (!PLCMem.Timers[nIndex].nInited) return 0;
|
|
92 |
if (PLCMem.Timers[nIndex].bSet) // bSet =1;
|
|
93 |
{
|
|
94 |
if (!PLCMem.Timers[nIndex].bTon)
|
|
95 |
{
|
|
96 |
int TimeDiff = GetTick() - PLCMem.Timers[nIndex].LastActTime;
|
|
97 |
int nScale = TICK_OF_MS;
|
|
98 |
if (PLCMem.Timers[nIndex].nScale == 0)
|
|
99 |
{nScale = TICK_OF_MS;
|
|
100 |
}else if (PLCMem.Timers[nIndex].nScale == 1)
|
|
101 |
{nScale = TICK_OF_RS;
|
|
102 |
}else if (PLCMem.Timers[nIndex].nScale == 2)
|
|
103 |
{nScale = TICK_OF_XS;
|
|
104 |
}else if (PLCMem.Timers[nIndex].nScale == 3)
|
|
105 |
{nScale = TICK_OF_YS;
|
|
106 |
}else {}
|
|
107 |
|
|
108 |
|
|
109 |
if (TimeDiff >= nScale)
|
|
110 |
{
|
|
111 |
int TimeDiffmS = TimeDiff / nScale;
|
|
112 |
unsigned short NextEV = PLCMem.Timers[nIndex].EV + TimeDiffmS;
|
|
113 |
PLCMem.Timers[nIndex].LastActTime += TimeDiffmS*nScale;
|
|
114 |
|
|
115 |
if (NextEV >= PLCMem.Timers[nIndex].SV)
|
|
116 |
{
|
|
117 |
NextEV = PLCMem.Timers[nIndex].SV;
|
|
118 |
PLCMem.Timers[nIndex].bTon =1;
|
|
119 |
}
|
|
120 |
PLCMem.Timers[nIndex].EV = NextEV;
|
|
121 |
}
|
|
122 |
}
|
|
123 |
}else //bSet=0;
|
|
124 |
{
|
|
125 |
if(PLCMem.Timers[nIndex].bTon)
|
|
126 |
{
|
|
127 |
PLCMem.Timers[nIndex].bTon = 0;
|
|
128 |
}
|
|
129 |
}
|
|
130 |
return PLCMem.Timers[nIndex].bTon;
|
|
131 |
}
|
|
132 |
|
|
133 |
int IsTimerOn(int nIndex)
|
|
134 |
{
|
|
135 |
if (nIndex >= TOTALTIMERS) return 0;
|
|
136 |
ProcessTimer(nIndex);
|
|
137 |
return PLCMem.Timers[nIndex].bTon;
|
|
138 |
|
|
139 |
}
|
|
140 |
|
|
141 |
int GetTimerSV(int nIndex)
|
|
142 |
{
|
|
143 |
if (nIndex >= TOTALTIMERS) return 0;
|
|
144 |
// ProcessTimer(nIndex);
|
|
145 |
return PLCMem.Timers[nIndex].SV;
|
|
146 |
// return 0;
|
|
147 |
}
|
|
148 |
int GetTimerEV(int nIndex)
|
|
149 |
{
|
|
150 |
if (nIndex >= TOTALTIMERS) return 0;
|
|
151 |
// ProcessTimer(nIndex);
|
|
152 |
return PLCMem.Timers[nIndex].EV;
|
|
153 |
// return 0;
|
|
154 |
}
|
|
155 |
const unsigned short bitMasks[16]=
|
|
156 |
{
|
|
157 |
0x1<<0,
|
|
158 |
0x1<<1,
|
|
159 |
0x1<<2,
|
|
160 |
0x1<<3,
|
|
161 |
0x1<<4,
|
|
162 |
0x1<<5,
|
|
163 |
0x1<<6,
|
|
164 |
0x1<<7,
|
|
165 |
0x1<<8,
|
|
166 |
0x1<<9,
|
|
167 |
0x1<<10,
|
|
168 |
0x1<<11,
|
|
169 |
0x1<<12,
|
|
170 |
0x1<<13,
|
|
171 |
0x1<<14,
|
|
172 |
0x1<<15,
|
|
173 |
|
|
174 |
};
|
|
175 |
|
|
176 |
inline void SetAddrBit(unsigned short * pW, unsigned char bitAddr)
|
|
177 |
{
|
|
178 |
(*pW)|=bitMasks[bitAddr&0xf];
|
|
179 |
}
|
|
180 |
|
|
181 |
inline void ResetBit(unsigned short * pW, unsigned char bitAddr)
|
|
182 |
{
|
|
183 |
(*pW)&=~bitMasks[bitAddr&0xf];
|
|
184 |
}
|
|
185 |
|
|
186 |
static inline void SetBitValue(unsigned short * pW, unsigned char bitAddr, unsigned char Value)
|
|
187 |
{
|
|
188 |
if (Value) { SetAddrBit(pW, bitAddr);}
|
|
189 |
else {ResetBit(pW, bitAddr);}
|
|
190 |
}
|
|
191 |
|
|
192 |
static inline unsigned char GetBitValue(unsigned short W, unsigned char bitAddr)
|
|
193 |
{
|
|
194 |
if (W&bitMasks[bitAddr&0xf]) return 1;
|
|
195 |
else return 0;
|
|
196 |
}
|
|
197 |
|
|
198 |
int InitAllDFs()
|
|
199 |
{
|
|
200 |
for (int i=0;i<TOTAL_WDFS;i++)
|
|
201 |
{
|
|
202 |
PLCMem.WDFs[i]=0;
|
|
203 |
}
|
|
204 |
return TOTAL_WDFS;
|
|
205 |
}
|
|
206 |
|
|
207 |
int IsDF(int nIndex, int bSet)
|
|
208 |
{
|
|
209 |
unsigned short addr1 = (nIndex&0xff0)>>4;
|
|
210 |
unsigned char bitAddr=nIndex&0xf;
|
|
211 |
|
|
212 |
if (addr1 >= TOTAL_WDFS) return 0;
|
|
213 |
if (!GetBitValue( PLCMem.WDFs[addr1],bitAddr) && bSet)
|
|
214 |
{
|
|
215 |
SetBitValue(&PLCMem.WDFs[addr1],bitAddr,1);
|
|
216 |
return 1;
|
|
217 |
}else
|
|
218 |
{
|
|
219 |
SetBitValue(&PLCMem.WDFs[addr1],bitAddr,bSet);
|
|
220 |
}
|
|
221 |
return 0;
|
|
222 |
}
|
|
223 |
|
|
224 |
int PushInVal(void)
|
|
225 |
{
|
|
226 |
for (int i=TOTAL_CurVAL;i>0;i--)
|
|
227 |
{
|
|
228 |
PLCMem.CurVALs[i]=PLCMem.CurVALs[i-1];
|
|
229 |
}
|
|
230 |
PLCMem.CurVALs[0]=PLCMem.CurVAL;
|
|
231 |
return PLCMem.CurVAL;
|
|
232 |
}
|
|
233 |
|
|
234 |
int PopOutVal(void)
|
|
235 |
{
|
|
236 |
unsigned char theVAL=PLCMem.CurVALs[0];
|
|
237 |
for (int i=0;i<TOTAL_CurVAL-1;i++)
|
|
238 |
{
|
|
239 |
PLCMem.CurVALs[i]=PLCMem.CurVALs[i+1];
|
|
240 |
}
|
|
241 |
return theVAL;
|
|
242 |
}
|
|
243 |
|
|
244 |
int ANS(int bValue)
|
|
245 |
{
|
|
246 |
return PLCMem.CurVAL;
|
|
247 |
}
|
|
248 |
int ORS(int bValue)
|
|
249 |
{
|
|
250 |
return PLCMem.CurVAL;
|
|
251 |
}
|
|
252 |
|
|
253 |
int ST(int nAddr)
|
|
254 |
{
|
|
255 |
return 0;
|
|
256 |
}
|
|
257 |
|
|
258 |
int AN(int nAddr)
|
|
259 |
{
|
|
260 |
return 0;
|
|
261 |
}
|
|
262 |
|
|
263 |
int OR(int nAddr)
|
|
264 |
{
|
|
265 |
return 0;
|
|
266 |
}
|
|
267 |
|
|
268 |
int AN_(int nAddr)
|
|
269 |
{
|
|
270 |
return 0;
|
|
271 |
}
|
|
272 |
|
|
273 |
int OR_(int nAddr)
|
|
274 |
{
|
|
275 |
return 0;
|
|
276 |
}
|
|
277 |
|
|
278 |
stPLCPROG const prog1[]= //__attribute__((at(0X8008000)))
|
|
279 |
{
|
|
280 |
{OP_ST,Addr_X,0},
|
|
281 |
{OP_OR,Addr_Y,0},
|
|
282 |
{OP_AN_,Addr_X,1},
|
|
283 |
{OP_OUT,Addr_Y,0},
|
|
284 |
|
|
285 |
{OP_ST,Addr_X,2},
|
|
286 |
{OP_SET,Addr_R,1},
|
|
287 |
{OP_ST,Addr_X,3},
|
|
288 |
{OP_RESET,Addr_R,1},
|
|
289 |
|
|
290 |
{OP_ST,Addr_R,1},
|
|
291 |
{OP_PSHS,0,0},
|
|
292 |
{OP_AN_,Addr_Y,1},
|
|
293 |
{OP_TML,5,25},
|
|
294 |
{OP_SET,Addr_Y,1},
|
|
295 |
{OP_RESET,Addr_Y,2},
|
|
296 |
|
|
297 |
{OP_POPS,0,0},
|
|
298 |
{OP_AN,Addr_Y,1},
|
|
299 |
{OP_TML,6,25},
|
|
300 |
{OP_RESET,Addr_Y,1},
|
|
301 |
{OP_SET,Addr_Y,2},
|
|
302 |
|
|
303 |
};
|
|
304 |
|
|
305 |
/*
|
|
306 |
|
|
307 |
{OP_ST,Addr_R,1},
|
|
308 |
{OP_PSHS,0,0},
|
|
309 |
{OP_AN_,Addr_Y,1},
|
|
310 |
{OP_TMR,5,200},
|
|
311 |
{OP_SET,Addr_Y,1},
|
|
312 |
{OP_POPS,0,0},
|
|
313 |
{OP_AN,Addr_Y,1},
|
|
314 |
{OP_TMR,6,200},
|
|
315 |
{OP_RESET,Addr_Y,1},
|
|
316 |
|
|
317 |
*/
|
|
318 |
int nSizeProg1=sizeof(prog1)/sizeof(stPLCPROG);
|
|
319 |
|
|
320 |
char * PLCPRG=
|
|
321 |
{
|
|
322 |
"ST X0\n\
|
|
323 |
AN X1\n\
|
|
324 |
ST Y0\n\
|
|
325 |
AN Y1\n\
|
|
326 |
ORS\n\
|
|
327 |
AN/ X2\n\
|
|
328 |
AN/ X3\n\
|
|
329 |
OT Y0\n\
|
|
330 |
OT Y1\n\
|
|
331 |
"
|
|
332 |
};
|
|
333 |
|
|
334 |
int InitPLCPROGStat()
|
|
335 |
{
|
|
336 |
return 0;
|
|
337 |
}
|
|
338 |
|
|
339 |
unsigned char GetAddrValue(unsigned char AddrType, unsigned short Addr)
|
|
340 |
{
|
|
341 |
unsigned char thisValue;
|
|
342 |
unsigned short Addr1=(Addr&0xff0)>>4;
|
|
343 |
unsigned char bitAddr=Addr&0xf;
|
|
344 |
switch(AddrType)
|
|
345 |
{
|
|
346 |
case Addr_None:
|
|
347 |
break;
|
|
348 |
case Addr_X:
|
|
349 |
thisValue=GetBitValue( KMem.WX[Addr1],bitAddr);
|
|
350 |
break;
|
|
351 |
case Addr_Y:
|
|
352 |
thisValue=GetBitValue( KMem.WY[Addr1],bitAddr);
|
|
353 |
break;
|
|
354 |
case Addr_R:
|
|
355 |
thisValue=GetBitValue( KMem.WR[Addr1],bitAddr);
|
|
356 |
break;
|
|
357 |
case Addr_T:
|
|
358 |
thisValue=PLCMem.Timers[Addr].bTon;
|
|
359 |
break;
|
|
360 |
case Addr_L:
|
|
361 |
break;
|
|
362 |
default:
|
|
363 |
break;
|
|
364 |
}
|
|
365 |
return thisValue;
|
|
366 |
}
|
|
367 |
int SetAddrValue(unsigned char AddrType, unsigned short Addr, unsigned char Value)
|
|
368 |
{
|
|
369 |
unsigned short Addr1=(Addr&0xff0)>>4;
|
|
370 |
unsigned char bitAddr=Addr&0xf;
|
|
371 |
switch(AddrType)
|
|
372 |
{
|
|
373 |
case Addr_None:
|
|
374 |
break;
|
|
375 |
case Addr_X:
|
|
376 |
SetBitValue(&KMem.WX[Addr1],bitAddr,Value);
|
|
377 |
break;
|
|
378 |
case Addr_Y:
|
|
379 |
SetBitValue(&KMem.WY[Addr1],bitAddr,Value);
|
|
380 |
break;
|
|
381 |
case Addr_R:
|
|
382 |
SetBitValue(&KMem.WR[Addr1],bitAddr,Value);
|
|
383 |
break;
|
|
384 |
case Addr_T:
|
|
385 |
PLCMem.Timers[Addr].bTon=Value;
|
|
386 |
break;
|
|
387 |
case Addr_L:
|
|
388 |
break;
|
|
389 |
default:
|
|
390 |
break;
|
|
391 |
}
|
|
392 |
return Value;
|
|
393 |
}
|
|
394 |
int ProcessPLCPROG(const stPLCPROG * prog,int nSize)
|
|
395 |
{
|
|
396 |
for (int i=0;i<nSize;i++)
|
|
397 |
{
|
|
398 |
unsigned char thisOP=prog[i].OP;
|
|
399 |
unsigned char thisAddrType=prog[i].AddrType;
|
|
400 |
unsigned short thisAddr=prog[i].Addr;
|
|
401 |
switch (thisOP)
|
|
402 |
{
|
|
403 |
case OP_None:
|
|
404 |
break;
|
|
405 |
case OP_ST:
|
|
406 |
PushInVal();
|
|
407 |
PLCMem.CurVAL=GetAddrValue(thisAddrType, thisAddr);
|
|
408 |
break;
|
|
409 |
case OP_ST_:
|
|
410 |
PushInVal();
|
|
411 |
PLCMem.CurVAL=!GetAddrValue(thisAddrType, thisAddr);
|
|
412 |
break;
|
|
413 |
case OP_AN:
|
|
414 |
PLCMem.CurVAL = PLCMem.CurVAL&&GetAddrValue(thisAddrType, thisAddr);
|
|
415 |
break;
|
|
416 |
case OP_AN_:
|
|
417 |
PLCMem.CurVAL = PLCMem.CurVAL && (!GetAddrValue(thisAddrType, thisAddr));
|
|
418 |
break;
|
|
419 |
case OP_OR:
|
|
420 |
PLCMem.CurVAL = PLCMem.CurVAL || GetAddrValue(thisAddrType, thisAddr);
|
|
421 |
break;
|
|
422 |
case OP_OR_:
|
|
423 |
PLCMem.CurVAL = PLCMem.CurVAL || (!GetAddrValue(thisAddrType, thisAddr));
|
|
424 |
break;
|
|
425 |
case OP_NOT:
|
|
426 |
PLCMem.CurVAL = ! PLCMem.CurVAL;
|
|
427 |
break;
|
|
428 |
case OP_PSHS:
|
|
429 |
PushInVal();
|
|
430 |
break;
|
|
431 |
case OP_POPS:
|
|
432 |
PLCMem.CurVAL = PopOutVal();
|
|
433 |
break;
|
|
434 |
case OP_ANS:
|
|
435 |
PLCMem.CurVAL = PLCMem.CurVAL && PopOutVal();
|
|
436 |
break;
|
|
437 |
case OP_ORS:
|
|
438 |
PLCMem.CurVAL = PLCMem.CurVAL || PopOutVal();
|
|
439 |
break;
|
|
440 |
|
|
441 |
case OP_OUT:
|
|
442 |
SetAddrValue(thisAddrType,thisAddr,PLCMem.CurVAL);
|
|
443 |
break;
|
|
444 |
case OP_SET:
|
|
445 |
if (PLCMem.CurVAL) SetAddrValue(thisAddrType,thisAddr,1);
|
|
446 |
break;
|
|
447 |
case OP_RESET:
|
|
448 |
if (PLCMem.CurVAL) SetAddrValue(thisAddrType,thisAddr,0);
|
|
449 |
break;
|
|
450 |
case OP_DF:
|
|
451 |
break;
|
|
452 |
case OP_TML:
|
|
453 |
if (!PLCMem.Timers[thisAddrType].nInited) InitTimer(thisAddrType,0);
|
|
454 |
if (PLCMem.CurVAL) StartTimer(thisAddrType,thisAddr);
|
|
455 |
else StopTimer(thisAddrType);
|
|
456 |
PLCMem.CurVAL = ProcessTimer(thisAddrType);
|
|
457 |
|
|
458 |
break;
|
|
459 |
case OP_TMR:
|
|
460 |
if (!PLCMem.Timers[thisAddrType].nInited) InitTimer(thisAddrType,1);
|
|
461 |
if (PLCMem.CurVAL) StartTimer(thisAddrType,thisAddr);
|
|
462 |
else StopTimer(thisAddrType);
|
|
463 |
PLCMem.CurVAL = ProcessTimer(thisAddrType);
|
|
464 |
|
|
465 |
break;
|
|
466 |
|
|
467 |
|
|
468 |
default:
|
|
469 |
break;
|
|
470 |
}
|
|
471 |
}
|
|
472 |
return 0;
|
|
473 |
}
|