用API函数实现串行通讯.docx

上传人:b****5 文档编号:4110762 上传时间:2022-11-27 格式:DOCX 页数:10 大小:20.53KB
下载 相关 举报
用API函数实现串行通讯.docx_第1页
第1页 / 共10页
用API函数实现串行通讯.docx_第2页
第2页 / 共10页
用API函数实现串行通讯.docx_第3页
第3页 / 共10页
用API函数实现串行通讯.docx_第4页
第4页 / 共10页
用API函数实现串行通讯.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

用API函数实现串行通讯.docx

《用API函数实现串行通讯.docx》由会员分享,可在线阅读,更多相关《用API函数实现串行通讯.docx(10页珍藏版)》请在冰豆网上搜索。

用API函数实现串行通讯.docx

用API函数实现串行通讯

用API函数实现串行通讯

责任编辑:

admin 更新日期:

2005-8-6

以往的DOS系统是通过DOS中断和BIOS中断向用户提供串行接口的通讯能力。

在Windows环境下,C++的开发工具既没有提供象DOS和BIOS中那样专门的串行通讯控制方法,也不允许用户直接控制串口的中断。

为了保证资源共享,Windows系统完全接管了各种硬件资源,使用中断来控制端口将破坏系统的多任务性,使系统的稳定性受到影响。

但Windows同时也提供了功能强大的API函数使用户能间接的控制串行通讯。

1、实现串行通讯的相关API函数

API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。

常用函数及作用如表5-1所示。

表5-1常用串行通讯API函数及其作用

函数名  作用

CreateFile打开串口

GetCommState  检测串口设置

SetCommState设置串口

BuilderCommDCB用字符串中的值来填充设备控制块

GetCommTimeouts检测通信超时设置

SetCommTimeouts设置通信超时参数

SetCommMask设定被监控事件

WaitCommEvent等待被监控事件发生

WaitForMultipleObjects等待多个被监测对象的结果

WriteFile发送数据

ReadFile  接收数据

GetOverlappedResult返回最后重叠(异步)操作结果

PurgeComm清空串口缓冲区,退出所有相关操作

ClearCommError更新串口状态结构体,并清除所有串口硬件错误

CloseHandle  关闭串行口

2、打开串口

函数CreateFile原本用于打开文件,但它同样可用于打开一个通信端口。

与系统中其他对象一样,通信端口也是用句柄来标识的。

CreateFile函数返回被操作的通信端口句柄,其调用方法如下:

HANDLECreateFile(

LPCTSTRlpFileName,    //指向文件名字符串的指针

DWORDdwDesireAccess,     //操作模式

DWORDdwShareMode,      //共享方式

LPSECURITY_ATTRIBUTES  lpSecurityAttributes,            

//指向安全属性的指针

DWORDdwCreationDistribution,//文件建立方式

DWORDdwFlagsAndAttributes  //文件属性

HANDLEhTemplateFile)      //模板文件句柄

lpFileName:

指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字。

当用CreateFile打开串口时,这个参数可用“COM1”指定串口1,用“COM2”指定串口2,依此类推。

dwDesireAccess:

指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或ENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值。

用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;

dwShareMode:

指定此文件可以怎样被共享。

因为串行口不支持任何共享模式,所以dwShareMode必须设为0;

lpSecurityAttributes定义安全属性,一般不用,可设为NULL。

Win9x下该参数被忽略;

dwCreationDistribution定义文件创建方式,对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;

dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;

hTemplateFile指向一个模板文件的句柄,串口无模板可言,设为NULL。

在Windows9x下该参数必须为NULL。

用异步读写方式打开串口1的函数调用如下:

m_hComm=CreateFile(“COM1”,       //打开串口1

                     GENERIC_READ|GENERIC_WRITE,//读写方式  

                      0,              //不能共享

                     NULL,         //不用安全结构

                     OPEN_EXISTING,      //打开已存在的设备                                                   

                     FILE_FLAG_OVERLAPPED,   //异步方式

                     0);              //无模板

串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_VALUE(0XFFFFFFFF)。

  

3、串口设置

  

第一次打开串口时,串口设置为系统默认值,函数GetCommState和SetCommState可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息。

程序中可先用GetCommState检索端口的当前设置,修改其中的部分字段后再用SetCommState进行端口设定。

这样可不必构造一个完整的DCB结构。

下面介绍几个主要的函数和结构体:

(1)GetCommState

BOOL  GetCommState(hCommDev,lpdcb);

