调用Windows的API函数串口编程.docx

上传人:b****0 文档编号:17380629 上传时间:2023-07-24 格式:DOCX 页数:13 大小:21KB
下载 相关 举报
调用Windows的API函数串口编程.docx_第1页
第1页 / 共13页
调用Windows的API函数串口编程.docx_第2页
第2页 / 共13页
调用Windows的API函数串口编程.docx_第3页
第3页 / 共13页
调用Windows的API函数串口编程.docx_第4页
第4页 / 共13页
调用Windows的API函数串口编程.docx_第5页
第5页 / 共13页
调用Windows的API函数串口编程.docx_第6页
第6页 / 共13页
调用Windows的API函数串口编程.docx_第7页
第7页 / 共13页
调用Windows的API函数串口编程.docx_第8页
第8页 / 共13页
调用Windows的API函数串口编程.docx_第9页
第9页 / 共13页
调用Windows的API函数串口编程.docx_第10页
第10页 / 共13页
调用Windows的API函数串口编程.docx_第11页
第11页 / 共13页
调用Windows的API函数串口编程.docx_第12页
第12页 / 共13页
调用Windows的API函数串口编程.docx_第13页
第13页 / 共13页
亲,该文档总共13页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

调用Windows的API函数串口编程.docx

《调用Windows的API函数串口编程.docx》由会员分享,可在线阅读,更多相关《调用Windows的API函数串口编程.docx(13页珍藏版)》请在冰点文库上搜索。

调用Windows的API函数串口编程.docx

调用Windows的API函数串口编程

API串口通信部分

1.串口的操作可以有两种操作方式:

同步操作方式和重叠操作方式(又称为异步操作方式)。

同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程);而重叠操作方式,API函数会立即返回,操作在后台进行,避免线程的阻塞。

2.一般都通过四个步骤来完成:

打开串口,配置串口,读写串口,关闭串

(1)打开串口

11.CreateFile来打开或创建的。

该函数的原型为:

HANDLECreateFile(

LPCTSTRlpFileName,//将要打开的串口逻辑名,如“COM1”;

          DWORDdwDesiredAccess,//指定串口访问的类型,可以是读取写入或二者并列;

DWORDdwShareMode,//指定共享属性,由于串口不能共享,该参数必须置为0;

         LPSECURITY_ATTRIBUTESlpSecurityAttributes,//引用安全性属性结构,缺省值为NULL;

          DWORDdwCreationDistribution,//创建标志,对串口操作该参数必须置为OPEN_EXISTING;

DWORDdwFlagsAndAttributes,//属性描述,用于指定该串口是否进行异步操作,该值为

FILE_FLAG_OVERLAPPED,//表示使用异步的I/O;

该值为0,表示同步I/O操作;

HANDLEhTemplateFile);//对串口而言该参数必须置为NULL;

12.同步I/O方式打开串口的示例代码:

