linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘网络学院网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > 开发语言 > Delphi >
栏目导栏
  php
  JSP
  ASP
  asp.net
  JAVA
  c/c++/c#
  perl
  JavaScript
  Basic
  Delphi
资料搜索
热门文章
·HexToStr函数和StrToHex函数
·Delphi中的进制转换
·delphi轻松设置无边框透明窗体
·delphi第三方控件安装(Ehlib)
·DELPHI组件安装全攻略
·delphi动态创建控件
·开发工具比较Visual C++ VS De
·delphi完整身份证效验程序实例
·delphi中的Format函数详解
·delphi编程获取打印机的打印任
·如何判断文本文件的编码格式
·深入研究Variant数组
·用delphi编写网络游戏的外挂
·Delphi技巧-用户自定义数据类型
·delphi设置控件透明
最新文章
·在应用程序中跟踪MOUSE的坐标
·压缩和修复MS Access 2000文件
·DELPHI 6.0 动画制做
·怎样在Delphi中调用LastError信
·怎样得到主域服务器名称
·怎样利用递归实现删除某一目录
·读出主键下所有项
·如何制作照片底片效果的图像(
·获得Modem的状态
·WebBrowser屏幕滚动的实现,设
·有关字符串处理的小技巧
·Delphi建立键盘鼠标动作纪录与
·Delphi中布尔类型辨析
·DELPHI程序注册码设计
·图形的不规则的Copy
Google
 
Delphi实现远程串口的数据采集
[ 作者:  加入时间:2007-10-30 16:10:39  来自:Linux联盟收集整理 ]
摘要:本文介绍了在Windows平台下串口开发的方法,并给出一个使用Delphi设计的远程数据采集的实例。FZjLinux联盟
FZjLinux联盟
  1 引言FZjLinux联盟
FZjLinux联盟
  在工业生产实践中,使用PC机对Inprise公司推出的Delphi是一种功能强大的高级编程语言,其具有可视化面向对象的特征,特别适合Windows平台下的图形界面和用户程序的编制。本文就介绍在Windows平台下用Delphi开发串口的方法和使用Delphi设计的一个实现远程串行数据采集的实例。FZjLinux联盟
FZjLinux联盟
  2 串口工作原理及软件实现方法FZjLinux联盟
FZjLinux联盟
  串口进行通信的方式有两种:同步通信方式和异步通信方式。同步通信方式要求通信双方以相同的时钟频率进行,而且准确协调,通过共享一个单个时钟或定时脉冲源保证发送方和接收方的准确同步,效率较高;异步通信方式不要求双方同步,收发方可采用各自的时钟源,双方遵循异步的通信协议,以字符为数据传输单位,发送方传送字符的时间间隔不确定,发送效率比同步传送效率低。FZjLinux联盟
FZjLinux联盟
  在Windows平台下,Win32 API支持同步和异步两种I/O操作。同步操作的方式的程序设计相对比较简单,但是I/O操作函数在I/O操作结束前不能返回,这将挂起调用线程,直到I/O操作结束;异步操作方式要相对复杂一些,但是可以让I/O操作在后台运行,而不会挂起调用线程,这在大数据量通信情况下对改善调用线程的响应速度是相当有效的。同时由于Win9x和WinNT下对串行通信的处理不同,这就导致了在Win9x下开发的同步方式串行通信程序在NT下会发生工作线程之间的协作阻塞,即当读线程在等待WaitCommEvent的时候,写线程不能正常工作,停在那里,整个程序处于瘫痪状态。这个问题是Windows的API函数处理串行通信的一个BUG,所以对于适应性强的程序都是选择异步方式。下面,本文对在Windows平台下对串口进行开发的方法进行介绍:FZjLinux联盟
FZjLinux联盟
  1. 汇编程序直接读写串口FZjLinux联盟
FZjLinux联盟
  汇编语言的编译效率和执行效率都很高,使用汇编语言直接对串口进行操作可以部分弥补串行通信速度较慢的缺陷,具体做法是:用汇编语言编写读、写串口的函数,在通信程序中直接调用,或者在Delphi中直接内嵌汇编程序进行对端口的读写。FZjLinux联盟
FZjLinux联盟
  例如:FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
asmFZjLinux联盟
  mov dx,0001hFZjLinux联盟
  mov ax,005ehFZjLinux联盟
  int 14hFZjLinux联盟
end;FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
  这样可以达到直接读到端口的效果。但是在WinNT和Win2000下,系统使用了保护机制,不允许用户态的程序直接读取端口,所以在WinNT和Win2000下,这种方法不能被允许执行。Ring3的用户态的程序要进入Ring0去读写端口必须先提供一个驱动(sys)程序,然后通过DLL导出函数供用户程序调用,显然,这种方法比较不容易实现。FZjLinux联盟
FZjLinux联盟
  2. 使用API函数进行串口编程FZjLinux联盟
FZjLinux联盟
  Windows系统通信一般都以WOSA(Windows Open Service Architecture,即Windows开放式服务体系)模型为基础,在此模型中位于上层的应用程序通过调用各种通信API(Application Programming Interfaces,即应用程序接口)与位于下层的设备驱动程序进行数据交换。FZjLinux联盟
FZjLinux联盟
  在Windows平台下,Windows将设备看作是文件进行管理,对设备的操作也可以看作是对文件的操作。Win32 API提供了CreateFile(),WriteFile(),ReadFile(),WaitForSingleObject(),WaitForMultipleObjects(),CreateEvent(),CreateMutex(),CreateSemaphore(),CreateThread()等函数,其基本步骤如下:FZjLinux联盟
FZjLinux联盟
  (1) 利用CreateFile()函数打开串口。该函数有七个参数,其中dwCreationDistribution参数取OPEN_EXISTING,表明打开的串口对应于实际的物理串口;lpFileName参数是要打开的串口名称,如"COM1";DwFlagsAndAttributes参数决定对串口的操作是同步操作还是异步操作;DwDesiredAccess参数是访问方式,可取GENERIC_READ或GENERIC_WRITE;DwShareMode参数是共享模式,对串口物理设备必须取0;LpSecurityAttributes参数是安全属性,取值为NULL;DwFlagsAndAttributes是文件属性和标识,一般取值为FILE_ATTRIBUTE_NORMAL。该函数返回串口操作的句柄。FZjLinux联盟
FZjLinux联盟
  (2) 对该串口句柄对应的设备进行配置,如波特率、数据位、停止位、是否奇偶校验等。这部分首先使用GetCommState()函数得到当前的串口配置信息,将这些信息存放在一个DCB结构中,然后对该DCB结构里面的内容进行重新按要求设置,最后调用SetCommState()函数使修改的设置生效。FZjLinux联盟
FZjLinux联盟
  (3) 配置串口事件。SetCommMask()函数可以设置多个串口信息事件,其串口的信息事件可以是以下任意的组合:FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
EV_BREAK:在输入时Windows检测到中断;FZjLinux联盟
EV_CTS :CTS信号改变状态;FZjLinux联盟
EV_DSR :DSR信号改变状态;FZjLinux联盟
EV_ERR :发生线状态错误;FZjLinux联盟
EV_RING :检测到振铃指示;FZjLinux联盟
EV_RLSD :接收线信号探测状态发生改变;FZjLinux联盟
EV_RXCHAR:接收缓冲区里收到字符;EV_RXFLAG:收到事件字符,并放入接收缓冲区;FZjLinux联盟
EV_TXEMPTY:输出缓冲区空。FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
    (4) 创建串口监视线程监视串口事件。首先使用WaitForSingleObject()、WaitForCommEvent()、WaitForMultipleObjects()等等待函数对线程进行控制,当没有数据收发时,将线程阻塞,减少其CPU的资源占用;当有数据收发时,线程自动启动,完成数据的收发。最后调用CreateThread()函数启动线程。FZjLinux联盟
FZjLinux联盟
  (5) 串口使用结束,用CloseHandle()函数关闭串口,回收资源。FZjLinux联盟
FZjLinux联盟
  由此可见,利用Win32 API函数编写串口通信程序比较复杂,需要掌握大量的系统和通信知识,其优点是实现的功能强大,应用面广泛,适合编写较为复杂的地层次应用程序。FZjLinux联盟
FZjLinux联盟
  3. 使用MSComm控件进行串口编程FZjLinux联盟
FZjLinux联盟
  Microsoft Communication Control(MSComm)是Microsoft公司提供的Windows下串行通信编程的AcitiveX控件。该控件具有丰富的与串口通信密切相关的属性及事件,提供了一系列标准通信命令接口,可以用它创建全双工、事件驱动、高效实用的通信程序。MSComm控件通过串口传输和接收数据,为应用程序提供串行通信功能。FZjLinux联盟
FZjLinux联盟
  MSComm的主要属性及事件:FZjLinux联盟
FZjLinux联盟
  (1) CommPort:设置或返回串行端口号,缺省值1;FZjLinux联盟
FZjLinux联盟
  (2) Setting:设置或返回串口通信参数,格式为"波特率,奇偶校验位,数据位,停止位";FZjLinux联盟
FZjLinux联盟
  (3) PortOpen:打开或关闭串行端口;FZjLinux联盟
FZjLinux联盟
  (4) InBufferSize:设置或返回接收缓冲区的大小,缺省值为1024字节;FZjLinux联盟
FZjLinux联盟
  (5) InBufferCount:返回接收缓冲区内等待读取的字节数,可通过设置该属性为0来清空接收缓冲区;FZjLinux联盟
FZjLinux联盟
  (6) RThreshold:该属性为一阀值,它确定当接收缓冲区内的字节个数达到或超过该值后就产生代码为ComEvReceive的OnComm事件;FZjLinux联盟
FZjLinux联盟
  (7) SThreshold:该属性为一阀值,它确定当发送缓冲区内的字节个数少于该值后就产生代码为ComEvSend的OnComm事件;FZjLinux联盟
FZjLinux联盟
  (8) InputLen:设置或返回接收缓冲区内用Input读入的字节数,设置该属性为0表示Input读取整个缓冲区的内容;FZjLinux联盟
FZjLinux联盟
  (9) Input:从接收缓冲区读取一串字符;FZjLinux联盟
FZjLinux联盟
  (10) InputMode:返回从Input中取回的数据类型,可以是ANSI码和二进制数据数组;FZjLinux联盟
FZjLinux联盟
  (11) OutBufferSize:设置或返回发送缓冲区的大小,缺省值为512字节;FZjLinux联盟
FZjLinux联盟
  (12) OutBufferCount:返回发送缓冲区内等待发送的字节数,可通过设置该属性为0来清空缓冲区;FZjLinux联盟
FZjLinux联盟
  (13) OutPut:向发送缓冲区传送一串字符。FZjLinux联盟
FZjLinux联盟
  如果在通信过程中发生错误或事件,就会触发OnComm事件,并由CommEvent属性代码反映错误类型,在通信程序的设计中可根据该属性值来执行不同的操作。CommEvent属性值及其含义如下:FZjLinux联盟
FZjLinux联盟
  (1) ComEvSend:值为1,发送缓冲区的内容少于SThreshold指定的值;FZjLinux联盟
FZjLinux联盟
  (2) ComEvReceive:值为2,接收缓冲区内字符数达到RThreshold指定的值;FZjLinux联盟
FZjLinux联盟
  (3) ComEvFrame:值为1004,硬件检测到帧错误;FZjLinux联盟
FZjLinux联盟
  (4) ComEvRxOver:值为1008,接收缓冲区溢出;FZjLinux联盟
FZjLinux联盟
  (5) ComEvTxFull:值为1010,发送缓冲区溢出;FZjLinux联盟
FZjLinux联盟
  (6) ComEvRxParity:值为1009,奇偶校验错误;FZjLinux联盟
FZjLinux联盟
  (7) ComEvEOF:值为7,接收数据中出现文件尾(ASCII码为26)字符。FZjLinux联盟
FZjLinux联盟
  所以,MSComm控件主要提供下列两种处理通信的方式:FZjLinux联盟
FZjLinux联盟
  (1) 事件驱动通信方式。当串口发送或接收到数据时,可以利用MSComm控件OnComm事件捕获并处理这些通信事件。OnComm事件还可以检查和处理通信错误。FZjLinux联盟
FZjLinux联盟
  (2) 查询方式。在关键程序之后可以通过检查CommEvent属性来查询事件和错误。 FZjLinux联盟
FZjLinux联盟
  3 系统功能设计FZjLinux联盟
FZjLinux联盟
  本远程数据采集子系统就是利用MSComm控件,通过Moderm同远端的下位机进行通信,发送命令,获得下位机采集的实时数据,通信流程如下: FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
  当PC机检测到下位机摘机的信号,将控制命令写入MSComm的发送缓冲区,控制命令为定长的数据报,格式如下:FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
  其中,当命令代码不是向下位机要数据的命令的时候,起始时间和终止时间均为0。下位机上传的数据报也为定长数据报,格式如下:FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
  数据报标志表明正在传输是数据,为0xFFFF,数据报序号说明当前传输的是第几个数据报,当序号校验码出错时,PC机停止接收数据,并向下位机发重传命令,此时控制命令的起始时间字段填入需要重传的数据报的序号。最后一个数据报将结束标志置为0xFFFF,检测线程检测到该标志时,认为数据接收完毕,向主线程发消息,通知主线程做进一步的处理。FZjLinux联盟
FZjLinux联盟
  数据传输模式采用二进制数据流形式即MSComm的InputMode属性设置为ComInputModeBinary,收到数据之后使用如下程序进行转换:FZjLinux联盟
FZjLinux联盟
FZjLinux联盟
vDataBuffer: oleVariant;FZjLinux联盟
DataBuffer: variant;FZjLinux联盟
vDataBuffer := MSComm1.Input;FZjLinux联盟
DataBuffer := VarArrayCreate([0,2048], varByte);FZjLinux联盟
DataBuffer := vDataBuffer;FZjLinux联盟
FZjLinux联盟
  主线程向下位机发要数据命令的同时,生成检测线程,每收到1032个字节,检测线程对收到的数据报的结束标志和数据报序号进行检验,发现数据报序号错误立即向主线程发错误消息,主线程停止从缓冲中取数据,向下位机发重传数据报的命令。检测线程发现数据报接收完毕,向主线程发消息,主线程结束检测线程,回收资源。FZjLinux联盟
FZjLinux联盟
  4 结论FZjLinux联盟
FZjLinux联盟
  整个系统在远程心电医疗诊断软件上已经得到了应用,实际运行表明,该通信方式简单、可靠、稳定,具有比较高的效率和很好的差错控制功能,可供其他远程通信系统借鉴参考。 Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·Delphi托盘编程实战演练  (2007-10-30 16:09:56)
 ·DELPHI中操作ACCESS技巧集  (2007-10-30 16:08:48)
 ·在DELPHI中打印TDBGrid内容  (2007-10-30 16:05:41)
 ·在Delphi 2005中安装组件  (2007-10-30 16:04:02)
 ·DELPHI组件安装全攻略  (2007-10-30 15:54:19)
 ·Delphi中树型控件的使用技巧  (2007-10-30 15:41:50)
 ·在DELPHI中用线程排序  (2007-10-30 15:41:06)
 ·Delphi的嵌入式asm: Byte快速转换为16进制  (2007-10-30 15:40:20)
 ·创建一个简单的Delphi专家  (2007-10-30 15:14:08)
 ·Delphi下的接口编程学习笔记  (2007-10-30 15:11:56)