参数hCommDev标识通信设备,应使用CreateFile返回的句柄。

Lpdcb是指向DCB结构的指针,函数调用后当前串口配置信息将被保存在这个结构内。

如果函数成功返回值为TRUE;否则返回值为FALSE。

SetCommState用法与GetCommState相似,在此不再重复。

DCB结构定义如下(只介绍主要的几项):

       typedef  struct_DCB{

              ……

              DWORD   BardRate;      //波特率的设置

              BYTE     ByteSize;     //数据位的个数

              BYTE     Parity;         //是否有奇偶校验位

              BYTE     StopBits;       //停止位的个数

              ……

              }DCB;

(2)SetCommTimeouts

BOOL  SetCommTimeouts(hCommDev,lpctmo);

Lpctmo指向包含新的超时参数的COMMTIMEOUTS结构。

COMMTIMEOUTS结构定义如下:

typedef  struct_COMMTIMEOUTS{

DWORD  ReadIntervalTimeout;

DWORD  ReadTotalTimeoutMultiplier;

DWORD  ReadTotalTimeoutconstant;

DWORD  WriteTotalTimeoutMultiplier;

DWORD  WriteTotalTimeoutconstant;

}COMMTIMEOUTS,LPCOMMTIMEOUTS;

ReadIntervalTimeout:

  以毫秒为单位指定通信线上两个字符到达之间的最大时间。

在ReadFile操作其间,收到第一个字符时开始计算时间。

若任意两个字符到达之间的间隔超过这个最大值,ReadFile操作完成,返回缓冲数据。

0值表示不用间隔限时。

若该成员为MAXDWORD,且ReadTotalTimeoutconstant和ReadTotalTimeoutMultiplier成员为零,则指出读操作要立即返回已接收到的字符,即使未收到字符,读操作也要返回。

ReadTotalTimeoutMultiplier:

以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间。

每个读操作的总限时时间等于读操作所需的字节数与该值的乘积。

ReadTotalTimeoutConstant:

以毫秒为单位指定一个常数,用于计算读操作的总限时时间。

每个操作的总限时时间等于ReadTotalTimeoutMultiplier成员乘以读操作所需字节数再加上该值的和。

ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant成员的值为0表示读操作不使用限时时间。

WriteTotalTimeoutMultiplier和WriteTotalTimeoutconstant的意义和作用分别与ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant相似,不再重复。

(3)BuilderCommDCB

BOOLBuilderCommDCB(lpszDef,lpdcb)

这个函数按lpszDef字符串所指定的格式来配置串口的DCB。

    LpszDef:

指向一个以NULL结束的字符串,该字符串指定串口的控制信息。

比如,“1200,N,8,1”指定波特率为1200,无奇偶校验位,有8个数据位和1个停止位。

lpdcb:

指向被填充的DCB结构。

  

(4)SetCommMask

BOOLSetCommMask(hCommDev,fdwEvtMask);

fdwEvtMask指向一个32位的屏蔽码,如果指定为EV_RXCHAR|EV_CTS,表示程序监控串口的收、发事件。

  

下面以简单的例子说明串口设置的步骤:

       m_CommTimeouts.ReadIntervalTimeout=1000;

       m_CommTimeouts.ReadTotalTimeoutMultiplier=1000;

       m_CommTimeouts.ReadTotalTimeoutConstant=1000;

       m_CommTimeouts.WriteTotalTimeoutMultiplier=1000;

       m_CommTimeouts.WriteTotalTimeoutConstant=1000;

       if(SetCommTimeouts(m_hComm,&m_CommTimeouts))

       //串口超时参数设置

              if(SetCommMask(m_hComm,dwCommEvents))

              //设置串口事件掩码

                     if(GetCommState(m_hComm,&m_dcb))

                     //获取串口当前状态

                            if(BuildCommDCB(“1200,N,8,1”,&m_dcb))

                            //建立串口设备控制块

用API函数实现串行通讯

责任编辑:

admin 更新日期:

2005-8-6

;      if(SetCommState(m_hComm,&m_dcb));

                                   //设置串口参数

       ……

以上任何一个if语句的判断条件为假时都将调用GetLastError函数获取错误信息,进行错误处理。

  

  

4、读写串口数据

  

Win32API函数ReadFile和WriteFile支持对串行口的读写操作。

这些函数的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响。

串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的。

在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序。

而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行。

程序在调用ReadFile和WriteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动的事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程。

通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,则读写函数立即返回并返回已传输的数据字节数。

