就是串口编程!要看看API函数!

解决方案 »

  1.   

    我用的是api的函数,自己初始化,自己打开,自己设buffer,自己.....所以很烦
    倒是没什么难得,注意串口状态,和收到的数据格式,packed,校验就好了。
    好象有现成的控件。找找把。
      

  2.   

    转在一篇文章:
    用C++ Builder 4.0编写Win 95下的串行异步通信程序姜滨  ·串口操纵的基本方法·
      在Win32下,对串口的操作就如同对文件一样打开或关闭,对串行数据的读写可在用户定义的读写缓冲区中进行。具体使用的函数为:  首先用CreateFile( )打开通信串口,其中参数lpFileName指向串口逻辑名,如“COM1”或“COM2”等,参数dwDesiredAccess定义文件的读写权限,一般设为GENERIC-READ|GENERIC-WRITE;参数dwShareMode定义资源共享方式,此处必须设为0,为独占方式;lpSecurityAttributes定义安全属性,Win 95下为NULL;dwCreationDistribution定义文件创建方式;dwFlagsAndAttributes定义文件属性和标记,应设为FILE-FLAG-OVERLAPPED,表示异步通信方式;hTemplateFile 指向一个模板文件的句柄,在 Windows 95下为NULL。  然后用BuildCommDCB( )和SetCommState( )函数通过通信设备控制块DCB(Device Control Block)设置串口通信参数(如波特率、停止位、数据位、校验位等),其中BuildCommDCB( )中的字符串参数lpDef 定义同DOS命令中MODE的参数格式,关于DCB更具体的设置需要根据用户对数据流定义、握手信号及通信控制要求具体定义,参见有关Windows技术资料。用GetCommState()可以得到当前的DCB参数值。如果需要还可通过SetCommTimeouts()和GetCommTomeouts()重新设置读写的超时参数;读写缓冲区的设置使用SetupComm(),参数dwInQueue和 dwOutQueue分别定义为输入和输出缓冲区的大小。  在串口初始化完毕后,还要建立与通信有关的事件对象。一般使用CreateEvent()函数,它返回一事件句柄,其中参数lpEventAttributes指向安全属性结构地址,在Win 95(无安全属性)中为NULL;布尔参数bManualReset 定义事件重置方式,true 表示手工重置,false表示自动重置(相关函数为SetEvent()和ResetEvent());参数bInitialState定义事件初始状态,true表示发信号,否则为不发信号;lpName是为多进程设置的事件名,对于单进程定义为NULL。然后用SetCommMask()定义用户程序可监视的通信事件类别。  以上设置完成后,用户程序就可以等待通信事件的产生,一般调用函数WaitCommEvent()监视通信事件,其中参数lpEvtMask指向产生事件的掩码地址,用于判断事件产生的性质,lpOverlapped指向重叠结构地址,可简单定义为NULL。对于串口事件的响应一般有四种方式:查询、同步I/O、异步I/O和事件驱动I/O,需要根据用户不同控制要求而定。查询方式占用较长的计算机时间,同步I/O方式直到读取完指定的字节数或超时时才返回,容易造成线程阻塞,异步I/O用于后台处理,事件驱动是由系统通知用户程序发生的事件并进行串口操作。 比较而言事件驱动I/O方式较灵活。  当有通信事件产生时,就可用函数ReadFile()和WriteFile()直接对串口缓冲区进行读写操作了。其中lpBuffer 指向读写缓冲区,nNumberOfBytes为要读写的字节数,lpNumberOfBytes为实际读写的字节数,lpOverlapped指定同步或异步操作。通信结束后,调用函数CloseHandle()将串口关闭。  ·应用实例说明·
      使用以上的API函数,笔者给出了简化后的串口初始化的实例。图1为使用C++ Builder 组件生成的串口通信基本参数设置的界面实例。  HANDLE hcom; //定义句柄  DCB dcb;  OVERLAPPED e; //定义重叠结构  void -fastcall TForm1::OkBtnClick(TObjectSender)  { hcom=CreateFile("COM2",GENERIC-READ|GENERIC-WRITE,0,NULL,OPEN-EXISTING,
    FILE-ATTRIBUTE-NORMAL|FILE-FLAG-OVERLAPPED,NULL); //打开通讯口   BuildCommDCB("9600,O,8,1",&dcb);//第一个字符串参数实际使用时由图1选择后组合,这里仅简单说明其格式   SetCommState(hcom,&dcb);   SetupComm(hcom,512,512);//设置读写缓冲区   e.hEvent=CreateEvent(NULL,false,false,NULL); //设置事件   SetCommMask(hcom,EV-RXCHAR| EV-TXEMPTY); //设置事件掩码   OkBtn-〉Enabled=false;}
    用C++ Builder编程实现串行通信(武汉 刘纪锋)用C++ Builder来编写串行通信程序, 我们需要用到几个Windows API函数,而不象在DOS 下那样直接操作串口和中断芯片.这几个函数有OpenFile, CloseFile, GetCommState, SetCommState等,Microsoft的Visual Basic中有一个OCX控件MSComm32,在VB用它做串行通信设备很方便, 将它装入Builder 3中, 它的Input和Ouput属性是Unknown, 即 Builder 3不认识MSComm32的这两个属性, 我们升级到Borland的C++ Builder 4.0,在 Object Inspector中将不再看到这两个属性, 但它们仍然存在, 这两个属性的类型是 OleVariant,也就是Ole万能变量,使用这种类型的方法如下:在要发送数据时,我们声明一个发送数据缓冲区,然后重置它的大小,填充它的元素,发送它,例如:    buff[200];//请声明为全局变量
        OleVariant TxBuff;//声明一个OleVariant变量
        Txbuff=VarArrayCreat(OPENARRAY(int,(0,n)),varByte);//重置它的大小,为0~n,int 为n的类型。
        //varByte为TxBuff每一个元素的类型。
        for(int i=0;i<n+1;i++)Txbuff.PutElement(buf[i],i);
        //填充元素其中buff为你定义的一个固定数组,其中有你要发的数据
        MsComm1->Output=TxBuff;//发送数据,MSComm1为你方在窗体上的一个MSComm32控件。接收数据时请看下面的例子:
        int buff[200];//声明一个存储接收数据的缓冲区,全局变量
        int ByteNum;//收到的字节数
        int BuffPtr;//接收缓冲区的指针,请声明为全局变量,
        OleVariant RxBuff;//一个用于接收的OleVariant变量。
        if(MSComm1-> InBuffCount>0)RxBuff=Communica1->Input;//如果缓冲区有多于一个字节的数据
        ByteNum=RxBuff.ArrayHighBound(1);//将实际读的字节数取出
        for(int i=0;i<=ByteNum;i++){buff[BuffPtr++]=RxBuff.GetElement(i);}//将接收数据读入自己的缓冲区。
    在Object Inspector的Event标签中只有一个事件OnComm, 这个事件在MSComm32控件接收到数据时会被调用,但你必须设置TThreshold属性,这是一个门槛,表示收到几个字节就发送通知消息,如果为零,就不发送通知消息,这样你的OnComm函数就不会得到执行,TThreshold是发送门槛,不要忘记Setting。另外值得注意的是MSComm32的OnComm事件不是很准确,有时会丢失,你不能过分依赖这个事件,否则,经常发生的不是发不出数据,就是接收不到数据,最好的办法是使用一个定时控件,需要的时候就区读MSComm32控件的缓冲区。C++ Builder 编程文集 
    用Pcomm Pro 开 发 串 行 通 信 程 序 
    用C + +Builder 在Win9x 下 开 发 串 行 通 信 程 序 是 程 序 员 们 经 常 遇 到 却 又 令 人 头 痛 的 事 情, 不 但 要 理 解 许 多 复 杂 的API 函 数, 还 要 掌 握 多 线 程 编 程。 令 人 欣 慰 的 是 有 一 些 公 司 专 门 为C + +Builder 开 发 了 编 写 串 行 通 信 程 序 的 开 发 工 具, 例 如MOXA 公 司 的Pcomm( 该 软 件 可 在http:\\www.moxa.com.tw 下 载), 因 而 帮 我 们 解 决 了 串 行 编 程 这 一 难 题。 ----下 面 结 合 一 个 具 体 的 例 子 来 说 明 串 行 通 信 程 序 的 开 发。 本 程 序 的 编 程 环 境 是Win98 和C + +Builder3.0。 这 个 编 程 示 例 的 功 能 比 较 强, 它 具 有 发 送 数 据 和 自 动 接 收 数 据 的 双 重 功 能。 在 它 的 基 础 上 稍 加 修 改, 即 可 以 让 用 户 选 定 进 行 传 输 的 通 信 端 口, 并 设 定 这 个 端 口 的 相 关 参 数, 包 括 波 特 率、 数 据 位、 停 止 位、 奇 偶 校 验 和 流 量 控 制 等。 一、 Pcomm 的 设 置 
    ----启 动C + +Builder3.0, 点 击File/New Application, 建 立 一 个 项 目 文 件, 修 改 表 单 的Name 属 性 为Comm, 然 后 存 盘, 命 名 项 目(Project) 为CommTest, 命 名 单 元(Unit) 为Comm。 
    ----Pcomm Library 是 一 个 动 态 连 接 库(DLL) 文 件, 当 使 用C + +Builder 编 译 器 编 译PComm.dll 库 时, 我 们 必 须 告 诉C + +Builder 的 编 译 器 怎 样 找 到 这 些 函 数(sio_xxx())。 ----因 此 我 们 用PComm Pro 在Borland C + +Builder 中 开 发 一 个 串 行 程 序 时, 必 须 做 到 以 下 两 点: 假 如 你 的Pcomm Pro 是 安 装 在c:\Program files( 缺 省 安 装 目 录) 目 录 下, 把c:\Program files \ Pcomm Pro \ Lib 下 的Pcommb.lib 文 件 加 入 到C + +Builder 的View 菜 单 中Project Manager 的 项 目 中, 使 之 成 为 项 目 的 一 个 单 元(unit)。 
    把 #include "c:\Program files\PcommPro\Lib\PComm.h" 包 含 在 你 的Comm.cpp 中。 
    二、 表 单 及 属 性 的 设 置 
    ----如 图1 中 表 单 所 示: 
     ----依 照 图1 中 主 界 面 来 添 加 控 件, 并 依 照 表1 中 的 设 置 来 设 置 各 控 件 的Name 和Caption 属 性。  ----该 通 信 程 序 的 工 作 原 理 为 中 断 方 式, 即 当 输 入 缓 存 内 有 数 据 时, 就 会 触 发Pcomm 的 中 断 函 数sio_cnt_irq (Port, *CntIrq, count), 再 由 它 启 动 中 断 服 务 程 序CntIrq(), 然 后 由 数 据 接 收 函 数sio_read (port, ibuf, len) 来 接 收 数 据 并 做 其 他 相 应 的 处 理; 至 于 函 数 Open ()、Sent ()、Close () 则 分 别 为 打 开 按 钮、 发 送 按 钮、 关 闭 按 钮 的click 事 件 函 数;SendData、 ReceiveData 分 别 为 发 送 数 据 编 辑 框 和 接 收 数 据 编 辑 框 相 对 应 的 字 符 串 变 量。 三、 主 程 序 的 编 制 
    ----双 击 表 单 上 的Button 控 件, 就 会 产 生 相 应 的 事 件, 如 双 击" 打 开" 按 钮, 就 会 产 生Open() 事 件 函 数。 在 这 些 函 数 中 添 加 代 码, 以 及Pcomm Pro 的 串 行 控 制 函 数, 就 能 实 现 对 串 口 事 件 的 处 理。 其 中 一 个 需 要 注 意 的 问 题 是SendData 和ReceiveData 都 为 AnsiString 字 符 串, 而Pcomm Pro 的 函 数 所 需 发 送 和 接 收 的 字 符 串 都 为 char 型, 因 此 要 正 确 使 用Pcomm 函 数, 还 要 注 意 字 符 串 转 换。AnsiString 字 符 串 可 通 过c_str() 函 数 转 换 为char 型, 而char 行 字 符 串 转 换 为 AnsiString 则 比 较 简 单。 可 用AnsiString(char) 把char 型 强 制 转 换 为AnsiString 型。 程 序 主 要 代 码 如 下 所 示: 
    void __fastcall TComm::Open (TObject *Sender)  
        // 串 口 打 开 函 数
    {
      int i;
      sio_open (port);     // 打 开 串 口
      sio_ioctl (port, B2400, P_NONE | BIT_7 | STOP_1 );
        // 设 置 串 口 参 数
      // 包 括 波 特 率、数 据 位、停 止 位、奇 偶 校 验
      void __stdcall ( *p)(int);
      p=cntirq;
      i=sio_cnt_irq(port, *p,1);// 设 置 中 断 函 数
    }
    // - - - - -  - - - - - - - - - - - -
    void __fastcall TComm::Sent (TObject *Sender) 
       // 数 据 发 送 函 数
    {
    char *SendData=new char[20];
    SendData=SentEdit ->Text.c_str();    
     // 把SendEdit 中 的AnsiString 型 字
         符 串 转 换 为char 型
    sio_write(port,SendData,20);         // 发 送 数 据
    }
    // - - - - - - - - - - - - - - - - -
    void __fastcall TComm::Close (TObject *Sender)  
      // 串 口 关 闭 函 数
    {
     sio_close (port);    // 关 闭 串 口
    }
    // - - - - - - - - - - - - - - - - -
    void __stdcall cntirq(int port)
     // 中 断 服 务 函 数( 手 工 生 成 函 数)
    {
     char ibuf[20];              
     AnsiString ReceiveData[20];      
     sio_read (port,ibuf, 20);    // 接 收 数 据
     ReceiveData = Ansistring(ibuf); 
     //char 字 符 串 转 换AnsiString 型 字 符 串
     ReceiveEdit ->Text=ReceiveData; 
     // 显 示 接 受 到 的 字 符 串
    }----在 程 序 中, 我 们 使 用 了 一 些sio_xxx() 型 的 函 数, 它 们 都 是Pcomm pro 自 带 的 串 行 通 信 函 数( 函 数 的 具 体 用 法 可 以 参 考Pcomm pro 的 帮 助), 通 过 这 些 函 数, 我 们 可 以 对 串 行 端 口 进 行 设 置。 ----sio_open(port) 和sio_close(port) 为 打 开 串 口 和 关 闭 串 口 函 数, 参 数port 可 设 置 具 体 操 作 的 串 口;sio_ ioctl(int port, int baud, int mode) 为 串 口 控 制 函 数, 可 设 置 串 口 的 波 特 率、 数 据 位、 停 止 位、 奇 偶 校 验; 至 于sio_write(port) 和sio_read(port), 则 为 读 串 口 和 写 串 口 函 数;sio_cnt_irq(int port,VOID (CALLBACK *func)(int port), int count) 为 中 断 函 数, 当 串 口 有 数 据 时, 就 触 发 该 函 数, 然 后 该 函 数 就 会 启 动 其 中 断 服 务 程 序VOID (CALLBACK *func)(int port)( 为 一 函 数 指 针), 这 里 是 调 用cntirq() 函 数 接 收 数 据, 该 函 数 需 要 程 序 员 手 工 生 成。 ----由 此 我 们 可 以 看 出, 只 要 我 们 对 程 序 稍 加 修 改, 在 表 单 上 再 添 加 一 些 控 件, 使 得sio_xxx() 这 些 函 数 的 参 数 可 以 由 用 户 界 面 输 入, 就 可 以 做 到 由 用 户 选 定 进 行 数 据 传 输 的 通 信 端 口, 并 设 定 这 个 端 口 的 相 关 参 数, 包 括 波 特 率、 数 据 位、 停 止 位、 奇 偶 校 验 和 流 量 控 制 等 
     
    串口操纵的基本方法·
      在Win32下,对串口的操作就如同对文件一样打开或关闭,对串行数据的读写可在用户定义的读写缓冲区中进行。具体使用的函数为:  首先用CreateFile( )打开通信串口,其中参数lpFileName指向串口逻辑名,如“COM1”或“COM2”等,参数dwDesiredAccess定义文件的读写权限,一般设为GENERIC-READ|GENERIC-WRITE;参数dwShareMode定义资源共享方式,此处必须设为0,为独占方式;lpSecurityAttributes定义安全属性,Win 95下为NULL;dwCreationDistribution定义文件创建方式;dwFlagsAndAttributes定义文件属性和标记,应设为FILE-FLAG-OVERLAPPED,表示异步通信方式;hTemplateFile 指向一个模板文件的句柄,在 Windows 95下为NULL。  然后用BuildCommDCB( )和SetCommState( )函数通过通信设备控制块DCB(Device Control Block)设置串口通信参数(如波特率、停止位、数据位、校验位等),其中BuildCommDCB( )中的字符串参数lpDef 定义同DOS命令中MODE的参数格式,关于DCB更具体的设置需要根据用户对数据流定义、握手信号及通信控制要求具体定义,参见有关Windows技术资料。用GetCommState()可以得到当前的DCB参数值。如果需要还可通过SetCommTimeouts()和GetCommTomeouts()重新设置读写的超时参数;读写缓冲区的设置使用SetupComm(),参数dwInQueue和 dwOutQueue分别定义为输入和输出缓冲区的大小。  在串口初始化完毕后,还要建立与通信有关的事件对象。一般使用CreateEvent()函数,它返回一事件句柄,其中参数lpEventAttributes指向安全属性结构地址,在Win 95(无安全属性)中为NULL;布尔参数bManualReset 定义事件重置方式,true 表示手工重置,false表示自动重置(相关函数为SetEvent()和ResetEvent());参数bInitialState定义事件初始状态,true表示发信号,否则为不发信号;lpName是为多进程设置的事件名,对于单进程定义为NULL。然后用SetCommMask()定义用户程序可监视的通信事件类别。  以上设置完成后,用户程序就可以等待通信事件的产生,一般调用函数WaitCommEvent()监视通信事件,其中参数lpEvtMask指向产生事件的掩码地址,用于判断事件产生的性质,lpOverlapped指向重叠结构地址,可简单定义为NULL。对于串口事件的响应一般有四种方式:查询、同步I/O、异步I/O和事件驱动I/O,需要根据用户不同控制要求而定。查询方式占用较长的计算机时间,同步I/O方式直到读取完指定的字节数或超时时才返回,容易造成线程阻塞,异步I/O用于后台处理,事件驱动是由系统通知用户程序发生的事件并进行串口操作。 比较而言事件驱动I/O方式较灵活。  当有通信事件产生时,就可用函数ReadFile()和WriteFile()直接对串口缓冲区进行读写操作了。其中lpBuffer 指向读写缓冲区,nNumberOfBytes为要读写的字节数,lpNumberOfBytes为实际读写的字节数,lpOverlapped指定同步或异步操作。通信结束后,调用函数CloseHandle()将串口关闭。  ·应用实例说明·
      使用以上的API函数,笔者给出了简化后的串口初始化的实例。图1为使用C++ Builder 组件生成的串口通信基本参数设置的界面实例。  HANDLE hcom; //定义句柄  DCB dcb;  OVERLAPPED e; //定义重叠结构  void -fastcall TForm1::OkBtnClick(TObjectSender)  { hcom=CreateFile("COM2",GENERIC-READ|GENERIC-WRITE,0,NULL,OPEN-EXISTING,
    FILE-ATTRIBUTE-NORMAL|FILE-FLAG-OVERLAPPED,NULL); //打开通讯口   BuildCommDCB("9600,O,8,1",&dcb);//第一个字符串参数实际使用时由图1选择后组合,这里仅简单说明其格式   SetCommState(hcom,&dcb);   SetupComm(hcom,512,512);//设置读写缓冲区   e.hEvent=CreateEvent(NULL,false,false,NULL); //设置事件   SetCommMask(hcom,EV-RXCHAR| EV-TXEMPTY); //设置事件掩码   OkBtn-〉Enabled=false;} 使用Sockets 
    version 1.0 by zyqsj 使用sockets Socket控件让你建立一个利用TCP/IP和有关的协议与其他系统进行通信的应用。使用Sockets,你能够读和写通过它连接的其他机器,而不用担心实际的网络软件的相关细节。Sockets提供基于TCP/IP协议的连接。除此以外还能很好的工作,在其他相关的协议,例如Xerox Network System (XNS), Digital's DEC net, or Novell's IPX/SPX 家族。 
    C++ Builder提供你写网络服务器或客户应用程序去读和写其他的系统。一个服务或客户程序通常专注于一个单一的服务如超文本传送协议(HTTP)或文件传输协议(FTP)。使用server sockets,一个应用程序可以提供这些服务中的一个去连接一个希望使用服务的客户程序。Client sockets允许一个应用使用这些服务中的一个去连接提供这个服务的服务应用。 
    使用sockets去写应用程序,你必须理解下面这些知识: 
    一、服务工具 
    当你需要写网络服务或客户应用时,Sockets提供一种接合。对于许多服务,象 
    HTTP 或 FTP,第三方服务商提供这些服务已经相当有效。有些甚至随着操作系统捆绑而来,以便不用你自己写。然而,当你想更多的控制服务的实现,如想让你的应用程序与网络通信更加紧密,或当没有一个服务能提供你特殊需要的服务时,你可能想建立你自己的服务或客户应用。例如,工作在分布式data sets时,你可能想为数据库写一层与其他系统通信的应用。想使用Sockets实现一个服务,你必须理解: 1.服务协议 
    在你写一个网络服务或客户程序前,你必须明白你的应用将提供或使用什么服务。你的网络应用必须支持许多服务的标准协议。如果你为标准的服务例如HTTP,FTP写网络应用,或even finger or time,你必须先理解与其他系统通信所使用的协议。特殊服务细节你必须看提供的或使用的文档。 
    如果你的应用程序提供一个新的服务与其他系统通信,第一步是为这个服务的 
    服务端和客户端设计通信协议。什么信息将发送?如何整理这些信息?如何对这些信息进行编码? 应用程序通信 
    经常的,你的网络服务端或客户端应用程序要提供一层在网络软件和一个应用之间使用的服务。例如,一个HTTP服务站点在INternet与一个Web 服务应用之间为HTTP请求信息提供内容和应答。 
    在你的网络应用(或客户应用)和网络软件之间Sockets 提供一个接口。你必须提供一个接口,在你的应用程序与应用间使用。你可以拷贝第三方服务商提供的标准API(例如ISAPI),或你可以设计和发布你自己的API. 2.理解服务和端口 
    许多标准服务都有关联的、指定的端口号。当 执行服务时,你可以为服务考虑一个端口号。如果你实现一个标准服务, Windows socket objects 提供一些方法让你为服务寻找端口号。如果提供一个新的服务,在基于Windows 95 或 NT机器上,你能够在文件Services中为你的服务指定一个相关联的端口号。设置Services文件的更多信息请看微软 的Windows Sockets文档。 二、Socket连接的类型 
    Socket连接可以分成三个基本的类型,它们反映了如何开始连接和本地Socket 连接是什么。这三个类型是: 1.客户端连接 
    客户端连接是一个本地系统的客户端socket与一个远程系统上的服务端Socket连接。客户端连接由客户端Socket开始。首先,客户端Socket必须描述它想连接到的服务端Socket. 接着客户端socket查找服务端socket,当找到服务器时,就要求连接。服务端socket可能不能完成正确的连接。服务器sockets维持一个客户端请求队列,在他们有时间时完成连接。当服务端socket接受客户端连接,服务端socket 
    将向它想连接的客户socket发送一个完整的描述,客户端的连接完成。 2.倾听连接 
    服务器 socket不会去定位客户端,代替的,他们形成被动的,"半连接"状态,倾听来自客户端的请求。服务器 sockets形成一个队列,存放 它们听到的连接请求。这个队列记录着客户端连接请求就象他们已连接进来一样。当服务器sockets同意客户连接请求时,它形成一个新的socket去连接客户端,因此这个倾听连接能保持开放状态允许其他客户端请求。 3.服务端连接 
    当倾听socket同意一个客户端请求时,服务器端socket形成一个服务器连接。当服务器端同意连接时,向客户端发送一个服务端socket描述以完成连接,当客户端socket收到这个描述时这个连接得到确认,连接完成。一但连接到客户端的Socket完成,服务端连接就不能识别从一个客户端来的连接。末端双方有同样的能力去接收同样的事件类型。只有倾听(listening)连接是根本不同的,它只有一个单一的末端。 三、sockets描述 
    Sockets让你的网络应用软件通过网络与其他系统进行通信。在网络连接中每个socket可以看成一个终端点。它有一个指定的地址。 *这个系统正在运行 
    *它理解的接口类型 
    *用来连接的端口 
    一个完整的socket连接描述,你必须提供sockets 在连接两端的地址。在你开始一个socket连接前,你必须完整的描述你想得到的连接。有些信息可以从你的应用 
    软件运行的系统平台上得到。例如,你不需要描述一个客户端socket的本地IP地址--这个信息可以从操作系统上获得。你必须提供你工作所依靠的socket的类型的信息。客户端socket必须描述他们想连接的服务器。侦听服务器sockets必须描述他们提供反应的服务器的端口。一个socket 连接终端的完整描述包括两部分: 1.IP地址 
    主机是这样一个系统,它运行着包含有socket的应用程序。你必须描述主机给socket,通过给出主机的IP地址来完成这个描述。IP地址是一个有四个数字(byte)值的,在标准internet点付内的字符串。 
    例如123.197.1.2 
    一个简单的系统可以支持多于一个的IP地址。IP地址通常难于记忆并且容易打错。一个可供选择的方法是使用主机名。主机名就是IP地址的别名,它就是你常看到的统一资源定位(URLs)。它是一个字符串,包括了域名和服务。 
    例如 http://www.wsite.com 
    许多内部网提供给主机的名字对应的系统IP地址是internetIP地址。在windows95 和NT机器上,如果一个主机名不能用,你可以在HOSTS文件中为你的本地IP地址(这个本地IP地址应该是指你想连接的主机IP地址--zyqsj)建立一个进入的名字。 
    关于HOSTS文件的更多信息请看WINDOWS SOCKETS的文档。 
    服务器sockets不需要指定主机。本地IP地址可以从系统中读到。如果本地系统支持多于一个的IP地址,服务器sockets将同时在所有的IP地址上侦听客户端请求。当一个服务器socket同意一个连接,客户端提供一个远程IP地址。客户sockets必须指定远程主机通过提供主机名或者IP地址。 在主机名和IP地址间作一个选择 
    许多应用软件使用一个主机名去指定一个系统。主机名容易记住和容易检查排版错误。进一步讲,服务器能改变系统或与IP地址关联的特殊的主机名。使用一个主机名,能够允许客户端通过主机名描述找到抽象的站点,即使主机使用一个新的IP地址。 
    如果主机名是未知的,客户socket必须指定服务器系统使用的IP地址。通过给一个IP地址来指定服务器将更快。当你提供主机名时,socket在定位服务器系统前,必须搜寻与这个主机名相关的IP地址。 2.端口号 
    虽然IP得地址提供了足够的信息去找到socket连接中位于另一端的系统,你通常还需要指定那个系统的端口号。没有端口号,一个系统在同一时间只能进行一个单一的连接。端口号是唯一标识那允许一个独立系统连接到支持同时多个连接的主机,每个连接都必须指定一个端口号。 
    在网络应用中,对于服务器工具来说端口号是一个数字代码。有一个习惯就是侦听服务连接到他们自己固定的端口号上,以便他们能找到客户端sockets.服务器socket监听为他们提供服务的相关端口号。当他们允许给予一个客户端socket连接时,他们创建一个独立的socket连接,使用不同的专用的端口号。通过这个方法,能持续的监听相关服务的端口号。 
    客户端socket使用一个专用的本地端口号,就不用其他的socket去寻找它们。他们指定他们想连接的服务器端socket的端口号,这样他们就能找到服务器应用程序。常常的,这个端口号是通过命名想连接的服务来间接指定的。 四、使用socket控件 
    C++Builder提供两个socket控件,客户端sockets和服务器sockets.他们允许你的网络应用构成连接其他的机器和允许你通过这个连接来读写信息。与每个socket控件相关联的是windows socket对象,它们在终端的的作用是一个实际的socket连接。socket控件使用windows socket对象去封装windows socket API 调用,所以你的应用不用去关心连接建立的细节或管理socket信息。 
    如果你想利用windows socket API调用或自定义连接细节,socket控件提供了便利,你可以使用windows socket对象的properies,events和方法。 1.使用客户端sockets 
    添加一个客户端socket控件(TClientSocket)到你的form或data module 使你的应用成为一个TCP/IP客户。客户sockets允许你指定你想连接的服务器socket和你希望服务器提供的服务。一但你描述你想得到的连接,你可以使用客户socket控件去完成连接服务。 
    每个客户socket控件使用独立的客户windows socket对象(TClientWinSocket)去应答连接中的客户终端。使用客户sockets去: A.指定想得到的服务 
    客户socket控件有一个数字properties,允许你指定想连接的服务器系统和端口。你可以通过主机名来指定服务器系统,使用Host property。 
    如果你不知道主机名,或者你关心找到服务器的速度,你可以指定服务器系统的IP地址,通过使用 Address property。你必须指定IP地址和主机名中的一个。 
    如果你两个都指定,客户socket控件将使用主机名。除服务器系统外,你必须指定你的客户socket将连接的在服务器系统上的端口。你能够直接使用Port property来指定服务端口号。或者直接在Service property使用想得到的服务的名字。如果你指定端口号和服务名,客户socket控件将使用服务名。 B.建立连接 
    一旦你在客户socket控件中完成了设置描述你想连接的服务器的属性,你就可以进行连接,通过调用Open方法。如果你想你的应用启动时自动建立连接,在设计时设置Active property为true,通过使用Object Inspector来设置。 C.取得关于连接的信息 
    完成连接到服务器socket后,你可以使用与你的客户socket控件相关的客户windows socket object去取得关于连接的信息。使用Socket property去访问client windows socket object。windows socket object 有一个properties,它能让你确定在连接的两端客户和服务器使用的地址和端口号。 
    当使用一个windows socket API调用时,你可以使用SocketHandle property区获得socket连接使用的handle。你可以使用Handle property去访问windows,以便接收来自socket连接的信息。AsyncStyles property决定哪种信息类型是windows handle要接收的。 D.关闭连接 
    当你完成通讯想关闭socket 连接时,你能够通过调用Close方法来关闭连接。连接可能要由服务器端来关闭。如果是这种情况,你将收到一个OnDisconnect 事件的通知。 2.使用服务器sockets 
    添加一个服务端socket控件(TServerSocket)到你的form或data module使你的应用成为一个TCP/IP服务器。服务器sockets允许你指定你想提供的服务或你想用来监听客户请求时使用的端口。你可以使用服务器socket控件去监听和允许客户连接请求。每个服务器socket控件使用一个单一的服务器windows socket Object(TServerWinSocket)去应答在服务器端监听到的连接。它通常使用一个服务器客户winodws socket Object(TServerClientWinSocket)应答在服务器端每个活动的,连接着得到允许服务的客户socket。使用服务器sockets去: A.指定端口 
    在你的服务器socket能够监听客户请求之前,你必须指定一个端口给你的监听服务。你可以使用Port property来指定这个端口。如果你的服务器应用提供一个标准的服务,这个服务使用一个习惯使用的相关联的端口。你能够使用Service property直接指定端口号。使用Service property是一个好的主意,能够减少设置端口号时的错误。如果你既指定了Port property,又指定了Service property,服务socket将使用服务名。 B.监听客户请求 
    一旦你在server socket控件上设置好你的端口号,你就能够通过在运行时通过调用Open方法来监听一个连接。如果你希望你的应用程序能够在启动的时候自动监听连接,在设计的时候通过使用Object Inspector设置Active 属性为true。 C.连接到客户端。 
    当监听服务socket控件接收到一个客户端连接请求时他们将自动接受这个请求。当你没次收到通知时,OnClientConnetc事件将发生。 D.取得关于连接的信息 
    一但你的服务器socket打开了监听连接,你能够使用与你服务器socket控件相关联的服务器windows socket object来取得关于连接的信息。使用Socket property去访问server windows socket object.windows socket object有一个属性能够让你找到关于所有活动的客户socket连接这些客户socket是你通过服务器socket控件允许连接的。使用Handle属性去存取windows通过socket连接收到的信息。 
    每个活动的,连接到客户应用是通过服务、客户windows socket bject (TServerClientWinSocket)封装的。你能够通过server windows socket object的连接属性来访问所有的这些。这些server client windows socket object有些属性让你能够决定哪些地址和端口号给连接的两端--客户和服务器socket使用。当你使用windows socket API调用时,可以使用SocketHandle属性去获得socket连接使用的handle。你能够使用Handle属性去访问windows从socket连接处得来的信息。AsyncStyles属性决定windows handle将接收哪种类型的信息。 E.关闭连接 
    当你决定关闭监听连接时,调用Close方法。这将关闭所有打开着的,连接到客户应用的连接,取消任何尚未同意的连接,接着关闭监听连接以便你的服务socket控件不在接受任何新的连接。当客户端关闭他们自己独立的连接到你的server socket的连接时,你可以在OnClientDisconnect事件中得到讯息。 五、socket事件的应答 
    当使用sockets写应用程序时,大多数工作发生在socket控件的handler事件中.当通过socket连接开始读或写时,OnRead和OnWrite事件在non-blocking client sockets中发生从而通知sockets.同样的,服务器sockets(blocking or non-blocking)收到OnClientRead和OnClientWrite事件. 
    当服务器结束一个连接时,客户scokets收到一个OnDisconnect事件.当客户端结束一个连接时,服务器socket收到一个OnClientDisconnect事件. 
    另外,客户端Sockets和服务器端socket从连接中收到一个错误信息时,都将产生有个错误事件. 错误事件:客户sockets和服务器sockets通常会产生一个OnError事件,当他们从连接中收到一个错误信息的时候.你能够写一个OnError事件处理去响应这些错误信息.这个OnError事件处理提供传送关于socket试图做什么的时候这个错误发生的信息,以及错误信息提供的错误代码.你可以在OnError事件处理中对这个错误作出响应,并且把错误代码改为0,以避免socket产生一个例外. 当开始和完成发生时,socket控件通常会收到一个事件号(number of events).如果你的应用程序需要改变socket开始操作的处理过程或通过连接开始读或写操作时,你将写事件handlers去应答这些client events和server events. A.client events 
    当一个客户socket打开一个连接时,以下事件发生: 
    1.一个OnLookup事件最先发生,它试图去定位server socket.在这里你不能改变Host,Address,Port,Service属性去改变你想定位的服务器.你能够使用Socket属性去访问client windows socket object,并且使用它的SocketHandle属性去调用windows API,以便改变socket的客户属性.例如,如果你想在客户应用软件中设置端口号,你必须在server client连接前做这件事. 
    2.windows socket设置和初始化事件通知. 
    3.当找到server socket时一个OnConnecting事件发生.在这事件中,windows Socket object可以利用的是通过socket属性提供关于连接的另一端的服务socket的一些信息.这是获得实际使用来连接的端口和IP地址的第一个机会,它可能不同于从监听socket处同意连接时得到的端口或IP地址. 
    4.服务器同意连接请求,客户端socket完成连接. 
    5.当一个连接得到确定后,一个OnConnect事件发生.如果你的socket立即开始通过连接读或写,就应写一个OnConnect事件Handler去作这件事. B.服务器端事件(server events) 
    服务器socket控件通过两中方式连接:监听连接和连接到客户应用.服务器socket收到这两个连接的所有事件. 监听时事件 
    当构成监听连接前,OnListen事件发生.在这个时候你能够通过socket属性获得server windows socket object.你能够使用它的SocketHandle属性去改变socket,在socket打开监听之前.例如,如果你想限定监听服务使用的IP地址,你可以在这个OnListen事件Handler中做. 与客户端连接的事件 
    当一个服务器socket同意一个客户连接请求时,接下来的事件发生: 
    1.服务器socket产生一个OnGetSocket事件,通过windows socket handle传送给连接的另一端的socket.如果你想提供自己定义的TServerClientWinSocket of descendant,你可以在OnGetSocket 事件 handler中建立,将被用来替代TServerClientWinSocket. 
    2.一个OnAccept事件发生,传送新的TServerClientWinSocket对象给事件句柄.这是第一个要点,当你使用TServerClientWinSocket的属性去获得被连接中服务的那端的客户的信息时. 
    3.如果服务类型是stThreadBlocking,一个OnGetThread事件发生.如果你想提供自己定义的TServerClientThread子类,你可以在OnGetThread事件句柄中建立一个,它将替代TServerClientThread. 
    4.如果服务类型是stThreadBlocking,一个ONThreadStart事件发生当这个线程(thread)开始执行时.如果你想执行任何初始化这个线程,或调用一些windows socket API在这线程开始通过连接读和写之前,应该使用OnThreadStart事件句柄. 
    5.当客户端完成一个连接时,一个OnClientConnect事件发生.如果是non-blocking服务,你可能想开始通过socket连接在这端进行读或写操作. 六、通过socket连接进行读和写 
    通过socket连接到其他机器的原因是想通过这些连接来读和写信息.什么信息是你要读和写的,或者当你想读和写时是依靠哪些socket连接的相关服务的. 
    通过sockets进行读和写可以是异步的,所以在你的网络应用中不需要阻塞其他代码的执行.这是调用non-blocking connection.你也同样可以通过blocking connection,这时你的下一行代码的执行必须等到读或写操作完成. A.Non-blocking连接,读和写是异步的, 所以在你的网络应用中不需要阻塞其他代码的执行.建立一个Non-blocking连接: 
    1.在客户socket中设置ClientType属性为ctNonBlocking. 
    2.在服务器socket中设置ServerType属性为stNonBlocking. 
    当连接是non-blocking时,连接的另一端企图读或写时读和写事件将把这个信息通知你的socket. 读和写操作事件 
    Non-blocking sockets想通过连接读或写时,它会产生一个读和写操作事件通知你的socket.在客户端sockets,你可以在OnRead或OnWrite事件句柄中对这些事件做出反应.在服务器端Scokets,可以在OnClientRead或OnClientWrite事件句柄中对这些事件做出反应.与socket连接相关联的windows socket object在事件句柄的读或写中被当作一个参数.Windows socket object提供一个方法号(number of methods)以允许你通过连接读或写. 
    通过socket连接读,使用ReceiveBuf或ReceiveText方法.在使用ReceiveBuf方法前,使用Receivelength方法去确定在连接的另一端socket准备发送的字节数(number of bytes). 
    通过socket连接写,使用SendBuf,SendStream,或SendText方法.如果你通过socket发送信息后不在需要socket连接,你可以使用SendStreamThenDrop方法. SendStreamThenDrop在写完所有的信息后将关闭Socket连接,它能够从stream读信息.如果你使用SendStream或SendStreamThenDrop方法,不要释放Stream object, socket在连接结束后会自动释放这个Stream. 
    注意:SendStreamThenDrop将关闭一个独立的客户连接服务,而不是监听连接. B.Blocking connections 
    当你使用的连接是Blocking时,你的Socket必须通过连接发起读或写操作,胜过被动的等待从socket连接发来的通知. 当你的连接末端的读和写操作发生改变时使用Blocking socket.对于客户端sockets,设置ClientType属性为ctBlocking 以便构成一个blocing connection.根据你的客户端应用想完成什么,你可能想建立一个执行线程去完成读或写操作,以便你的应用能够继续执行其他的线程,当它在等待通过连接读或写操作的完成. 
    对于服务器sockets,设置ServerType属性为stThreadBlocking以便构成一个blocking connection.因为blocking connections在等待通过连接读或写信息完成时挂起了其他代码的执行,服务器socket控件通常产生一个新的执行线程给每一个客户连接,当ServerType设置为stThreadBlocking时.许多使用Blocking连接的应用都写使用线程(using threads.甚至如果你不使用线程,你可能也想使用(using) TWinSocketStream去读和写. 
    1)using threads 
    当使用一个blocking connection进行读或写操作时,客户sockets不会自动产生一个新线程.如果你的客户应用程序没有什么事做,直到读或写信息完成,那么这正是你想要的.如果你的应用包括了一个用户界面,它还需要响应用户的操作,那么,你可能想产生一个独立的线程去读写.当服务器sockets形成一个blocking连接时,他们常常产生独立的线程给每一个客户连接,所以没有客户需要等待直到其他客户完成通过连接读或写操作.在默认情况下,服务器sockets使用TServerClientThread对象去实现为每个连接执行不同的线程. 
    TServerClientThread对象模拟发生在non-blocking连接中的OnClientRead和OnClientWrite事件.可是,这些事件发生在监听socket上时,不是本地线程(thread-local).如果客户请求频繁,你将想建立你自己的TServerClientThread子类去提供一个安全线程(Thread-Safe)去完成读和写操作. 
    当写客户线程或写服务器线程时,你能够使用TwinSocketStream去做实际的读写操作. 
    A)写客户端线程 
    为客户端连接写一个线程,定义一个新线程对象,使用新线程对象对话框.你的新线程对象Execute方法的句柄的通过线程连接进行读写操作的细节,可以建立一个TWinSocketStream对象,然后使用它来读或写. 
    使用你自己的线程,在OnConnect事件句柄中建立它.关于建立和运行线程的更多信息,请看Executing thread objects. 
    例子:这个例子显示一个应用的客户线程在连接确定后向服务器发出写请求. 
    void __fastcall TMyClientThread::Execute() 

    while (!Terminated && ClientSocket1->Active) 
    // make sure connection is active 

    try 

    TWinSocketStream *pStream = new TWinSocketStream(ClientSocket1.Socket,60000); 
    try 

    char buffer[10]; 
    GetNextRequest(buffer); 
    // GetNextRequest must be a thread-safe method 
    // write a request to the server 
    pStream->Write(buffer,strlen(buffer) + 1); 
    // continue the communication (eg read a response) } 
    __finally { 
    delete pStream; 


    catch (Exception &E) 

    if (!E.ClassNameIs("EAbort")) 
    Synchronize(HandleThreadException()); 
    // you must write HandleThreadException 


    } B)写服务器线程 
    服务器连接线程由TServerClientThread派生.因为这个,不能使用新线程对象对话框.替代的,手动声明你的线程如下: class PACKAGE TMyServerThread : 
    public ScktComp::TServerClientThread 

    public 
    void __fastcall ClientExecute(void); 
    } 注意你将用重载ClientExcute方法替代Execute方法.执行ClientExecute方法必须为客户端连接写一个同样的Execute方法线程.然而,当你从控件栏上放一个客户socket控件到你的应用上时来替代这个方法时.监听服务socket同意一个连接时,服务客户线程必须使用TServerClientWinSocket对象来建立.这可以利用共公共的CientSocket属性.另外,你能够使用HandleException这个protected性的方法,胜过 
    你自己写你的thread-safe例外操作. 警告:Server sockets会缓存他们使用到的线程.确信ClientExecute方法执行一些必要的初始化操作,以便它们在最后执行时不致于产生不利的结果. 当你使用你的线程时,在OnGetThread事件句柄中建立它.当建立线程,设置CreateSuspended参数为false. 
    例子:这个例子显示一个为一个应用服务的线程,这个应用是在连接确定后由客户端来的读请求. void __fastcall TMyServerThread::ClientExecute() 

    while (!Terminated && ClientSocket->Connected) 
    // make sure connection is active 

    try 

    TWinSocketStream *pStream = new TWinSocketStream(ClientSocket, 
    60000); 
    try 

    char buffer[10]; 
    memset(buffer, 0, sizeof(buffer)); 
    if (pStream->WaitForData(60000)) 
    // give the client 60 seconds to start writing 

    if (pStream->Read(buffer, sizeof(buffer) == 0) ClientSocket->Close(); 
    // if can't read in 60 seconds, close the connection 
    // now process the request 

    else 
    ClientSocket->Close(); 

    __finally { 
    delete pStream; 


    catch (...) 

    HandleException(); 


    } C.使用TwinSocketStream 
    当为一个blocking连接实现一个线程时,你必须确定在连接的另一端的socket是准备写还是读.Blocking连接不会通知socket当它准备好写或读操作的时候.想看看连接是否准备好,使用TWinSocketStream对象.TWinSocketStream提供一个方法去帮助调整读或写操作时间的选择.调用WaitForData方法去等待,直到socket另一端的 
    准备好写操作.当读写操作使用TWinSocketStream时,如果读或写操作在指定的时间期限内未能完成,Stream将发生超时.这个超时被当作一个结果,socket应用不会暂停,而是不断的通过一个dropped connection试图读或写. 注意:你不能在non-blocking连接中使用TWinSocketStream  C++ Builder 编程文集 
    用C++ Builder编程实现串行通信  用C++ Builder来编写串行通信程序,我们需要用到几个Windows API函数而不像在DOS下那样直接操作串口和中断芯片。这几个函数有OpenFile、CloseFile,GetCommState、SetCommState等。Microsoft的Visual Basic 中有一个OCX控件MSComm32,在VB中用它做串行通信程序很方便,将它装入Builder 3中,它的Input和Output属性是UnKnown,即Builder 3不认识MSComm32的这两个属性,我们升级到Borland 的C++ Builder4.0,在Object Inspector中将不再看到这两个属性,但它们仍然存在,这两个属性的类型是OleVariant,也就是Ole万能变量,使用这种类型方法如下:
      在要发送数据时,我们声明一个发送数据缓冲区,然后重置它的大小,填充它的元素,发送它,例如:
      buff[200];//请声明为全局变量
      OleVariant TxBuff;//声明一个OleVariant 变量
      TxBuff=VarArrayCreate(OPENARRAY(int,(0,n)),varByte);//重置它的大小,为0~n,int 为n的类型。
      //varByte为TxBuff每一个元素的类型。
      TxBuff.PutElement(buff[i],i);
      for(int i=0;ibr<n+1;i++) //填充元素,其中buff为你定义的一个固定数组,其中有你要发的数据。
      MSComm1->Output=TxBuff;//发送数据,MSComm1为你放在窗体上的一个MSComm32控件。
      按收数据时请看下面的例子:
      int buff[200];//声明一个存储接收数据的缓冲区,全局变量
      int ByteNum;//收到的字节数
      int BuffPtr;//接收缓冲区的指针,请声明为全局变量,
      OleVariant RxBuff;//一个用于接收的OleVariant变量,
      if(MSComm1->InBufferCount>0)RxBuff=Communica1->Input;//如果缓冲区中有多于一个字节的数据
      ByteNum=RxBuff.ArrayHighBound(1);//将实际读的字节数取出
    {buff[BuffPtr++]=RxBuff.GetElement(i);}//将接收数据读入自己的缓冲区>   
    for(int i=0;ibr<ByteNum+1;i++)
      在Object Inspector的Event标签中只有一个事件OnComm,这个事件在MSComm32控件收到数据时会被调用,但你必须设置RThreshold属性。这是一个门槛,表示收到几个字节就发送通知消息,如果为零,就不发送通知消息,这样你的OnComm函数就不会得到执行,TThreshold是发送门槛,不要忘记Settings。
      另外值得注意的是MSComm32的OnComm事件不是很准确,有时候会丢失,你不能过分依赖这个事件,否则,经常发生的不是发不出数据,就是接收不到数据,最好的办法是使用一个定时控件,需要的时候就去读MSComm32控件的缓冲区。 
     
      

  3.   

    你可以用SPCOMM控件,很多编程的网站都有的当,然后你可以在CSDN里面搜一下,有它的使用方法,好像是在文档中心。
      

  4.   

    createfile那组 api你看一下。
      

  5.   

    spcomm 
    下面是一篇其用法:
              Delphi中串口通信的实现Delphi是一种具有功能强大、简便易用和代码执行速度快等优点的可视化快速应用开发工具,它在构架企业信息系统方面发挥着越来越重要的作用,许多程序员愿意选择 Delphi作为开发工具编制各种应用程序。但是,美中不足之处是 Delphi没有自带的串口通信控件,在它的帮助文档里也没有提及串口通信,这就给编制通信程序的开发人员带来许多不便。 目前,利用 Delphi实现串口通信的常用的方法有 3种:一是利用控件,如 MSCOMM控件和 SPCOMM控件;二是使用 API函数;三是调用其他串口通信程序。其中利用 API编写串口通信程序较为复杂,需要掌握大量的通信知识。相比较而言,利用 SPCOMM控件则相对较简单,并且该控件具有丰富的与串口通信密切相关的属性及事件,提供了对串口的各种操作,而且还支持多线程。下面本文结合实例详细介绍 SPCOMM控件的使用。 SPCOMM的安装 1.选择下拉菜单 Component中的 Install Component选项,弹出如图 1所示的窗口。 在 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); 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,这表示串口已正确地发送出数据并正确地接收到数据,则串口通信成功。