串口通讯中的数据处理-Sky

上传人:pia****nwu 文档编号:166982465 上传时间:2022-11-02 格式:DOC 页数:19 大小:52.50KB
返回 下载 相关 举报
串口通讯中的数据处理-Sky_第1页
第1页 / 共19页
串口通讯中的数据处理-Sky_第2页
第2页 / 共19页
串口通讯中的数据处理-Sky_第3页
第3页 / 共19页
点击查看更多>>
资源描述
今天给大家简单讲讲Delphi中串口通信中的数据处理 1.串口通信的基本原理:一般计算机与外部设备通讯有两种方式:并行传送(Parallel ):一次的传输量为8个位(1字节),通过并行端口,如打印机串行传送(Serial ):一次只传输1个位,通过串行端口,如RS-232 位与字节的概念:二进制中的每一位0和1,被叫做一个位,每8个位构成一个字节一个字节中最右面的位被称为第0位,最左面的位被称为第7位。 传输过程中的字节类型:一般有两种。 1.文本(字符字母、标点符号等)在计算机中存储时,每个不同的字符都用不同的数值来表示。这些数值的范围通常在0-127或0-255范围。7位:ASCII码,每个字节留一个备用位8位:前128个遵循ASCII码规则,其余的128个用来做扩展字符、数字符号、图形字符等编码。2.二进制数据: 某些可执行指令文件和图形图像文件就是以二进制形式而不是ASCII码形式存储的。 一个数据可用二进制形式存储,可以占多个字节。在通信领域,常常把这种类型的资料叫做二进制数据。 今天要讲的就是有关二进制数据的处理方法。文本的处理方法比较简单。我以前写过一个测试软件发布在盒子上。可以从这个地址下载:几个概念:波特率:每秒所能产生的最大电压状态改变率(一秒钟可以振荡的次数)bps 通信双方必须要取得一样的通信速度。原始信号经过不一样的波特率取样后,所得的结果完全不一样,如取样速度只有原来一半时,信号被跳着取样,数据因此错误。数据位:有5,6,7,8四种停止位:在奇偶位(选择有奇偶校验)或数据位(选择无奇偶校验)之后发送或接收的停止位。停止位的长度可在1、15或2位 三者中选择)。奇偶校验位:数据传输之后是可供选择的奇偶校验位发送和接收。奇偶位的状态取决于选择的奇偶校验类型。如果选择奇校验,则该字符数据中为1的位数与校验位相加,结果应为奇数。可选奇,偶或无。如果要保证通讯畅通。通讯双方以上4项设置必须一致。一个字节是8位,数据位可以7位,然后一位校验位就8位了。就是说数据占5.6。7或8位。这些参数可以自己设置。但是如果要保证通讯畅通。通讯双方以上4项设置必须一致。2.Delphi中串口通信常用的常用控件进行串口通讯可以用Windows的Api函数:Delphi的Windows.pas单元文件中已经将Win32 API均声明进去,因此在Delphi里面使用API时只要在uses 区段中加入Windows,使其引用该单元文件即可。串行通信相关函数:CreateFile:建立文件,在此用打开通信端口CloseHandle:关闭由CreateFile建立的文件,在此用于关闭通信端口GetCommState:取得计算机串口的设置参数SetCommState:设置计算机串口的参数WriteFile:将数据写入文件,在此用来将数据由串口送出ReadFile:由文件中读取数据,在此用来取得送到串口的数据ClearCommError:清除串行端口的错误,并取得信息PurgeComm:清除串口上的缓冲区EscapeCommFunction:控制串口的硬件状态SetCommMask:设置事件的掩码,用以触发事件WaitCommEvent:等待设置事件的发生GetCommModemStatus:取得串口上的硬件线路状态这里不推荐使用Windows API函数。虽然用API函数可以实现很强大很灵活的功能,但是势必要花更多的时间和精力在通讯细节上。而Dephi的是RAD的经典代表,当然会有更简单的方法,那就是使用封装好的控件。较常用的控件有spcomm,mscomm,comport,apro等。其中mscomm是ActiveX控件,另外3个控件都是Delphi控件,自带源码,可以到delphi盒子,Delphi园地,sourceforge等网站下载。具体使用方法这里不详细介绍。3.数据帧的概念今天我们主要讲的是二进制数据的处理,所以先介绍下数据帧的概念。我们要进行数据通讯,那么通讯双方必须遵循一定的协议,这样,通讯双方才能够相互理解从对方所接收过来的数据。帧是传送信息的基本单元,每帧由帧起始符标志域,控制域,数据长度域,数据域,帧信息纵向校验域及帧结束域等6个域组成。每个域由若干字节组成。比如有这样一个帧格式:代码字节数说明68H1帧起始符RTUA4终端逻辑地址MSTA2主站地址与命令序号68H1帧起始符C1控制码L2数据长度DATA变长数据域CS1校验码16H1结束码从这个数据帧格式可以看出,一个数据帧至少有13个字节。而且前后中间都有规定。这样我们就可以通过处理分析其中的某些字节来判断这一个数据帧的意义,来进行其他相关的工作。当然不同的系统数据帧格式会有不同。我们今天就用这个格式作例子。4.数据的接收与发送今天我只介绍下使用Comport控件接收和发送数据。接收数据:在OnRxChar事件中。onRxChar的原型:procedur TForm1.ComPortRxChar(Sender: TObject; Count: Integer)这个事件当接收缓冲区中有数据时触发,count为缓冲区中的字节数。发送数据:发送数据本控件提供了6个函数:WaitForAsyncWaitForEventWriteWriteAsyncWriteStrWriteStrAsync较常使用的是WriteStr。function WriteStr(const Str: String): Integer;参数为字符串类型,返回实际发送的字节数。 安徽刀(297099102) 20:28:27spcomm,mscomm,comport,apro 佛山-sky A (11116580) 20:28:31我感觉comport比较好。 佛山-sky A (11116580) 20:29:00我感觉comport比较好。 安徽刀(297099102) 20:29:17哦 佛山-sky A (11116580) 20:29:47apro功能很强大,而且开发这个控件组的公司已经倒闭,贡献了所有的源代码。除了mscomm以外,另外3个都有源代码。为什么用WriteStr,这里要解释下string类型。Delphi的String类型非常强大,可以兼容PChar,Array of Char,WideString 等字符串或字符数组类型。还有一个很关键的作用是可以作为动态Byte数组来使用。比如你要发送$68 80 50 60 20 30 10 00 00 20这几个字符,可以定义一个字符串A:string;然后用下面的代码:setlength(A,10);A1:=Chr(68);A2:=Chr(80);。A9:=Chr(00)A10:=Chr(20)writestr(A);当然看起来很烦琐,其实这不是String的优势所在。它真正的优势在于1.无须管理内存,交给Delphi来管理。2.可以很方便的作为参数或者变量来进行处理。后面讲。 5.数据的处理如果从终端不断的发送数据到服务器上来,例如每隔10毫秒发送一帧数据,我们如何区分这些数据呢? 要知道,串口通讯是一位一位来传送的,接收则是一个字节一个字节来接收的,不是一帧一帧来接收的。为了要判断一个字节是前一帧的数据还是后一帧的数据,我们也只能一个字节一个字节的判断。先看一段代码,然后我再解释这段代码。这样我们就可以明确地获取每一帧的数据了。讲完这个之后,我再解释如何利用Delphi的面向对象特性来处理收到的这一帧数据。帧格式就用刚才介绍的那个格式。 先定义几个全局变量:FDataStatus:Word; /0 就绪 1.帧头1 2.帧头2FNextLength:Word; /接下来要读的长度FCurrentLength:Word; /当前的长度FtmpStr:string;/一帧数据代码如下:procedure ComPortRxChar(Sender: TObject; Count: Integer);var S1:string; J:Integer;begin case FDataStatus of 0:begin J:=0; FtmpStr:=; repeat ComPort.ReadStr(S1,1); J:=J+1; until (Ord(S11)=$68) or (J=Count); if Ord(S11)=$68 then begin FtmpStr:=S1; FDataStatus:=1; FNextLength:=10; FCurrentLength:=0; end; end; 1:begin J:=FCurrentLength; repeat ComPort.ReadStr(S1,1); FtmpStr:=FtmpStr+S1; FCurrentLength:=FCurrentLength+1; until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count); if FCurrentLength=FNextLength then begin FDataStatus:=2; FNextLength:=(Ord(FtmpStr11) shl 8) + Ord(FTmpStr10)+2; FCurrentLength:=0; end; end; 2:begin J:=FCurrentLength; repeat ComPort.ReadStr(S1,1); FtmpStr:=FtmpStr+S1; FCurrentLength:=FCurrentLength+1; until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count); if FCurrentLength=FNextLength then begin FDataStatus:=0; FNextLength:=0; FCurrentLength:=0; FReceiveFrame.Str:=FtmpStr; SendMessage(CommServer.Handle,XM_OutData,0,LongWord(FReceiveFrame); end; end; end;end;case FDataStatus of判断目前接收的数据段。0:begin J:=0; FtmpStr:=; repeat ComPort.ReadStr(S1,1); J:=J+1; until (Ord(S11)=$68) or (J=Count); if Ord(S11)=$68 then begin FtmpStr:=S1; FDataStatus:=1; FNextLength:=10; FCurrentLength:=0; end; end;如果是一帧开始,那么就对相关参数进行初始化,数据帧初始化为空。J:=0;FtmpStr:=;然后开始读,直到读到帧起始符$68或者读完为止,没有的话,就抛弃读到的数据(当然你也可以另外记下来,不过意义不大)。 repeat ComPort.ReadStr(S1,1); J:=J+1; until (Ord(S11)=$68) or (J=Count);J就是读到的数据,Jcount表示读完了缓冲区。Ord(S11)=$68,S1是个字符串,ORD(S11)表示S1的第一个字节。新乡-和尚(66927785) 20:42:06ReadStr的第二个参数是读取步长么? 佛山-sky A (11116580) 20:42:09ComPort.ReadStr(S1,1);每次只读一个字节,所以S1里只有1个字节。 佛山-sky A (11116580) 20:42:15是的。 新乡-和尚(66927785) 20:42:25可以不是1么?可以。佛山-sky A (11116580) 20:42:50但是如果大于Count会出错。 新乡-和尚(66927785) 20:42:51不好意思,耽误大家时间了,GOON repeat ComPort.ReadStr(S1,4); J:=J+4; until (Ord(S11)=$68) or (JCount); 如何?佛山-sky A (11116580) 20:43:58不赞成。这样用。 北京-不赖猴(35927925) 20:44:08和尚,我想还是让SKY把课讲完再讨论细节,OK? 新乡-和尚(66927785) 20:44:22OK,罪过罪过如果$68在你读的第二个字节里,那不是蒙混过关了?如果读到了$68,就接下来设置读状态为第二阶段,帧数据加上$68,下阶段长度为10,读取的字节数为0.然后结束函数。 if Ord(S11)=$68 then begin FtmpStr:=S1; FDataStatus:=1; FNextLength:=10; FCurrentLength:=0; end;如果缓冲区还有数据,它将再次触发OnRxChar事件。只要缓冲区中有数据,没有处理或者没有正在处理,就会一直触发OnRxChar事件。 佛山-sky A (11116580) 20:46:56刚才将读状态设置为第二阶段了,那么现在就会执行第二阶段的代码:Case语句来判断的。 1:begin J:=FCurrentLength; repeat ComPort.ReadStr(S1,1); FtmpStr:=FtmpStr+S1; FCurrentLength:=FCurrentLength+1; until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count); if FCurrentLength=FNextLength then begin FDataStatus:=2; FNextLength:=(Ord(FtmpStr11) shl 8) + Ord(FTmpStr10)+2; FCurrentLength:=0; end; end;J:=FCurrentLength;/计数器,记下共读了几个。 佛山-sky A (11116580) 20:49:27RTUA4终端逻辑地址MSTA2主站地址与命令序号68H1帧起始符C1控制码L2数据长度 佛山-sky A (11116580) 20:49:44这就是我们第二阶段要读的10个字节。佛山-sky A (11116580) 20:50:04第二阶段的处理是读10个字节,不管缓冲区里有几个字节,不管读几次,读满10个为止。 佛山-sky A (11116580) 20:50:20repeat ComPort.ReadStr(S1,1); FtmpStr:=FtmpStr+S1; FCurrentLength:=FCurrentLength+1; until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count);repeat ComPort.ReadStr(S1,1); FtmpStr:=FtmpStr+S1; FCurrentLength:=FCurrentLength+1; until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count); 佛山-sky A (11116580) 20:50:44FNextLength10是第一阶段设置的。 佛山-sky A (11116580) 20:51:00读到10个字节之后将进入第三阶段。 佛山-sky A (11116580) 20:51:12if FCurrentLength=FNextLength then begin FDataStatus:=2; FNextLength:=(Ord(FtmpStr11) shl 8) + Ord(FTmpStr10)+2; FCurrentLength:=0; end; 佛山-sky A (11116580) 20:51:32下一阶段要读几个呢?FNextLength:=(Ord(FtmpStr11) shl 8) + Ord(FTmpStr10)+2;好在有个L2数据长度表示DATA的长度。所以就有了这一句。FNextLength:=(Ord(FtmpStr11) shl 8) + Ord(FTmpStr10)+2;2是最后两个字节。 佛山-sky A (11116580) 20:54:41接下来就是第三个阶段了: 佛山-sky A (11116580) 20:55:012:begin J:=FCurrentLength; repeat ComPort.ReadStr(S1,1); FtmpStr:=FtmpStr+S1; FCurrentLength:=FCurrentLength+1; until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count); if FCurrentLength=FNextLength then begin FDataStatus:=0; FNextLength:=0; FCurrentLength:=0; FReceiveFrame.Str:=FtmpStr; SendMessage(CommServer.Handle,XM_OutData,0,LongWord(FReceiveFrame); end; end; end; 佛山-sky A (11116580) 20:55:21第三个阶段的读法跟前面一样,都是读一个计一个,直到读完需要的字节为止。J:=FCurrentLength; repeat ComPort.ReadStr(S1,1); FtmpStr:=FtmpStr+S1; FCurrentLength:=FCurrentLength+1; until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count); 佛山-sky A (11116580) 20:56:02读好了就初始化:if FCurrentLength=FNextLength then begin FDataStatus:=0; FNextLength:=0; FCurrentLength:=0; FReceiveFrame.Str:=FtmpStr;SendMessage(CommServer.Handle,XM_OutData,0,LongWord(FReceiveFrame);最后就得到一帧完整的数据FtmpStr,然后将这个数据发送给处理数据的函数。SendMessage(CommServer.Handle,XM_OutData,0,LongWord(FReceiveFrame);相关的函数就会来处理它了。这样,不关什么东西来,什么时候来,一帧完整的数据都在FtmpStr这个字符串里 佛山-sky A (11116580) 20:57:39先取消自动增长,搞完再加上。当然具体的读法还要根据数据帧的格式来定,但是万变不离其宗:就是将读到的字节跟给定的格式比较。 有了这些知识,就基本上可以应付串口通讯程序的编写了。 佛山-sky A (11116580) 20:59:06考虑到Delphi面向对象的特性,如果不用类来规范数据帧的格式似乎有些可惜了。还是拿刚才那帧数据格式来举例:我们可以这样定义基类。 TCustomGY = class(TObject) /0 规约基类 private FFrameBegin:Byte; /帧起始符 FTerminalLogicAddr:T4Byte; /终端逻辑地址 FMasterStation:T2Byte; /主站地址与命令序号 FFrameBegin2:Byte; /帧起始符 FFrameControl:Byte; /控制码 FDataLength:Word; /数据长度 FFrameVerify:Byte; /校验码 FFrameEnd:Byte; /结束码 FPosSend:TFramePosTerminal; /帧发起端 FPosReceive:TFramePosTerminal; /帧接收端 procedure SetDataLength(const Value: Word); procedure SetFrameBegin(const Value: Byte); procedure SetFrameBegin2(const Value: Byte); procedure SetFrameControl(const Value: Byte); procedure SetFrameEnd(const Value: Byte); procedure SetFrameVerify(const Value: Byte); function ReadFrameDataLengthHi: Byte; function ReadFrameDataLengthLo: Byte; function ReadFrameFSEQ: Byte; function ReadFrameISEQ: Byte; function ReadFrameMSTA: Byte; function ReadFrameMSTA2: Byte; procedure SetPosReceive(const Value: TFramePosTerminal); procedure SetPosSend(const Value: TFramePosTerminal); procedure SetMS1(const Value: Byte); procedure SetMS2(const Value: Byte); procedure SetFrameFSEQ(const Value: Byte); procedure SetFrameISEQ(const Value: Byte); procedure SetFrameMSTA(const Value: Byte); procedure SetFrameMSTA2(const Value: Byte); function GetTerminalAddr: Word; function GetTerminalLogicAddr(const AIndex: T4Integer): Byte; procedure SetTerminalAddr(const Value: Word); procedure SetTerminalLogicAddr(const AIndex: T4Integer; const Value: Byte); function GetMasterStation(const AIndex: T2Integer): Byte; procedure SetMasterStation(const AIndex: T2Integer; const Value: Byte); function GetTerminalLogicAddrStr: string; procedure SetTerminalLogicAddrStr(const Value: string); function GetMasterstationStr: string; procedure SetMasterstationStr(const Value: string); protected procedure SetData(const Value: string); virtual; abstract;/设置数据区 虚函数,实现方法在子类中 function ReadData:string; virtual; abstract;/ReadData虚函数,由子类重载. function ToVerifyFrame: Boolean; virtual;/帧是否正确 function ReadWholeFrame: string; virtual; procedure setWholeFrame(const Value: string); virtual; public property FrameBegin:Byte read FFrameBegin write SetFrameBegin; /帧起始符 property RTUAconst AIndex:T4Integer:Byte read GetTerminalLogicAddr write SetTerminalLogicAddr; /终端逻辑地址 property RTUAStr:string read GetTerminalLogicAddrStr write SetTerminalLogicAddrStr; property TerminalAddr:Word read GetTerminalAddr write SetTerminalAddr; /终端地址 property MSTAsconst AIndex:T2Integer:Byte read GetMasterStation write SetMasterStation; /主站地址与命令序号 property MSTAStr:string read GetMasterstationStr write SetMasterstationStr; property FrameBegin2:Byte read FFrameBegin2 write SetFrameBegin2; /第二个帧起始符 property FrameControl:Byte read FFrameControl write SetFrameControl; /控制码 property DataLength:Word read FDataLength write SetDataLength; /数据长度,2位,地位在前,高位在后 property Data:string read ReadData write SetData; /数据,虚属性,在子类实现 property CS:Byte read FFrameVerify write SetFrameVerify; /帧校验位 property FrameEnd:Byte read FFrameEnd write SetFrameEnd; /帧结束码 property FrameIsRight:Boolean read ToVerifyFrame; /检测帧是否正确 property WholeFrame:string read ReadWholeFrame write setWholeFrame; /整帧信息,虚函数,子类实现 property MS1:Byte read FMasterStation0 write SetMS1; /MS1 property MS2:Byte read FMasterStation1 write SetMS2; /MS2 property MSTA:Byte read ReadFrameMSTA write SetFrameMSTA; /MSTA property MSTA2:Byte read ReadFrameMSTA2 write SetFrameMSTA2; /MSTA2,发送端和接收端都为主站时有效 property ISEQ:Byte read ReadFrameISEQ write SetFrameISEQ; /ISEQ property FSEQ:Byte read ReadFrameFSEQ write SetFrameFSEQ; /FSEQ property DataLengthLo:Byte read ReadFrameDataLengthLo; /数据长度低位 property DataLengthHi:Byte read ReadFrameDataLengthHi; /数据长度高位 property PosSend:TFramePosTerminal read FPosSend write SetPosSend; /帧发送端 property PosReceive:TFramePosTerminal read FPosReceive write SetPosReceive; /帧接收端 class function VerifyFrame(S:string): Boolean; /帧是否正确 class function GetVerifyByte(S:string):Byte; /得到校验码 constructor Create; virtual; destructor Destory; virtual; function DecodeFrame(const S:string;NoError:Boolean=True):Boolean; /dynamic; /分解操作后返回True function SumVerify:Byte; dynamic; /计算数据帧CS码 function SumDataLength:Word; dynamic; /计算数据长度 end;所有的判断处理的东西都交给这个类。然后不同的命令再派生出不同的子类。留两个接口,一个进一个出。其他的那些中间数据就随意处置。 佛山-sky A (11116580) 21:03:02实现代码就不贴了。 佛山-sky A (11116580) 21:03:12再示范一个从基类派生的最简单的应用: TSimplyGY = class(TCustomGY) private FData:TarrayByte; /已处理好的Data,需要反转的数据已经反转 protected procedure SetData(const Value: string); override; /设置数据区 function ReadData:string; override; /ReadData public end;子类中实现基类规定的虚函数。有了这样一个类,就可以派生Data区不同的子类了。所要做的处理就是处理Data数据。不同的命令Data域的格式不同。Data数据域的处理,其原理和上面所讲的类似,无非都是字节比较判断。 佛山-sky A (11116580) 21:04:39再分享几个自己在处理串口通讯中比较常用的函数,有兴趣的可以看看,给初学者参考下:佛山-sky A (11116580) 21:04:39再分享几个自己在处理串口通讯中比较常用的函数,有兴趣的可以看看,给初学者参考下: 新乡-和尚(66927785) 21:04:50 佛山-sky A (11116580) 21:05:04function StrToHexStr(const S:string):string;/字符串转换成16进制字符串var I:Integer;begin for I:=1 to Length(S) do begin if I=1 then Result:=IntToHex(Ord(S1),2) else Result:=Result+ +IntToHex(Ord(SI),2); end;end;function HexStrToStr(const S:string):string;/16进制字符串转换成字符串var t:Integer; ts:string; M,Code:Integer;begin t:=1; Result:=; while tLength(S)or(not (St+1 in 0.9,A.F,a.f) then ts:=$+St else ts:=$+St+St+1; Val(ts,M,Code); if Code=0 then Result:=Result+Chr(M); inc(t,2); end;end;function StrToTenStr(const S:string):string;/字符串转换成10进制字符串var I:Integer;begin for I:=1 to Length(S) do begin if I=1 then Result:=IntTostr(Ord(S1) else Result:=Result+ +IntToStr(Ord(SI); end;end;function StrToByteArray(const S:string):TarrayByte;/字符串转换成相应Bytevar I:Integer;begin SetLength(Result,Length(S); for I:=1 to Length(S) do ResultI-1:=Ord(SI);end;function ByteArrayToStr(const aB:TarrayByte):string;/Byte转换成相应字符串var I:Integer;begin SetLength(Result,High(aB)+1); for I:=0 to High(aB) do ResultI+1:=Chr(aBI);end;function StrToBcdByteArray(const S:string; const Rotate:Boolean=False):TarrayByte; /字符串转换成相应BCDBytevar ts:string; I:Integer;begin if Odd(Length(S) then ts:=0+S else ts:=S; SetLength(Result,Length(ts) div 2); for I:=0 to High(Result) do begin if Rotate then ResultHigh(Result)-I:=StrToInt($+ts2*I+1+ts2*I+2) else ResultI:=StrToInt($+ts2*I+1+ts2*I+2); end;end;function BcdByteArrayToStr(const aNum:TarrayByte; const Rotate:Boolean=False):string; /BCDByte转换成相应字符串var I:Integer; t:string;begin SetLength(Result,2*(High(aNum)+1); for I:=0 to High(aNum) do begin t:=IntToHex(aNumI,2); if Rotate then begin Result2*(High(aNum)-I)+1:=t1; Result2*(High(aNum)-I)+2:=t2; end else begin Result2*I+1:=t1; Result2*I+2:=t2; end; end;end;/集合形式转换成数组function SetToByteArray(s:array of const):TarrayByte;var I:Byte;begin SetLength(Result,High(s)+1); for I:=0 to High(s) do ResultI:=SI.VInteger;end;function SetToWordArray(s:array of const):TarrayWord;var I:Byte;begin SetLength(Result,High(s)+1); for I:=0 to High(s) do ResultI:=SI.VInteger;end;function StrToBinStr(const S:string):string;/字符串转换为2进制字符串var I:Integer;begin Result:=; for I:=1 to Length(S) do begin if I=1 then Result:=BinStrArrayOrd(S1) else Result:=Result+ +BinStrArrayOrd(SI); end;end;function ByteToBinStr(const B:Byte):string;/Byte型转换为二进制字符串var I:Integer;begin Result:=; for I:=7 downto 0 do Result:=Result+Chr(B shr I) and 1)+48);end;function BinStrToByte(const S:string):Byte;/二进制字符串转成数字var S1:string8; L:Integer; I:Integer;begin S1:=00000000; L:=min(8,Length(S); for I:=L downto 1 do if SI=1 then S18+I-L:=SI else S18+I-L:=0; Result:=0; for I:=0 to 7 do Result:=Result+(Ord(S1I+1)-48) shl (7-I);end;function T2ByteToWord(const T:T2Byte;const LowFront:Boolean=False):Word;/T2Byte类型转换成Word类型var a1,a2:Byte;begin if LowFront then begin a1:=T1; a2:=T0; end else begin a1:=T0; a2:=T1; end; Result:=a1; Result:=(Result shl 8) + a2;end;function WordToT2Byte(const aNum:Word;const LowFront:Boolean=False):T2Byte;/Word类型转换成T2Byte类型var a1,a2:Byte;begin a1:=aNum; a2:=aNum shr 8; if LowFront then begin Result0:=a1; Result1:=a2; end else begin Result0:=a2; Result1:=a1; end;end;function ByteToBCDByte(const B:Byte;const aType:TBCDType=bt8421):Byte;/Byte转换成BCD码var B1,B2:Byte; function T2421(const P:Byte):Byte; begin if P99 then Result:=0 else begin B1:=B div 10; B2:=B mod 10; case aType of bt8421:begin Result:=(B1 shl 4)+B2; end; bt2421:begin Result:=(T2421(B1) shl 4)+T2421(B2); end; btR3:begin Result:=(B1+3) shl 4)+(B2+3) end; else Result:=(B1 shl 4)+B2; end; end;end;function BCDByteToByte(const B:Byte;const aType:TBCDType=bt8421):Byte;/BCD转成Byte型var B1,B2:Byte; function Ts2421(const P:Byte):Byte; begin if PFF 8421码var B1,B2:Byte;begin if (B=$FF)or(Auto and (B=$AA) then Result:=B else begin B1:=(B and
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 中学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!