下面介绍主要的用于串口读写的函数:

(1)ReadFile函数的调用方法如下:

       BOOLReadFile(

                     HANDLEhFile,          //用CreateFile获得的文件句柄

                     LPVOIDlpBuffer,      //输入缓冲区首址

                     DWORDnNumberOfBytesToRead,//设定读入字节数

                     LPDWORDlpNumberOfByteRead,//实际读入字节数

                     LPOVERLAPPEDlpOverlapped   //重叠操作方式数据结构地址

                     );

(2)WriteFile函数的调用方法如下:

       BOOLWriteFile(

           HANDLEhFile,             //用CreateFile获得的文件句柄

           LPCVOIDlpBuffer,    //输出缓冲区首址

           DWORDnNumberOfBytesToWrite,   //要求输出的字节数

           LPDWORDlpNumberOfBytesWritten,//实际输出字节数

           LPOVERLAPPEDlpOverlapped):

        //重叠操作方式数据结构地址

(3)GetOverlappedResult函数调用方法如下:

       BOOLGetOverlappedResult(

           HANDLE  hFile,//用CreateFile获得的文件句柄

           LPOVERLAPPED  lpOverlapped,    

                                          //指向一个在启动重叠操作时指定的

                                          OVERLAPPED结构(即读写函数中指定的OverLapped结构)

           LPDWORDlpNumberOfBytesTransferred,//实际传输的字节数

                     BOOL  bWait,      //是否等待悬挂的重叠操作完成,若为

                                                 //TRUE,则此函数直到操作完成后才返回。

            );

       OVERLAPPED结构定义如下:

       typedefstruct_OVERLAPPED{

           DWORDInternal;

           DWORDInternalHigh;

           DWORDOffset;

           DWORDOffsetHigh;

           HANDLEhEvent;

              }OVERLAPPED;

如果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位)。

(4)WaitCommEvent函数的调用法如下:

       BOOLWaitCommEvent(

           HANDLEhCommDev,              //串口句柄

           LPDWORDlpfdwEvtMask,       //见SetCommEvent函数说明

           LPOVERLAPPEDlpo,   //重叠操作方式数据结构地址

            );

当由SetCommMask函数所指定的事件产生时这个函数将返回TRUE。

  

下面是一个串口读写的流程图。

  

  串口操作流程图

  

5、关闭串口

  

如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口。

如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭。

但为了安全起见,最好是显式的关闭它。

关闭串口的语句为CloseHandle(hCommDev);其中hCommDev为用CreateFile建立的串口句柄。

  

6、一个完整的例子

    这个串口控制类是我做的一个软件中使用的,基本用WINAPI实现,在Win95/Win98/Win2000下运行良好,可不做修改的用在其它BCB程序中。

读数据采用事件驱动方式,用一个线程处理相应事件,收到的字符用消息发往父窗口;由于我编的软件中写串口的数据不多,所以采用直接写的方式,而没用线程。

串口控制类COM.hCOM.cpp

串口控制类中使用的读串口线程COMThread.hCOMThread.cpp

打包下载

这个类的使用方法如下:

1、建立串口类的实例,如:

     SerialPort=newTSerialPort();    //实例化一个串口控制类

     //初始化串口,Baud:

9600,DataBits:

8,StopBits:

1,无校验位

     SerialPort->InitPort(this,g_iSerialPort,9600);

     SerialPort->StartMonitoring();   //创建串口监控线程,开始监控

2、接收串口数据

(1)映射串口消息,在创建以上实例的窗口类的声明中加入:

     void__fastcallOnComRx(TMessage&Message);   

    //指定消息WM_COMM_RXCHAR(由串口监控线程发出的消息,表示接收到一个字符)的处理函数为OnComRx

     BEGIN_MESSAGE_MAP

         MESSAGE_HANDLER(WM_COMM_RXCHAR,TMessage,OnComRx)

     END_MESSAGE_MAP(TForm)

(2)实现函数OnComRx(),如:

//---------------------------------------------------------------------------

//串口消息(接收到一个字符)处理函数

//消息的参数WParam就是接收到的字符

void__fastcallTDlgProgram:

:

OnComRx(TMessage&Message)

{

     unsignedcharucRxData=(unsignedchar)Message.WParam;     //串口监控线程收到的字符

     ………………

}

//---------------------------------------------------------------------------   

3、向串口发送数据

调用函数boolWriteToPort(unsignedcharucTxChar)可向串口写一个字符。

如SerialPort->WriteToPort(0x55); 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1