HANDLEhCom; //全局变量,串口句柄

 hCom=CreateFile("COM1",//COM1口

  GENERIC_READ|GENERIC_WRITE,//允许读和写

  0,//独占方式

  NULL,

  OPEN_EXISTING,//打开而不是创建

  0,//同步方式

  NULL);

 if(hCom==(HANDLE)-1)

 {

  AfxMessageBox("打开COM失败!

");

  returnFALSE;

 } returnTRUE;

13.异步I/O方式打开串口的示例代码:

HANDLEhCom; //全局变量,串口句柄

 hCom=CreateFile("COM1", //COM1口

            GENERIC_READ|GENERIC_WRITE,//允许读和写

            0, //独占方式

            NULL,

            OPEN_EXISTING, //打开而不是创建

            FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//重叠方式

            NULL);

 if(hCom==INVALID_HANDLE_VALUE)

 {

  AfxMessageBox("打开COM失败!

");

  returnFALSE;

 }   returnTRUE;

(2)配置串口

21.需要一个DCB结构。

DCB结构包含了诸如波特率、数据位数、奇偶校验和停止位数等信息。

在查询或配置串口的属性时,都要用DCB结构来作为缓冲区。

(结构详见后)

22.一般用CreateFile打开串口后,可以调用GetCommState函数来获取串口的初始配置。

GetCommState函数可以获得COM口的设备控制块,从而获得相关参数:

BOOLGetCommState(

  HANDLEhFile,//标识通讯端口的句柄

  LPDCBlpDCB//指向一个设备控制块(DCB结构)的指针

 );

23.要修改串口的配置,应该先修改DCB结构,然后再调用SetCommState函数设置串口。

SetCommState函数设置COM口的设备控制块:

BOOLSetCommState(

  HANDLEhFile,

  LPDCBlpDCB

 );

24.程序一般还需要设置I/O缓冲区的大小和超时。

Windows用I/O缓冲区来暂存串口输入和输出的数据。

如果通信的速率较高,则应该设置较大的缓冲区。

调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小。

BOOLSetupComm(

   HANDLEhFile, //通信设备的句柄

   DWORDdwInQueue, //输入缓冲区的大小(字节数)

   DWORDdwOutQueue //输出缓冲区的大小(字节数)

  );

25.在读写串口之前,要用PurgeComm()函数清空缓冲区,该函数原型:

BOOLPurgeComm(

HANDLEhFile, //串口句柄

   DWORDdwFlags //需要完成的操作:

PURGE_TXABORT  中断所有写操作并立即返回,即使写操作还没有完成。

PURGE_RXABORT  中断所有读操作并立即返回,即使读操作还没有完成。

PURGE_TXCLEAR  清除输出缓冲区

PURGE_RXCLEAR  清除输入缓冲区

);

26.在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。

超时的作用是在指定的时间内没有读入或发送指定数量的字符,ReadFile或WriteFile的操作仍然会结束。

要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。

调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。

(详见后)

  

(3)读写串口

31.我们使用ReadFile和WriteFile读写串口,下面是两个函数的声明:

 

BOOLReadFile(

HANDLEhFile, //串口的句柄

 LPVOIDlpBuffer,//读入的数据存储的地址,//即读入的数据将存储在以该指针的值为首地址的一片内存区

DWORDnNumberOfBytesToRead, //要读入的数据的字节数

 LPDWORDlpNumberOfBytesRead, //指向一个DWORD数值,该数值返回读操作实际读入的字节数

LPOVERLAPPEDlpOverlapped //重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL。

  ); 

BOOLWriteFile(

HANDLEhFile, //串口的句柄

LPCVOIDlpBuffer, //写入的数据存储的地址,即以该指针的值为首地址的nNumberOfBytesToWrite 个字节的数据将要写入串口的发送数据缓冲区。

DWORDnNumberOfBytesToWrite, //要写入的数据的字节数

LPDWORDlpNumberOfBytesWritten, //指向指向一个DWORD数值,该数值返回实际写入的字节数 

LPOVERLAPPEDlpOverlapped//重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL。

   );

   ReadFile函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。

而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。

  如果操作成功,这两个函数都返回TRUE。

需要注意的是,当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。

例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING。

这说明重叠操作还未完成。

32.例举同步方式读写串口的代码,同步方式读写串口比较简单:

//同步读串口

charstr[100];

DWORDwCount;//读取的字节数

BOOLbReadStat;

bReadStat=ReadFile(hCom,str,100,&wCount,NULL);

if(!

bReadStat)

{

 AfxMessageBox("读串口失败!

");

 returnFALSE;

}returnTRUE;

//同步写串口

 charlpOutBuffer[100];

 DWORDdwBytesWrite=100;

 COMSTATComStat;

 DWORDdwErrorFlags;

 BOOLbWriteStat;

 ClearCommError(hCom,&dwErrorFlags,&ComStat);

 bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,&dwBytesWrite,NULL);

 if(!

bWriteStat)

 {

  AfxMessageBox("写串口失败!

");

 }

 PurgeComm(hCom,PURGE_TXABORT|

  PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

33.在异步重叠操作时,操作还未完成函数就返回。

重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。

有两种方法可以等待操作完成:

一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员;另一种方法是调用GetOverlappedResult函数等待,后面将演示说明。

下面我们先简单说一下OVERLAPPED结构和GetOverlappedResult函数:

OVERLAPPED结构

OVERLAPPED结构包含了重叠I/O的一些信息,定义如下:

typedefstruct_OVERLAPPED{//o 

   DWORD Internal;

   DWORD InternalHigh;

   DWORD Offset;

   DWORD OffsetHigh;

   HANDLEhEvent;

}OVERLAPPED;

GetOverlappedResult函数

BOOLGetOverlappedResult(

   HANDLEhFile,//串口的句柄    

   //指向重叠操作开始时指定的OVERLAPPED结构

   LPOVERLAPPEDlpOverlapped,    

   //指向一个32位变量,该变量的值返回实际读写操作传输的字节数。

   LPDWORDlpNumberOfBytesTransferred,

   //该参数用于指定函数是否一直等到重叠操作结束。

   //如果该参数为TRUE,函数直到操作结束才返回。

   //如果该参数为FALSE,函数直接返回,这时如果操作没有完成,   //通过调用GetLastError()函数会返回ERROR_IO_INCOMPLETE。

   BOOLbWait 

  );

在使用ReadFile和WriteFile重叠操作时,线程需要创建OVERLAPPED结构以供这两个函数使用。

线程通过OVERLAPPED结构获得当前的操作状态,该结构最重要的成员是hEvent。

hEvent是读写事件。

当串口使用异步通讯时,函数返回时操作可能还没有完成,程序可以通过检查该事件得知是否读写完毕。

  当调用ReadFile,WriteFile函数的时候,该成员会自动被置为无信号状态;当异步重叠操作完成后,该成员变量会自动被置为有信号状态。

GetOverlappedResult该函数返回重叠操作的结果,用来判断异步操作是否完成,它是通过判断OVERLAPPED结构中的hEvent是否被置位来实现的。

异步读串口的示例代码:

charlpInBuffer[1024];

DWORDdwBytesRead=1024;

COMSTATComStat;

DWORDdwErrorFlags;

OVERLAPPEDm_osRead;

memset(&m_osRead,0,sizeof(OVERLAPPED));

m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

ClearCommError(hCom,&dwErrorFlags,&ComStat);

dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);

if(!

dwBytesRead)

returnFALSE;

BOOLbReadStatus;

bReadStatus=ReadFile(hCom,lpInBuffer,

     dwBytesRead,&dwBytesRead,&m_osRead);

if(!

bReadStatus)//如果ReadFile函数返回FALSE

{

 if(GetLastError()==ERROR_IO_PENDING)

 //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作

 {

 WaitForSingleObject(m_osRead.hEvent,2000);

 //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟

 //当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号

 PurgeComm(hCom,PURGE_TXABORT|

  PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

 returndwBytesRead;

 }

 return0;

}

PurgeComm(hCom,PURGE_TXABORT|

   PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

returndwBytesRead;

 对以上代码再作简要说明:

在使用ReadFile函数进行读操作前,应先使用ClearCommError函数清除错误。

ClearCommError函数的原型如下:

BOOLClearCommError(

   HANDLEhFile,//串口句柄

   LPDWORDlpErrors,//指向接收错误码的变量

   LPCOMSTATlpStat//指向通讯状态缓冲区

  );

该函数获得通信错误并报告串口的当前状态,同时,该函数清除串口的错误标志以便继续输入、输出操作。

参数lpStat指向一个COMSTAT结构,该结构返回串口状态信息。

本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数。

  最后用PurgeComm函数清空串口的输入输出缓冲区。

这段代码用WaitForSingleObject函数来等待OVERLAPPED结构的hEvent成员。

异步写串口的示例代码:

charbuffer[1024];

DWORDdwBytesWritten=1024;

 DWORDdwErrorFlags;

 COMSTATComStat;

OVERLAPPEDm_osWrite;

 BOOLbWriteStat;

 bWriteStat=WriteFile(hCom,buffer,dwBytesWritten,

 &dwBytesWritten,&m_OsWrite);

 if(!

bWriteStat)

 {

 if(GetLastError()==ERROR_IO_PENDING)

 {

  WaitForSingleObject(m_osWrite.hEvent,1000);

  returndwBytesWritten;

 }

 return0;

 }

 returndwBytesWritten;

(4)关闭串口

BOOLCloseHandle(

   HANDLEhObject;//handletoobjecttoclose

);

补:

1.DBC结构:

 DCB结构包含了串口的各项参数设置,下面仅介绍几个该结构常用的变量:

typedefstruct_DCB{

  ………

  //波特率,指定通信设备的传输速率。

这个成员可以是实际波特率值或者下面的常量值之一:

  DWORDBaudRate;

CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200,CBR_38400,

CBR_56000,CBR_57600,CBR_115200,CBR_128000,CBR_256000,CBR_14400

DWORDfParity;//指定奇偶校验使能。

若此成员为1,允许奇偶校验检查

  …

BYTEByteSize;//通信字节位数,4—8

BYTEParity;//指定奇偶校验方法。

此成员可以有下列值:

EVENPARITY偶校验    NOPARITY无校验

MARKPARITY标记校验  ODDPARITY奇校验

BYTEStopBits;//指定停止位的位数。

此成员可以有下列值:

ONESTOPBIT1位停止位  TWOSTOPBITS2位停止位

ONE5STOPBITS  1.5位停止位

  ………

 }DCB;

winbase.h文件中定义了以上用到的常量。

如下:

#defineNOPARITY           0

#defineODDPARITY          1

#defineEVENPARITY         2

#defineONESTOPBIT         0

#defineONE5STOPBITS       1

#defineTWOSTOPBITS        2

#defineCBR_110            110

#defineCBR_300            300

#defineCBR_600            600

#defineCBR_1200           1200

#defineCBR_2400           2400

#defineCBR_4800           4800

#defineCBR_9600           9600

#defineCBR_14400          14400

#defineCBR_19200          19200

#defineCBR_38400          38400

#defineCBR_56000          56000

#defineCBR_57600          57600

#defineCBR_115200         115200

#defineCBR_128000         128000

#defineCBR_256000         256000

2.超时处理:

 读写串口的超时有两种:

间隔超时和总超时。

间隔超时是指在接收时两个字符之间的最大时延。

总超时是指读写操作总共花费的最大时间。

写操作只支持总超时,而读操作两种超时均支持。

用COMMTIMEOUTS结构可以规定读写操作的超时。

COMMTIMEOUTS结构的定义为:

typedefstruct_COMMTIMEOUTS{  

   DWORDReadIntervalTimeout;//读间隔超时

   DWORDReadTotalTimeoutMultiplier;//读时间系数

   DWORDReadTotalTimeoutConstant;//读时间常量

   DWORDWriteTotalTimeoutMultiplier;//写时间系数

   DWORDWriteTotalTimeoutConstant;//写时间常量

}COMMTIMEOUTS,*LPCOMMTIMEOUTS;

COMMTIMEOUTS结构的成员都以毫秒为单位。

总超时的计算公式是:

总超时=时间系数×要求读/写的字符数+时间常量

例如,要读入10个字符,那么读操作的总超时的计算公式为:

读总超时=ReadTotalTimeoutMultiplier×10+ReadTotalTimeoutConstant

可以看出:

间隔超时和总超时的设置是不相关的,这可以方便通信程序灵活地设置各种超时。

如果所有写超时参数均为0,那么就不使用写超时。

如果ReadIntervalTimeout为0,那么就不使用读间隔超时。

如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则不使用读总超时。

如果读间隔超时被设置成MAXDWORD并且读时间系数和读时间常量都为0,那么在读一次输入缓冲区的内容后读操作就立即返回,而不管是否读入了要求的字符。

  在用重叠方式读写串口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。

在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间。

配置串口的示例代码:

 SetupComm(hCom,1024,1024);//输入缓冲区和输出缓冲区的大小都是1024

 COMMTIMEOUTSTimeOuts; 

 TimeOuts.ReadIntervalTimeout=1000;//设定读超时

 TimeOuts.ReadTotalTimeoutMultiplier=500;

 TimeOuts.ReadTotalTimeoutConstant=5000;

  TimeOuts.WriteTotalTimeoutMultiplier=500;//设定写超时

 TimeOuts.WriteTotalTimeoutConstant=2000;

 SetCommTimeouts(hCom,&TimeOuts);//设置超时

 DCBdcb;

 GetCommState(hCom,&dcb);

 dcb.BaudRate=9600;//波特率为9600

 dcb.ByteSize=8;//每个字节有8位

 dcb.Parity=NOPARITY;//无奇偶校验位

 dcb.StopBits=TWOSTOPBITS;//两个停止位

 SetCommState(hCom,&dcb);

 PurgeComm(hCom,PU

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

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2