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

上传人:woxinch****an2018 文档编号:38640838 上传时间:2018-05-05 格式:DOC 页数:19 大小:81KB
返回 下载 相关 举报
串口通讯中的数据处理-Sky_第1页
第1页 / 共19页
串口通讯中的数据处理-Sky_第2页
第2页 / 共19页
串口通讯中的数据处理-Sky_第3页
第3页 / 共19页
串口通讯中的数据处理-Sky_第4页
第4页 / 共19页
串口通讯中的数据处理-Sky_第5页
第5页 / 共19页
点击查看更多>>
资源描述

《串口通讯中的数据处理-Sky》由会员分享,可在线阅读,更多相关《串口通讯中的数据处理-Sky(19页珍藏版)》请在金锄头文库上搜索。

1、今天给大家简单讲讲 Delphi 中串口通信中的数据处理 1.串口通信的基本原理: 一般计算机与外部设备通讯有两种方式: 并行传送(Parallel ):一次的传输量为 8 个位(1 字节) ,通过并行端口,如打印机 串行传送(Serial ):一次只传输 1 个位,通过串行端口,如 RS-232 位与字节的概念: 二进制中的每一位 0 和 1,被叫做一个位,每 8 个位构成一个字节 一个字节中最右面的位被称为第 0 位,最左面的位被称为第 7 位。 传输过程中的字节类型:一般有两种。 1.文本(字符字母、标点符号等)在计算机中存储时,每个不同的字符都用不同的数 值来表示。这些数值的范围通常在

2、 0-127 或 0-255 范围。 7 位:ASCII 码,每个字节留一个备用位 8 位:前 128 个遵循 ASCII 码规则,其余的 128 个用来做扩展字符、数字符号、图形字符 等编码。 2.二进制数据: 某些可执行指令文件和图形图像文件就是以二进制形式而不是 ASCII 码形式存储的。 一个数据可用二进制形式存储,可以占多个字节。在通信领域,常常把这种类型的资料叫 做二进制数据。 今天要讲的就是有关二进制数据的处理方法。 文本的处理方法比较简单。我以前写过一个测试软件发布在盒子上。可以从这个地址下载: http:/ 几个概念: 波特率:每秒所能产生的最大电压状态改变率(一秒钟可以振荡

3、的次数)bps 通信双方必须要取得一样的通信速度。原始信号经过不一样的波特率取样后,所得的结果 完全不一样,如取样速度只有原来一半时,信号被跳着取样,数据因此错误。 数据位:有 5,6,7,8 四种 停止位:在奇偶位(选择有奇偶校验)或数据位(选择无奇偶校验)之后发送或接收的停 止位。停止位的长度可在 1、15 或 2 位 三者中选择) 。 奇偶校验位:数据传输之后是可供选择的奇偶校验位发送和接收。奇偶位的状态取决于选 择的奇偶校验类型。如果选择奇校验,则该字符数据中为 1 的位数与校验位相加,结果应 为奇数。可选奇,偶或无。 如果要保证通讯畅通。通讯双方以上 4 项设置必须一致。 一个字节是

4、 8 位,数据位可以 7 位,然后一位校验位就 8 位了。 就是说数据占 5.6。7 或 8 位。 这些参数可以自己设置。但是如果要保证通讯畅通。通讯双方以上 4 项设置必须一致。 2.Delphi 中串口通信常用的常用控件 进行串口通讯可以用 Windows 的 Api 函数:Delphi 的 Windows.pas 单元文件中已经将 Win32 API 均声明进去,因此在 Delphi 里面使用 API 时只要在 uses 区段中加入 Windows,使其引用该单元文件即可。 串行通信相关函数:CreateFile:建立文件,在此用打开通信端口 CloseHandle:关闭由 Create

5、File 建立的文件,在此用于关闭通信端口GetCommState:取得计算机串口的设置参数 SetCommState:设置计算机串口的参数 WriteFile:将数据写入文件,在此用来将数据由串口送出 ReadFile:由文件中读取数据,在此用来取得送到串口的数据 ClearCommError:清除串行端口的错误,并取得信息 PurgeComm:清除串口上的缓冲区 EscapeCommFunction:控制串口的硬件状态 SetCommMask:设置事件的掩码,用以触发事件 WaitCommEvent:等待设置事件的发生 GetCommModemStatus:取得串口上的硬件线路状态 这里不

6、推荐使用 Windows API 函数。 虽然用 API 函数可以实现很强大很灵活的功能,但是势必要花更多的时间和精力在通讯细 节上。而 Dephi 的是 RAD 的经典代表,当然会有更简单的方法,那就是使用封装好的控 件。 较常用的控件有 spcomm,mscomm,comport,apro 等。其中 mscomm 是 ActiveX 控件, 另外 3 个控件都是 Delphi 控件,自带源码,可以到 delphi 盒子,Delphi 园地,sourceforge 等网站下载。具体使用方法这里不详细介绍。 3.数据帧的概念 今天我们主要讲的是二进制数据的处理,所以先介绍下数据帧的概念。 我们

