C#与信捷PLC通讯.docx
实现C#与信捷P1.C通讯信捷P1.C在与PC通讯的时候,作为下位机,则上机必须按照MODBUSRTU的数据格式与其进行数据交换;下面为大家讲解相关使用:1、 什么是MOOBUSRT啾设?.MODBUSRTU的数据格式:请阅读Modbus协议中文版.pdf,通过这个介绍你会对MODBUS协议有所了解,其中还详细介绍了modbus通讯的另种模式一一MODBUSASCII模式,关于两者之间的区别,在此不再重复阐述,Modbus协议中文版.pdf上都有介绍,使用中清区分RTU和ASCII模式,不能笼统的认为使用的协议是MoDBUS协议。2、 MOOBUSRTIJ的数据格式:地址域功能码数据CRC或(1.RC)I例如:0106000100179804O1.060001(X)179804从机地址功能码数据地址数据CRC校验这一串数据的意思是:把数据OXoOI7(十进制23)写入1号从机地址OXOOOI数据地址。2.1功能码I功能码描述功能码描述:0x01读线圈状态0x05写单个线圈0x02读离散输入状态0x06写单个保持寄存器0x03读保持寄存器Ox1.O写多个保持寄存器0x04读输入寄存等OxOF写多个线圈2.2读寄存器:(0x03功能码)读取格式:地址I功能码I寄存器起始地址I寄存器数量CRCI6校殴Adrr0x03高8位低8位高8位低8位低8位高8位返回格式:地址I功能码I字节数I寄存器数据CRCI6校AdIT0x03NMX位低8位低8位高8位23写寄存器:(0x10功能码):写入格式:.地址I功能码I寄存叁起始地址I寄存叁数=I寄存叁数据CRCI6枚险AdrOxIO高8位低8位高8位低8位高8位低8位低8位高8位返回格式:地址I功能码I寄存器起始地址I寄存卷9ACRCI6校验AdrrOxIO高8位低8位裔8位低8位低8位高8位2.4示例发送:O1.0300010001D5CA从机地址功能号数据地址读取数据个数CRC校验那么P1.C接收到这串数据根据数据计算CRC校验判断数据是否正确,如果判断数据无误,则返回信息给主机:返回内容:O1.03020017F84A从机地址功能号数据字节个数数据CRC校验MoDBUS主机就完成了一次对从机P1.C数据的读操作,实现了通讯,3、核心代码usingSystem;usingSystcm.IO.Ports;usingSyStCm.Threading:namespaceSy1.ow1.y.Base(pub1.icc1.assP1.CHe1.perJpub1.icScria1.PortScrPortget;set:pub1.icintIntTimeOutget;set:)pub1.icstringStrPErrorget;set;)pub1.icP1.CHc1.pcr(Scria1.PortmscrPort.iumTinwOut)this.ScrPort=mscrPort;IhisJntTiineOut=m'ime0ut;)“CRC校验pub1.icbyte(JCRC1.6(bytebytData)(bytc11numArray=newbytcbytDgth+2;intmaxVa1.ue=(int)ushor.MaxVaIue;intnumI=40961;for(intindex1=0:index1<b>,tData.1.eneth:+index1)(maxVa1.ue=(int)bytDataindcx1.;for(intindex2=0:index2<8:+index2)(intnum2=maxVa1.ue&1;maxVa1.ue»=1;if(num2=I)maxVa1.ue=num1;J)Array.Copy(ay)bytData.0.(Array)nuni/Xrray.0.bytData.1.ength):numAr11ynumAray.1.ength-2=(byte)(maxVa1.ue&(int)bytc.MaxVa1.uc)numArraynunAay.1.ength-1=(byte)(maxVa1.ue»8);returnnumArray;pub1.icbyte11stringToBytes(stringStrVa1.ue)StrVaIue=st,Va1.ue.Rep1.ace("",""):bytc(numArray=newbytcstrVgth/2;for(intstartindex=O;startIndex<strVgth;startindex+=2)IwinArrayIstari1.ndex12=Convert.ToByte(strVa1.ue.Substring(stariIndex,2),16);returnnumArray;初始化端口pub1.icboo1.P1.c-Ini(stringSuCOm)if(this.SerPort.IsOpen)this.SerPort.C1.ose();this.ScrPort.PortNamc=strCom;Ihis.SerPort.BaudRate=192001Ihis-ScrPort-DataBits=8;this.ScrPort.Parity=Parity1Evcn:Ihis-SerPort-StopBits=StopBi1.s.One;this.ScrPort.RcadTi11woi=2000;his.SerPort.Open():returntrue;)catch(Exceptionex)(IhisSirPError="初始化P1.C通讯端口错误:"+cx.Mcssagc:returnfa1.se;)Ipub1.icstringbyteToHexStr(bytebytes)(stringstr=String.Empty:if(bytes!=nu1.1.)(tbr(intindex=O;index<bytes.1.ength;+index)sir=str+bytcs(indcx.ToString("X2")+""Jreiurnstr;)读取M寄存器pub1.icboo1.Rea<1.M(in1.intAddr,intintCount,refstring)StrVaIuc)(StrVaIue=newStringIintCount:boo1.f1.ag;try(bytcbytData=newbytc(6(byte)I.(byte)I.(byte)O,(byte)O.(byte)O.(byte)O;'byte11bytes1=this.stringToBytes(intAddr.ToString("X2").Pad1.eft(4,0');bytData2=bytes1.OJ;bytData3)=bytcs1.1.:bytData(4=(byte)O;bytData5=(byte)Convert.ToInt32(intCount.ToString(),16);byteIbufferI=this.CRCIWbytData);IhisSerPor1.DiscandInBUffierO;this.SerPortAVritc(buffcr1.0,buffer!.1.ength);DatcTimcnow=DatCTimC.Now;11read.S1.eep(30):intbyIcsToRcad=this.ScrPort.BytesToRcad;if(bytesToRead>O)(TimeSpanIimcSpan=DatcTimc-Now-now;if(timeSpan.Mi1.1.iseconds<=this.1.ntimeOut)bytebuffcr2=newbytcbytcsToRcad:intnum=this.SerPort.Read(bufer2,0,buffer2.Ingh);if(num>=6)(byte(1.bytes2=newbyteiniCount;if(buffcr2(1.I=(bvtc)I&&(int)buffcr22J=(int)(byte)intCount)(for(iniindex=O;index<intCount;+index)(Array.Copy(Array)bufter2,3,(Array)bytes2,0,intCount);siringstr=this.bytcToHcxStr(bytcs2).Rcp1.acc(""."").Trim();strVa1.ueindex=Convert.To1.nt32(str.16).ToString();f1.ag=true;)e1.se(IhisSirPEnW=-P1.C反馈字符出不符合要求!";f1.ag=fa1.se;e1.seIthis.StrPEror="读取寄存器:"+intA<1.dr.ToString()+"反像数据长度不够:"+nun.ToString();f1.ag=fa1.se;e1.seUiisStrPError="读取寄存器:"+intAddr.ToString()+”数据超时+IimCSPan.Mi1.1.isccondsToStringO;f1.ag=fa1.se;e1.sef1.ag=fa1.se;Ihis.StiPError="P1.C未反馈数据帧.”:)catch(Exceptionex)(11ag=fa1.se:(his.StrPError="读取寄存器:"+intA1.dr.ToString()+"发生异常:"+ex.Message;)returnf1.ag;J"写入M寄存器pub1.icboo1.Write_M(intintAddr.stringstrVa1.ue)ITimcSpanIimeSpanI=newTimcSpanO;boo1.f1.ag:Fif(this.SerPort.Is>en)(bytebytData=newbyte6(byte)1.(byte)5.(byie)0,(byte)O.(byte)O,(byte)O;byebytesI=this.siringToBytes(intAddr.ToSiring("X2").Pad1.eft(4,'O');bytData=bytes1.(O;b)Data3=bytes1.(1.;byteJbytcs2=this.stringToBytcs(strVa1.uc.Pad1.cfi(4,*0');bytData4)=bytcs2(I;bytData5=byes2(0;bytcJnumArr