我们公司的门禁系统要升级。需将原来的读卡器更换掉,这样原来Lonwork的dde server就不能用了。我们得自己开发读写硬件(即读写门卡处理器)的程序。我对系统和串口通信没有经验,望各位达人、高手不吝赐教,我百般感激。若能令我鹈鹕灌顶,我再送500分给您!

解决方案 »

  1.   

    lyywy (2001-9-24 14:14:00)  
    <div align=center>Delphi中串口通信的实现  
    Delphi是一种具有功能强大、简便易用和代码执行速度快等优点的可视化快速应用开发工具,它在构架企业信息系统方面发挥着越来越重要的作用,许多程序员愿意选择 Delphi作为开发工具编制各种应用程序。但是,美中不足之处是 Delphi没有自带的串口通信控件,在它的帮助文档里也没有提及串口通信,这就给编制通信程序的开发人员带来许多不便。 目前,利用 Delphi实现串口通信的常用的方法有 3种:一是利用控件,如 MSCOMM控件和 SPCOMM控件;二是使用 API函数;三是调用其他串口通信程序。其中利用 API编写串口通信程序较为复杂,需要掌握大量的通信知识。相比较而言,利用 SPCOMM控件则相对较简单,并且该控件具有丰富的与串口通信密切相关的属性及事件,提供了对串口的各种操作,而且还支持多线程。下面本文结合实例详细介绍 SPCOMM控件的使用。 SPCOMM的安装 1.选择下拉菜单 Component中的 Install Component选项,在 Unit file name处填写 SPCOMM控件所在的路径,其他各项可用默认值,点击 OK按钮。 2.安装后,在 System控件面板中将出现一个红色控件 COM。现在就可以像 Delphi自带控件一样使用 COM控件了。 SPCOMM的属性、方法和事件 1.属性 ●CommName:表示 COM1、 COM2等串口的名字; ●BaudRate:根据实际需要设定的波特率,在串口打开后也可更改此值,实际波特率随之更改; ●ParityCheck:表示是否需要奇偶校验; ●ByteSize:根据实际情况设定的字节长度; ●Parity:奇偶校验位; ●StopBits:停止位; ●SendDataEmpty:这是一个布尔型属性,为 true时表示发送缓存为空,或者发送队列里没有信息;为 false时表示发送缓存不为空,或者发送队列里有信息。 2.方法 ●Startcomm方法用于打开串口,当打开失败时通常会报错。错误主要有 7种:⑴串口已经打开;⑵打开串口错误;⑶文件句柄不是通信句柄;⑷不能够安装通信缓存;⑸不能产生事件;⑹不能产生读进程;⑺不能产生写进程; ●StopComm方法用于关闭串口,没有返回值; ●WriteCommData(pDataToWrite: PChar;dwSizeofDataToWrite:Word )方法是个带有布尔型返回值的函数,用于将一个字符串发送到写进程,发送成功返回 true,发送失败返回 false。执行此函数将立即得到返回值,发送操作随后执行。该函数有两个参数,其中 pDataToWrite是要发送的字符串, dwSizeofDataToWrite是发送字符串的长度。 3.事件 ●OnReceiveData :procedure (Sender: TObject;Buffer: Pointer;BufferLength: Word) of object 当有数据输入缓存时将触发该事件,在这里可以对从串口收到的数据进行处理。 Buffer中是收到的数据, BufferLength是收到的数据长度。 ●OnReceiveError : procedure(Sender: TObject; EventMask : DWORD) 当接收数据出现错误时将触发该事件。 SPCOMM的使用 下面是一个利用 SPCOMM控件的串口通信的例子。 以实现 PC机与单片机 8051之间的通信为例,首先要调通它们之间的握手信号。假定它们之间的通信协议是: PC到 8051一帧数据 6个字节, 8051到 PC一帧数据也为 6个字节。当 PC发出( F0,01,FF,FF,01,F0)后 8051能收到一帧( F0,01,FF,FF,01,F0),表示数据通信握手成功,两者之间就可以按照协议相互传输数据。 创建一个新的工程 COMM.DPR,把窗体的 NAME属性定为 FCOMM,把窗体的标题定义为测试通信,添加相应的控件。1.设定 COMM1属性: ●波特率: 4800; ●奇偶校验位:无; ●字节长度: 8; ●停止位: 1; ●串口: COM1。 Memo1中将显示发送和接收的数据。将新的窗体存储为 Comm.pas。 2.编写源代码 //变量说明 var fcomm: TFCOMM; viewstring:string; i:integer; rbuf,sbuf:array[16] of byte; //打开串口 procedure TFCOMM.FormShow(Sender: TObject); begin comm1.StartComm; end; //关闭串口 procedure TFCOMM.FormClose(Sender: TObject; var Action: TCloseAction); begin comm1.StopComm; end; //自定义发送数据过程 procedure senddata; var i:integer; commflg:boolean; begin viewstring:=‘’ ; commflg:=true; for i:=1 to 6 do begin if not fcomm.comm1.writecommdata(@sbuf[i],1) then begin commflg:=false; break; end; //发送时字节间的延时 sleep(2); 
     
      

  2.   


    viewstring:=viewstring+ inttohex(sbuf[i],2)+‘’ ; end; viewstring:=‘发送’+ viewstring; fcomm.memo1.lines.add(viewstring); fcomm.memo1.lines.add(‘’ ); if not commflg then messagedlg(‘发送失败 !’ ,mterror,[mbyes],0); end; //发送按钮的点击事件 procedure TFCOMM.Btn_sendClick(Sender: TObject); begin sbuf[1]:=byte($ f0); //帧头 sbuf[2]:=byte($ 01); //命令号 sbuf[3]:=byte($ ff); sbuf[4]:=byte($ ff); sbuf[5]:=byte($ 01); sbuf[6]:=byte($ f0); //帧尾 senddata;//调用发送函数 end; //接收过程 procedure TFCOMM.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;BufferLength: Word); var i:integer; begin viewstring:=‘’ ; move(buffer^,pchar(@rbuf^),bufferlength); for i:=1 to bufferlength do viewstring:=viewstring+ inttohex(rbuf[i],2)+‘’ ; viewstring:=‘接收’+ viewstring; memo1.lines.add(viewstring); memo1.lines.add(‘’ ); end; 如果 memo1上显示发送 F0 01 FF FF 01 F0和接收到 F0 01 FF FF 01 F0,这表示串口已正确地发送出数据并正确地接收到数据,则串口通信成功  
    brightangel (2001-10-9 20:02:00)  
    下面是来自水木清华的一篇关于VC中使用MSCOMM的文章,或许会对你有所帮助。
    我在BCB中用过这一控件,但遇到一些问题,最后只得放弃,改用API。《再谈用Visual C++开发Windows环境下串行通信程序 》
    清华大学电机系(100084)   吕文哲
    摘要:本文详细介绍了在Visual C++ 5.0中使用串行通信控件时一些常见的问题及 
    其解决办法,并给出了一个较实用的通信示例程序。 
    关键词:串行通信  Windows  Visual C++ 5.0  ActiveX控件 
    1  引言 2 Visual C++ 5.0中串口控件的新特征 
    在Visual C++ 5.0中,串行通信的控件不再叫做OCX控件,而是改名为ActiveX控件, 
    通用于Visual Basic、Delphi以及诸多Internet应用程序中。与Visual C++ 4.x中的 
    串口控件相比,其最显著的变化一是将GetInput()函数的返回类型改为VARIANT(以 
    前为CString);二是增加了一个新的属性:InputMode(输入方式),可以设置为 
    comInputModeText(0)或comInputModeBinary(1),分别表示以文本方式(字符串) 
    或以二进制方式读入接收到的字节串。这两大改进为我们解决下面将要介绍的某些 
    问题提供了强有力的武器。 3 使用串口控件时一些常见问题的产生原因及解决办法 
    概括起来,在使用串口控件时,经常会遇到以下一些问题: 3.1  如何发送00H 
    在《用…》文给出的示例程序中,需要发送的是一个简单的字符串,所以使用了 
    一个CString类型的变量来存储它,然后使用COleVariant类的构造函数将之转换 
    为SetOutput()函数所需要的VARIANT类型的参数(VARIANT和COleVariant可以通 
    用)。由于CString是以00H作为字符串结束标志的,所以如果要发送的串中含有 
    00H,则00H及其后的字节都将被CString舍弃,导致只有部分字节被发送。要解 
    决这个问题,必须使用其它类型的变量来存储待发送的字节串。 
    查看一下COleVariant类的构造函数可知,COleVariant()可以接受多种类型的 
    参数,除了CString外,比较常用的还有BYTE、short、long、float、double及 
    CByteArray等。由于通过串口发送的数据常常是一串二进制字节,因此 
    CByteArray将是最合适的一个数据类型。CByteArray用于存储一个动态的BYTE 
    数组(可以动态改变数组大小)。当待发送的字节串准备好后,我们可以定义 
    ,Visual C++ 4.2编程实践指要,中国铁道出版社,1997年。
      

  3.   

    一个CByteArray的临时变量,然后使用SetSize()函数设置其大小(包含的字节 
    数),并将相应的字节值存入该数组,最后利用COleVariant()转换为 
    COleVariant类型,即可利用SetOutput()函数发送出去(详见示例中 
    Transmitt()函数)。 
    3.2  中文Windows下通信有时会出错 
    有些编制好的通信程序在西文Windows下运行一直很正常,但在中文Windows 
    运行却常常出错,特别是一些大于80H的字节,接收和发送时会出现误码。 
    产生这个问题的主要原因是由于Windows使用不同类型的字符串而导致的。 
    Windows使用两种类型的字符串,即ANSI字符串和Unicode字符串。所有16 
    位的应用程序都使用ANSI字符串;而32位应用程序既可以使用ANSI字符串, 
    也可以使用Unicode字符串。ANSI以unsigned char类型存储字符串,每个字节表示一个不同 
    的字符(与DOS相同);而Unicode以unsigned short类 
    型存储字符串,每两个字节表示一个不同的字符。使用Unicode字符串的一 
    个好处就是便于应用程序的本地化(对我们来说就是汉化),因为汉字就 
    是使用的两个字节的内码(大于80H的ASCII码多被汉字内码所使用)。但 
    在Windows 95中,Windows系统调用使用的是ANSI字符串,因此在中文 
    Windows下的应用程序中,我们必须进行Unicode 字符串和ANSI字符串之 
    间的相互转换。 
    在Visual C++ 4.x中,读入串口接收数据的函数GetInput()返回的是 
    CString类型,如没有进行上述转换,就有可能导致误码出现。前面提 
    到,在Visual C++ 5.0中,GetInput()返回的是VARIANT类型,由于 
    VARIANT结构中包含一个多种数据类型的联合(union),使得我们可以避 
    开使用字符串。同时Visual C++ 5.0串口控件的另一个新属性InputMode 
    可以将输入方式设置为Binary(二进制),从而为我们避开使用字符串 
    进一步铺平了道路。 3.3  不知如何使用VARIANT数据类型 
    有不少读者对VARIANT这个新的数据类型大感头疼。SetOutput()函数中 
    需要的VARIANT参数还可以使用COleVariant类的构造函数简单生成,现 
    在GetInput()函数的返回值也成了VARIANT类型,很多读者往往不知该 
    如何从返回的值中提取有用的内容。 
    VARIANT及由之而派生出的COleVariant类主要用于在OLE自动化中传递 
    数据。实际上VARIANT也只不过是一个新定义的结构罢了,它的主要成 
    员包括一个联合体及一个变量。该联合体由各种类型的数据成员构成, 
    而该变量则用来指明联合体中目前起作用的数据类型。我们所关心的接 
    收到的数据就存储在该联合体的某个数据成员中。 
    该联合体中包含的数据类型很多,从一些简单的变量到非常复杂的数组 
    和指针。由于通过串口接收到的内容常常是一个字节串,我们将使用其 
    中的某个数组或指针来访问接收到的数据。这里推荐给大家的是指向一 
    个SAFEARRAY类型变量的指针parray。新的数据类型SAFEARRAY正如其名 
    字一样,是一个“安全数组”,它能根据系统环境自动调整其16位或32 
    位的定义,并且不会被OLE改变(某些类型如BSTR在16位或32位应用程 
    序间传递时会被OLE翻译从而破坏其中的二进制数据)。大家无须了解 
    SAFEARRAY的具体定义,只要知道它是另外一个结构,其中包含一个 
    (void *)类型的指针pvData,其指向的内存就是存放有用数据的地方。 
    简而言之,从GetInput()函数返回的VARIANT类型变量中,找出parray 
    指针,再从该指针指向的SAFEARRAY变量中找出pvData指针,就可以向 
    访问数组一样取得所接收到的数据了。(详见示例?
    程序中 
    OnCommMscomm()及SaveData()函数) 4   一个实用的通信示例程序 
    下面给出一个完整的通信示例程序,该程序能在两台计算机之间根据指 
    定要求进行数据通信。每台计算机既能发送也能接收各种二进制数据, 
    并且采取了事件驱动的接收方式(Event-drive,类似于DOS中的中断)。 
    其中的许多程序代码具有通用性,大家可以直接或稍加改动后用于自己 
    的应用程序中。 4.1  程序功能简介 
    从任一台机上可以向另一台机发送一命令帧,请求对方发回一数据帧。 
    该数据帧中包含的有效数据长度(字节数)、起始值及相应两数据之间 
    的增量都可以由用户指定,并通过命令帧传递过来。收到命令帧的计算 
    机发送指定要求的数据帧到对方。接收和发送的内容都显示在对话框中 
    (见图2、3)。 4.2  通信规约 
    命令帧格式如下: 
    帧长度  特征码00H       起始值  字节数  增量    校验和 
    其中校验和为前面所有字节的无进位累加和,用于检验通信是否出错。 
    对命令帧,帧长度=6。 
    数据帧格式如下: 
    帧长度  特征码0FFH      指定起始值、字节数及增量的字节串校验和 
    其中校验和同命令帧。对数据帧来说,帧长度=命令帧中指定的字节数 
    +3。 
      
    4.3  具体实现过程 
    第一步,启动Visual C++ 5.0,新建一个基于对话框的应用程序TxRx。 
    第二步,插入串口控件。在Visual C++ 5.0版中插入控件的方法与4.x 
    中不同,具体步骤是:选择Project菜单下Add To Project子菜单中的 
    Components and Controls…选项,在随后的对话框中双击Registered 
     ActiveX Controls项,则所有注册过的ActiveX控件出现在列表框中。 
    选择Microsoft Communications Control, version 5.0,这就是新的 
    串口控件,单击Insert按钮将它插入到我们的Project中来。 
    接下来的工作就是要改造应用程序的主对话框IDD_TXRX_DIALOG,删掉 
    其中的静态文本及“确定”按钮,将“取消”按钮改为“退出”,然 
    后增加新的静态文本、编辑框和按钮控件(如图1所示),并为它们添 
    加相应的变量(表1), 
    图1  定制应用程序主对话框 
    表1 主对话框中新增控件及相应变量 
    控件    控件ID  变量名  变量类型 
    按钮    IDC_TRANSMITT   发送按钮 
    Edit    IDC_TXDATA      m_TxData        CString 
    Edit    IDC_RXDATA      m_RxData        CString 
    Edit    IDC_INIT        m_Init  BYTE 
    Edit    IDC_LENGTH      m_Length        BYTE 
    Edit    IDC_STEP        m_Step  BYTE 
    串口    IDC_MSCOMM      m_ComPort       CMSComm第四步,需要修改TxRxDlg.cpp文件, 
    添加有关程序代码。具体步骤如下: 
      

  4.   

    to: mengxianbao1521(简单就是美丽-代码优化)
    有没有代码
      

  5.   

    to:mengxianbao1521
    代码可否发给我一份
    我的e-mail [email protected]
      

  6.   

    在网上讨论串口编程的不少但很少见用api 写的代码
      

  7.   

    在delphi未证实的葵花宝典 中有几个经典的例子
    如有需要可以发给你