7、要进行数据通讯,那么通讯双方必须遵循一定的协议,这样,通讯双方才能够相互理 解从对方所接收过来的数据。 帧是传送信息的基本单元,每帧由帧起始符标志域,控制域,数据长度域,数据域,帧信 息纵向校验域及帧结束域等 6 个域组成。每个域由若干字节组成。 比如有这样一个帧格式: 代码字节数说明68H 1帧起始符 RTUA4终端逻辑地址 MSTA2主站地址与命令序号 68H 1帧起始符 C1控制码 L2数据长度 DATA变长数据域 CS 1校验码 16H 1结束码 从这个数据帧格式可以看出,一个数据帧至少有 13 个字节。而且前后中间都有规定。这样 我们就可以通过处理分析其中的某些字节来判断这一个数据帧

8、的意义,来进行其他相关的 工作。 当然不同的系统数据帧格式会有不同。我们今天就用这个格式作例子。 4.数据的接收与发送 今天我只介绍下使用 Comport 控件接收和发送数据。 接收数据:在 OnRxChar 事件中。 onRxChar 的原型:procedur TForm1.ComPortRxChar(Sender: TObject; Count: Integer) 这个事件当接收缓冲区中有数据时触发,count 为缓冲区中的字节数。发送数据:发送数据本控件提供了 6 个函数: WaitForAsync WaitForEvent Write WriteAsync WriteStr Write

9、StrAsync 较常使用的是 WriteStr。 function WriteStr(const Str: String): Integer; 参数为字符串类型,返回实际发送的字节数。 安徽刀(297099102) 20:28:27 spcomm,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:47 apro 功能很

10、强大,而且开发这个控件组的公司已经倒闭,贡献了所有的源代码。 除了 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:=Ch

11、r(80); 。 。 。 。 A9:=Chr(00) A10:=Chr(20) writestr(A); 当然看起来很烦琐,其实这不是 String 的优势所在。它真正的优势在于 1.无须管理内存, 交给 Delphi 来管理。2.可以很方便的作为参数或者变量来进行处理。后面讲。 5.数据的处理 如果从终端不断的发送数据到服务器上来,例如每隔 10 毫秒发送一帧数据,我们如何区分 这些数据呢? 要知道,串口通讯是一位一位来传送的,接收则是一个字节一个字节来接收的,不是一帧 一帧来接收的。为了要判断一个字节是前一帧的数据还是后一帧的数据,我们也只能一个 字节一个字节的判断。 先看一段代码,然后我

12、再解释这段代码。这样我们就可以明确地获取每一帧的数据了。讲 完这个之后,我再解释如何利用 Delphi 的面向对象特性来处理收到的这一帧数据。帧格式就用刚才介绍的那个格式。 先定义几个全局变量: FDataStatus:Word; /0 就绪 1.帧头 1 2.帧头 2 FNextLength:Word; /接下来要读的长度 FCurrentLength:Word; /当前的长度 FtmpStr:string;/一帧数据 代码如下: procedure ComPortRxChar(Sender: TObject; Count: Integer); varS1:string;J:Integer;

13、 begincase FDataStatus of0:beginJ:=0;FtmpStr:=;repeatComPort.ReadStr(S1,1);J:=J+1;until (Ord(S11)=$68) or (J=Count);if Ord(S11)=$68 thenbeginFtmpStr:=S1;FDataStatus:=1;FNextLength:=10;FCurrentLength:=0;end;end;1:beginJ:=FCurrentLength;repeatComPort.ReadStr(S1,1);FtmpStr:=FtmpStr+S1;FCurrentLength:=F

14、CurrentLength+1;until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count);if FCurrentLength=FNextLength thenbeginFDataStatus:=2;FNextLength:=(Ord(FtmpStr11) shl 8) + Ord(FTmpStr10)+2;FCurrentLength:=0;end;end;2:beginJ:=FCurrentLength;repeatComPort.ReadStr(S1,1);FtmpStr:=FtmpStr+S1;FCurrentLengt

15、h:=FCurrentLength+1;until (FCurrentLength=FNextLength) or (FCurrentLength-J=Count);if FCurrentLength=FNextLength thenbeginFDataStatus:=0;FNextLength:=0;FCurrentLength:=0;FReceiveFrame.Str:=FtmpStr;SendMessage(CommServer.Handle,XM_OutData,0,LongWord(FReceiveFrame);end;end;end; end; case FDataStatus o

16、f 判断目前接收的数据段。 0:beginJ:=0;FtmpStr:=;repeatComPort.ReadStr(S1,1);J:=J+1;until (Ord(S11)=$68) or (J=Count);if Ord(S11)=$68 thenbeginFtmpStr:=S1;FDataStatus:=1;FNextLength:=10;FCurrentLength:=0;end;end; 如果是一帧开始,那么就对相关参数进行初始化,数据帧初始化为空。 J:=0; FtmpStr:=; 然后开始读,直到读到帧起始符$68 或者读完为止,没有的话,就抛弃读到的数据 (当然你也可以另外记下来,不过意义不大) 。repeatComPort.ReadStr(S1,1);J:=J+1;until (Ord(S11)=$68) or (J=Count); J 就是读到的数据,Jc

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 中学教育 > 高中教育

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号