QuakeGod
2022-01-16 326d3e312c74726814c39c9d112faab03c4a167c
提交 | 用户 | age
4b03ae 1 #pragma once
Q 2 /************************************************************************************
3 FPX PLC 通讯头文件
4 Version: V1.02
5 Date:    2015-06-30
6 Description;
7 2015-08-30 增加了模拟功能
8 1.03 2016-05-23
9 增加临界区
10
11 ************************************************************************************/
12 #include "omp.h"
13 #include "../SerialCom/SerialCom.hpp"
14 const unsigned short HexMask[16]=
15 {
16     0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80,
17     0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000
18 };
19 static inline int xtoi(const char * hexstr, int len=0)
20 {
21     int i,j,k;
22     unsigned char ch;
23     k=0;j=0;
24     int len1=(int)strlen(hexstr);
25     if (len>0) len1=len;
26     for (i=0;i<len1;i++)
27     {
28         ch=hexstr[i];
29         if (ch>='0'&&ch<='9')
30         {
31             k=ch-'0';
32             j=j*16+k;
33             continue;
34         }
35         if (ch>='A'&&ch<='F')
36         {
37             k=ch-'A'+10;
38             j=j*16+k;
39             continue;
40         }
41         if (ch>='a'&&ch<='f')
42         {
43             k=ch-'a'+10;
44             j=j*16+k;
45             continue;
46         }
47         if (ch==' '||ch=='    ')
48         {
49             continue;
50         }
51         break;
52     }
53     return j;
54 }
55 #pragma pack(push)
56 #pragma pack(2)
57 struct bitfield16 
58 {
59     short int b0:1;
60     short int b1:1;
61     short int b2:1;
62     short int b3:1;
63     short int b4:1;
64     short int b5:1;
65     short int b6:1;
66     short int b7:1;
67     short int b8:1;
68     short int b9:1;
69     short int ba:1;
70     short int bb:1;
71     short int bc:1;
72     short int bd:1;
73     short int be:1;
74     short int bf:1;
75 };
76 #pragma pack()
77 #pragma pack(pop)
78 class FPXPLC
79 {
80 public:
81     int Connected;
82     CSerialCom SerialPlc1;
83     int Station;
84     char buffer1[4000];
85     char buffer2[4000];
86     int SimFunc;        //模拟功能
87     int simresult1;        //模拟功能数值
88     CStringA LastRecvString;
89
90     double SendTimeMin;    //发送时间最小
91     double SendTimeMax;    //发送时间最大
92     double SendTimeCur;    //发送时间当前
93     double SendTimeAvg; //发送时间平均
94
95     double RecvTimeMin; //接收时间最小
96     double RecvTimeMax;    //接收时间最大
97     double RecvTimeCur;    //接收时间当前
98     double RecvTimeAvg;    //接收时间平均
99
100     double TransTimeMin;    //传输时间,最小
101     double TransTimeMax;    //传输时间最大
102     double TransTimeCur;    //传输时间当前
103     double TranstimeAvg;    //传输时间平均
104
105 #pragma pack(push)
106 #pragma pack(2)
107     union uPLCINFO
108     {
109         struct //stPLCINFO
110         {
111             char PlcType[2];
112             char Version[2];
113             char PrgSize[2];
114             char RunMode[2];
115             char LinkInfo[2];
116             char ErrMark[2];
117             char SelfTestInfo[4];
118         };
119         unsigned char bytes[16];
120     }InfoBytes;
121 #pragma pack()
122 #pragma pack(1)
123     struct stPLCINFO
124     {
125         unsigned char PlcType;
126         unsigned char Version;
127         unsigned char PrgSize;
128         union{
129             unsigned char RunMode;
130             struct 
131             {
132                 unsigned char Running:1;
133                 unsigned char Test:1;
134                 unsigned char BRK:1;
135                 unsigned char BRKALW:1;
136                 unsigned char ReFresh:1;
137                 unsigned char SigleStep:1;
138                 unsigned char MSG:1;
139                 unsigned char REM:1;
140             }stRunMode;
141         };
142         unsigned char LinkInfo;
143         union{
144             unsigned char Errs;
145             struct{
146                 unsigned char SelfTestErr:1;
147                 unsigned char PowerDown:1;
148                 unsigned char Fuse:1;
149                 unsigned char UnitErr:1;
150                 unsigned char IOChkErr:1;
151                 unsigned char BetteryErr:1;
152                 unsigned char BetteryErrKeep:1;
153                 unsigned char RunErr:1;
154             }stErrs;
155         };
156         unsigned short SelfTestInfo;
157     }PlcInfo;
158 #pragma pack()
159 #pragma pack(pop)
160     volatile bitfield16 * R;        //位访问
161     volatile short WX[110];        //WX0-WX109;
162     volatile short WY[110];        //WY0-WY109;
163     volatile short WL[128];        //WL0-WL127;
164     volatile short WR[256];        //WR0-WR255;
165     volatile short SWR[15];        //WR900-WR915;
166     volatile short DT[32768];    //DT0-DT32767;
167     volatile short SDT[512];    //DT90000-DT90499;
168     volatile short LD[256];        //LD0-LD255;
169
170     CCriticalSection myCriticalSection1;        //临界区
171
172     FPXPLC()
173     {
174         SimFunc=0;
175         R=(bitfield16 *)WR;
176         RecvTimeAvg=RecvTimeCur=RecvTimeMin=RecvTimeMax=0;
177         SendTimeAvg=SendTimeCur=SendTimeMin=SendTimeMax=0;
178         TranstimeAvg=TransTimeCur=TransTimeMin=TransTimeMax=0;
179
180     };
181     ~FPXPLC(){};
182     
183     int BCC(const char * value)
184     {
185         int i,j;
186         char k;
187         k=0;
188         j=(int)strlen(value);
189         for (i=0;i<j;i++)
190         {
191             k^=value[i];
192         }
193         return k;
194     }
195
196     int SendPLCData(const char * buffer, int n)
197     {
198         double time1=GetTimeMs();
199         SerialPlc1.Purge();
200         int j=SerialPlc1.Send(buffer,n);
201         double time2=GetTimeMs();
202         double dif=time2-time1;
203         if (SendTimeCur==0)
204         {
205             SendTimeCur=SendTimeMin=SendTimeMax=SendTimeAvg=dif;
206         }else
207         {
208             SendTimeCur=dif;
209             if (dif>SendTimeMax) {SendTimeMax=dif;}
210             if (dif<SendTimeMin) {SendTimeMin=dif;}
211             SendTimeAvg=SendTimeAvg*0.9+dif*0.1;
212         }
213         return j;
214     }
215
216     int ReadPLCCom(char * buffer, int n)
217     {
218         double time1=GetTimeMs();
219         int j=SerialPlc1.Read(buffer,n);
220         double time2=GetTimeMs();
221         double dif=time2-time1;
222         if (j>0)
223         {
224             buffer[j]=0;
225             LastRecvString=buffer;
226         }
227         if (RecvTimeCur==0)
228         {
229             RecvTimeCur=RecvTimeAvg=RecvTimeMax=RecvTimeMin=dif;
230         }else
231         {
232             RecvTimeCur=dif;
233             if (dif>RecvTimeMax) {RecvTimeMax=dif;}
234             if (dif<RecvTimeMin) {RecvTimeMin=dif;}
235             RecvTimeAvg=RecvTimeAvg*0.9+dif*0.1;
236         }
237         return j;
238     }
239     int Connect(int Station2=0)
240     {
241         int j;
242         j=SerialPlc1.Open();
243         if (j==1)
244         {//    RT(Station2);
245             Connected=1;
246             RecvTimeAvg=RecvTimeCur=RecvTimeMin=RecvTimeMax=0;
247             SendTimeAvg=SendTimeCur=SendTimeMin=SendTimeMax=0;
248             TranstimeAvg=TransTimeCur=TransTimeMin=TransTimeMax=0;
249         }
250         return j;
251     }
252     int DisConnect()
253     {
254         if (Connected)
255         {
256             SerialPlc1.Close();
257             Connected=0;
258         }
259         return 0;
260     }
261
262 //     /*
263 //     指令 功能描述
264 //*    RCS Read single point of contact information 读取单个触点的状态信息        X Y R L T C
265 //*    WCS Write single point of contact information 写入单个触点的状态信息          Y R L
266 //     RCP Read plural point of contact information 读取多个触点的状态信息
267 //     WCP Write plural point of contact information 写入多个触点的状态信息
268 //*    RCC Read word unit of contact information 读取字单位的触点的状态信息        X Y R L T C
269 //*    WCC Write word unit of contact information 写入字单位的触点的状态信息          Y R L
270 //     SC Preset word unit in contact area 预置字单位的触点
271 //
272 //*    RD Read data area 读取数据寄存器值    D L F
273 //*    WD Write data area 写入数据寄存器值    D L F
274 //     SD Preset of data area 预置数据寄存器值
275 // 
276 //     RS Read timer and counter set value area 读取定时器/计数器目标值
277 //     WS Write timer and counter set value area 写入定时器/计数器目标值
278 //     RK Read timer and counter elapsed value area 读取定时器/计数器经过值
279 //     WK Write timer and counter elapsed value area 写入定时器/计数器经过值
280 // 
281 //     MC Registration and reset of monitor contact 登录及复位监控触点
282 //     MD Registration and reset of monitor data 登录及复位监控数据
283 //     MG Monitor execution 执行监控
284 // 
285 //     RR Read system register 读取系统寄存器
286 //     WR Write system register 写入系统寄存器
287 // 
288 //*    RT Read Programmable Controller (PC) status 读取PLC 当前状态
289 //     RP Read program 读取程序
290 //     WP Write program 写入程序
291 //     RM Remote control (RUN/PROGRAM mode switching) 遥控(运行/编程模式切换)
292 //     AB Transmission abort command 传输终止指令
293 //     */
294     int RT(int Station2=0)
295     {
296         if (SimFunc)
297         {
298
299         }
300         if (!SerialPlc1.IsOpened) return 0;
301         int len;
302         CStringA s1;
303         int station3;
304         if (Station2==0) station3=Station;
305         else station3=Station2;
306         s1.Format("%%%02X#RT",station3);
307         s1.AppendFormat("%02X\r",(unsigned char)(BCC(s1)));
308         len=s1.GetLength();
309         myCriticalSection1.Lock(INFINITE);
310         SendPLCData(s1,len);
311         int j;
312         j=ReadPLCCom(buffer2,9+16);
313         myCriticalSection1.Unlock();
314         if (j>=9) 
315         {
316             buffer2[j]=0;
317             s1=buffer2;
318             for (int i=0;i<16;i++)
319             {
320                 InfoBytes.bytes[i]=buffer2[6+i];
321             }
322             PlcInfo.PlcType=xtoi(InfoBytes.PlcType,2);
323             PlcInfo.Version=xtoi(InfoBytes.Version,2);
324             PlcInfo.PrgSize=xtoi(InfoBytes.PrgSize,2);
325             PlcInfo.RunMode=xtoi(InfoBytes.RunMode,2);
326             PlcInfo.LinkInfo=xtoi(InfoBytes.LinkInfo,2);
327             PlcInfo.Errs=xtoi(InfoBytes.ErrMark,2);
328             PlcInfo.SelfTestInfo=xtoi(InfoBytes.SelfTestInfo,4);
329
330             return 1;
331         }
332         else
333         {
334             return 0;
335         }
336     }
337     int RCS(const char * typeaddr,int &value, int Station2=0) //RCS Read single point of contact information 读取单个触点的状态信息 X Y R L T C
338
339     {
340         if (SimFunc) 
341         {
342             myCriticalSection1.Lock(INFINITE);
343             CStringA stypeaddr;
344             stypeaddr=typeaddr;
345             CStringA type;
346             CStringA addr,Laddr,Raddr;
347             type=typeaddr[0];
348             addr="0000"+stypeaddr.Mid(1);
349             addr=addr.Right(4);
350             Laddr=addr.Left(3);
351             Raddr=addr.Right(1);
352             int Laddrv=atoi(Laddr);
353             int Raddrv=xtoi(Raddr);
354             if (type.MakeUpper()=="R")
355             {
356                 value=(WR[Laddrv]&HexMask[Raddrv]);
357                 simresult1=1;
358             }else {simresult1=0;}
359             myCriticalSection1.Unlock();
360             return simresult1;
361         }
362         if (!Connected) {return 0;}
363
364         CStringA stypeaddr;
365         stypeaddr=typeaddr;
366         CStringA type;
367         CStringA addr;
368         type=typeaddr[0];
369         addr="0000"+stypeaddr.Mid(1);
370         addr=addr.Right(4);
371         int len;
372         CStringA s1;
373         int station3;
374         if (Station2==0) station3=Station;
375         else station3=Station2;
376         s1.Format("%%%02X#RCS%c%s",station3,type[0],addr);
377         s1.AppendFormat("%02X\r",(unsigned char)(BCC(s1)));
378         len=s1.GetLength();
379         myCriticalSection1.Lock(INFINITE);
380         SendPLCData(s1,len);
381         int j;
382         j=ReadPLCCom(buffer2,9+2);
383         myCriticalSection1.Unlock();
384         if (j>=9) 
385         {
386             value=buffer2[6]-48;
387             return 1;
388         }
389         else
390         {
391             return 0;
392         }
393     }
394
395     int WCS(const char * typeaddr, int value)
396     {
397         if (SimFunc) 
398         {
399             myCriticalSection1.Lock(INFINITE);
400             CStringA stypeaddr;
401             stypeaddr=typeaddr;
402             CStringA type;
403             CStringA addr,Laddr,Raddr;
404             type=typeaddr[0];
405             addr="0000"+stypeaddr.Mid(1);
406             addr=addr.Right(4);
407             Laddr=addr.Left(3);
408             Raddr=addr.Right(1);
409             int Laddrv=atoi(Laddr);
410             int Raddrv=xtoi(Raddr);
411             if (type.MakeUpper()=="R")
412             {
413                 if (value)
414                 {
415                     WR[Laddrv]|=HexMask[Raddrv];
416
417                 }
418                 else
419                 {
420                     WR[Laddrv]&=~HexMask[Raddrv];
421                 }
422                 simresult1=1;
423             }else simresult1=0;
424             myCriticalSection1.Unlock();
425             return simresult1;
426         }
427
428         if (!Connected) {return 0;}
429         CStringA s1;
430         CStringA type;
431         CStringA addr;
432         CStringA stypeaddr;
433         stypeaddr=typeaddr;
434         type=typeaddr[0];
435         addr="0000"+stypeaddr.Mid(1);
436         addr=addr.Right(4);
437         s1.Format("%%%02X#WCS%C%s%1X",Station,type[0],addr,value);
438         s1.AppendFormat("%02X\r",(unsigned char)(BCC(s1)));
439         int len;
440         len=s1.GetLength();
441         myCriticalSection1.Lock(INFINITE);
442         SendPLCData(s1,len);
443         len=ReadPLCCom(buffer2,9+2);
444         myCriticalSection1.Unlock();
445         CString s1T;
446         if (len<9)
447         {
448             s1T.Format(_T("WCS faild\r\n"),type);
449             return 0;
450         }
451         return 1;
452     }
453
454
455     int RCC(const char * typeaddr,int count,short int value[])    //count 最大32
456     {
457         if (SimFunc)
458         {
459             myCriticalSection1.Lock(INFINITE);
460             CStringA stypeaddr,type,addr;
461             stypeaddr=typeaddr;
462             type=typeaddr[0];
463             addr=stypeaddr.Mid(1);
464             int addrv=atoi(addr);
465             if (type.MakeUpper()=="R")
466             {
467                 for (int i=0;i<count;i++)    {    value[i]=WR[i+addrv];    }
468             }else if (type.MakeUpper()=="X")
469             {
470                 for (int i=0;i<count;i++)    {    value[i]=WX[i+addrv];    }
471             }else if (type.MakeUpper()=="Y")
472             {
473                 for (int i=0;i<count;i++)    {    value[i]=WY[i+addrv];    }
474             }else if (type.MakeUpper()=="L")
475             {
476                 for (int i=0;i<count;i++)    {    value[i]=WL[i+addrv];    }
477             }
478             myCriticalSection1.Unlock();
479             return 1;
480         }
481         if (!Connected) {return 0;}
482         CStringA type;
483         int addr;
484         CStringA s1,s2;
485         type=typeaddr[0];
486         s1=typeaddr;
487         s1=s1.Mid(1);
488         CString s1T;
489         addr=atoi(s1);
490         if (count>32) {count=32;}
491
492         s1.Format("%%%02X#RCC%c%04d%04d",Station,type[0],addr,addr+count-1);
493         s1.AppendFormat("%02X\r",(unsigned char)(BCC(s1)));
494         int len=s1.GetLength();
495         myCriticalSection1.Lock(INFINITE);
496         SendPLCData(s1,len);
497         len=ReadPLCCom(s1.GetBuffer(512),9+count*4+1);
498         myCriticalSection1.Unlock();
499         s1.ReleaseBuffer(len);
500         int i;
501         if (len>9)
502         {
503             for (i=0;i<count;i++)
504             {
505                 value[i]=xtoi(s1.Mid(6+i*4,2))+xtoi(s1.Mid(8+i*4,2))*256;
506             }
507             s1T.Format(_T("RCC %c%d %d OK %dB \r\n"),type[0],addr,count,len);
508         }else
509         {
510             for (i=0;i<count;i++)
511             {
512                 value[i]=0;
513             }
514             return 0;
515         }
516         return    1;
517     }
518     int WCC(const char * typeaddr,int count,short int value[])
519     {
520         if (SimFunc)
521         {
522             myCriticalSection1.Lock(INFINITE);
523             CStringA stypeaddr,type,addr;
524             stypeaddr=typeaddr;
525             type=typeaddr[0];
526             addr=stypeaddr.Mid(1);
527             int addrv=atoi(addr);
528             if (type.MakeUpper()=="R")
529             {
530                 for (int i=0;i<count;i++)    {    WR[i+addrv]=value[i];    }
531             }else if (type.MakeUpper()=="X")
532             {
533                 for (int i=0;i<count;i++)    {    WX[i+addrv]=value[i];    }
534             }else if (type.MakeUpper()=="Y")
535             {
536                 for (int i=0;i<count;i++)    {    WY[i+addrv]=value[i];    }
537             }else if (type.MakeUpper()=="L")
538             {
539                 for (int i=0;i<count;i++)    {WL[i+addrv]=value[i];    }
540             }
541             myCriticalSection1.Unlock();
542             return 1;
543         }
544         if (!Connected) {return 0;}
545         CStringA type;
546         int addr;
547         CStringA s1,s2;
548         type=typeaddr[0];
549         s1=typeaddr;
550         s1=s1.Mid(1);
551         addr=atoi(s1);
552         int i;
553         s1.Empty();
554         unsigned char low,high;
555         CString s1T;
556         for (i=0;i<count;i++)
557         {
558             low=value[i]%256;high=((unsigned)value[i])/256;
559             s1.AppendFormat("%02X%02X",low,high);
560         }
561
562         s2.Format("%%%02X#WCC%c%04d%04d%s",Station,type[0],addr,addr+count-1,s1);
563         s2.AppendFormat("%02X\r",((unsigned char) (BCC(s2))));
564
565         int len=s2.GetLength();
566         myCriticalSection1.Lock(INFINITE);
567         SendPLCData(s2,len);
568         len=ReadPLCCom(s1.GetBuffer(512),9+2);
569         myCriticalSection1.Unlock();
570         s1.ReleaseBuffer(len);
571         if (len>0)
572         {
573         }else
574         {
575             s1T.Format(_T("WCC %c%d %d failed \r\n"),type[0],addr,count);
576         }
577         return    1;
578     }
579     int RD(const char * typeaddr,int count,short int value[])
580     {
581         if (SimFunc)
582         {
583             myCriticalSection1.Lock(INFINITE);
584             CStringA stypeaddr,type,addr;
585             stypeaddr=typeaddr;
586             type=typeaddr[0];
587             addr=stypeaddr.Mid(1);
588             int addrv=atoi(addr);
589             if (type.MakeUpper()=="D")
590             {
591                 if (addrv+count<32768)
592                 {
593                     for (int i=0;i<count;i++)    {    value[i]=DT[i+addrv];    }
594                 }
595                 else if (addrv>=90000)
596                 {
597                     for (int i=0;i<count;i++)    {value[i]=SDT[i+addrv-90000];}
598                 }
599                 else    {        }
600             }else if (type.MakeUpper()=="L")
601             {
602                 for (int i=0;i<count;i++){    value[i]=LD[i+addrv];}
603             }
604             myCriticalSection1.Unlock();
605             return 1;
606         }
607         if (!Connected) {return 0;}
608         CStringA type;
609         int addr;
610         CStringA s1,s2;
611         CString s1T;
612         type=typeaddr[0];
613         s1=typeaddr;
614         s1=s1.Mid(1);
615
616         addr=atoi(s1);
617         if (count>32) {count=32;}
618
619         s1.Format("%%%02X#RD%c%05d%05d",Station,type[0],addr,addr+count-1);
620         s1.AppendFormat("%02X\r",(unsigned char)BCC(s1));
621         int len=s1.GetLength();
622         myCriticalSection1.Lock(INFINITE);
623         SendPLCData(s1,len);
624         len=ReadPLCCom(s1.GetBuffer(512),9+count*4+1);
625         myCriticalSection1.Unlock();
626         s1.ReleaseBuffer(len);
627         if (len>9)
628         {
629             int i;
630             for (i=0;i<count&&i*4+9<=len;i++)
631             {
632                 value[i]=xtoi(s1.Mid(6+i*4,2))+xtoi(s1.Mid(8+i*4,2))*256;
633             }
634             for (;i<count;i++)    //剩余的。
635             {    value[i]=0;    }
636         }
637         else
638         {
639             for (int i=0;i<count;i++)    {    value[i]=0;    }
640             s1T.Format(_T("RD %c%d %d failed \r\n"),type[0],addr,count);
641             return 0;
642         }
643         return    1;
644     }
645     int WD(const char * typeaddr,int count,short int value[])
646     {
647         if (SimFunc)
648         {
649             myCriticalSection1.Lock(INFINITE);
650             CStringA stypeaddr,type,addr;
651             stypeaddr=typeaddr;
652             type=typeaddr[0];
653             addr=stypeaddr.Mid(1);
654             int addrv=atoi(addr);
655             if (type.MakeUpper()=="D")
656             {
657                 if (addrv+count<32768)
658                 {
659                     for (int i=0;i<count;i++){DT[i+addrv]=value[i];    }
660                 }else if (addrv>=90000)
661                 {
662                     for (int i=0;i<count;i++){    SDT[i+addrv-90000]=value[i];}
663                 }else{        }
664             } else if (type.MakeUpper()=="L")
665             {
666                 for (int i=0;i<count;i++){LD[i+addrv]=value[i];    }
667             }
668             myCriticalSection1.Unlock();
669             return 1;
670         }
671         if (!Connected) {return 0;}
672         CStringA type;
673         int addr;
674         CStringA s1,s2;
675         CString s1T;    
676         type=typeaddr[0];
677         s1=typeaddr;
678         s1=s1.Mid(1);
679         addr=atoi(s1);
680         int i;
681         s1.Empty();
682         unsigned char low,high;
683
684         for (i=0;i<count;i++)
685         {
686             low=value[i]%256;high=((unsigned)value[i])/256;
687             s1.AppendFormat("%02X%02X",low,high);
688         }
689
690         s2.Format("%%%02X#WD%c%05d%05d%s",Station,type[0],addr,addr+count-1,s1);
691         s2.AppendFormat("%02X\r",((unsigned char) (BCC(s2))));
692
693         int len=s2.GetLength();
694         myCriticalSection1.Lock(INFINITE);
695         SendPLCData(s2,len);
696         len=ReadPLCCom(s1.GetBuffer(512),9+2);
697         myCriticalSection1.Unlock();
698         s1.ReleaseBuffer(len);
699         if (len>0)    {    return 1;    }
700         else{
701             s1T.Format(_T("WD %c%d %d failed \r\n"),type[0],addr,count);
702             return 0;
703         }
704         return    1;
705     }
706 };
707
708