串口编程Word文档格式.docx
- 文档编号:623082
- 上传时间:2023-04-29
- 格式:DOCX
- 页数:18
- 大小:22.20KB
串口编程Word文档格式.docx
《串口编程Word文档格式.docx》由会员分享,可在线阅读,更多相关《串口编程Word文档格式.docx(18页珍藏版)》请在冰点文库上搜索。
GENERIC_READ|GENERIC_WRITE,//允许读和写
0,//独占方式
NULL,
OPEN_EXISTING,//打开而不是创建
0,//同步方式
NULL);
if(hCom==(HANDLE)-1)
{
AfxMessageBox("
打开COM失败!
"
);
returnFALSE;
}
returnTRUE;
异步I/O方式代码如下:
hCom=CreateFile("
//COM1口
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,//重叠方式
if(hCom==INVALID_HANDLE_VALUE)
2、配置串口
包括配置串口通讯参数、串口发送和接收缓冲区大小以及读写串口超时设置。
配置通讯参数
DCB(设备控制块)结构包含了串口的各项参数设置,诸如波特率、数据位数、奇偶校验和停止位数等信息。
在查询或配置串口的属性时,都要用DCB结构来作为缓冲区。
DCB结构原型:
typedefstruct_DCB{
……
DWORDBaudRate;
//波特率,指定通信设备的传输速率
DWORDfParity;
//指定奇偶校验使能。
若此成员为1,允许奇偶校验
检查
BYTEByteSize;
//通信字节位数,4—8
BYTEParity;
//指定奇偶校验方法
BYTEStopBits;
//指定停止位的位数。
}DCB,*LPDCB;
可以调用GetCommState函数来获取串口的初始配置。
GetCommState函数可以获得COM口的设备控制块,从而获得相关参数:
BOOLGetCommState(
HANDLEhFile,//标识通讯端口的句柄
LPDCBlpDCB//指向一个设备控制块(DCB结构)的指针
然后,修改DCB结构,然后再调用SetCommState函数修改串口的配置。
SetCommState函数设置COM口的设备控制块:
BOOLSetCommState(
设置缓冲区大小
除了在BCD中的设置外,程序一般还需要设置I/O缓冲区的大小和超时。
Windows用I/O缓冲区来暂存串口输入和输出的数据。
如果通信的速率较高,则应该设置较大的缓冲区。
调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小。
BOOLSetupComm(
HANDLEhFile,//通信设备的句柄
DWORDdwInQueue,//输入缓冲区的大小(字节数)
DWORDdwOutQueue//输出缓冲区的大小(字节数)
设置串口读写超时
在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。
超时的作用是在指定的时间内没有读入或发送指定数量的字符,ReadFile或WriteFile的操作仍然会结束。
调用GetCommTimeouts函数查询当前的超时设置,该函数会填充一个COMMTIMEOUTS结构。
BOOLGetCommTimeouts(
LPCOMMTIMEOUTSlpCommTimeouts//指向一个COMMTIMEOUTS的指针
调用SetCommTimeouts函数,用某一个COMMTIMEOUTS结构的内容来设置超时。
BOOLSetCommTimeouts(
读写串口的超时有两种:
间隔超时和总超时。
间隔超时是指在接收时两个字符之间的最大时延。
总超时是指读写操作总共花费的最大时间。
写操作只支持总超时,而读操作两种超时均支持。
用COMMTIMEOUTS结构可以规定读写操作的超时。
COMMTIMEOUTS结构原型
typedefstruct_COMMTIMEOUTS{
DWORDReadIntervalTimeout;
//读间隔超时
DWORDReadTotalTimeoutMultiplier;
//读时间系数
DWORDReadTotalTimeoutConstant;
//读时间常量
DWORDWriteTotalTimeoutMultiplier;
//写时间系数
DWORDWriteTotalTimeoutConstant;
//写时间常量
}COMMTIMEOUTS,*LPCOMMTIMEOUTS;
总超时的计算公式是:
总超时=时间系数×
要求读/写的字符数+时间常量
例如,要读入10个字符,那么读操作的总超时的计算公式为:
读总超时=ReadTotalTimeoutMultiplier×
10+ReadTotalTimeoutConstant
当总超时或间隔超时为0,表示不使用总超时或间隔超时。
在用重叠方式读写串口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。
在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间。
在读写串口之前,还要用PurgeComm()函数清空缓冲区,该函数原型:
BOOLPurgeComm(
HANDLEhFile,//串口句柄
DWORDdwFlags//需要完成的操作
参数dwFlags指定要完成的操作,可以是下列值的组合:
PURGE_TXABORT中断所有写操作并立即返回,即使写操作还没有完成。
PURGE_RXABORT中断所有读操作并立即返回,即使读操作还没有完成。
PURGE_TXCLEAR清除输出缓冲区
PURGE_RXCLEAR清除输入缓冲区
配置串口的示例代码:
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,&
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
3、读写串口
串口打开了并设置好了相应的参数,接下来就可以对串口进行I/O操作了。
我们用ReadFile和WriteFile来读写串口,下面是两个函数的原型:
BOOLReadFile(
HANDLEhFile,//串口的句柄
LPVOIDlpBuffer,//读入的数据存储的地址,即读入的数据将存储在以该指针的//值为首地址的一片内存区
DWORDnNumberOfBytesToRead,//要读入的数据的字节数
LPDWORDlpNumberOfBytesRead,//指向一个DWORD数值该数值返回读操作实际读//入的字节数
LPOVERLAPPEDlpOverlapped//重叠操作时,该参数指向一个OVERLAPPED结构,//同步操作时,该参数为NULL。
BOOLWriteFile(
LPCVOIDlpBuffer,//写入的数据存储的地址,即以该指针的值为首地址的//nNumberOfBytesToWrite个字节的数据将要写入串口的发送//数据缓冲区。
DWORDnNumberOfBytesToWrite,//要写入的数据的字节数
LPDWORDlpNumberOfBytesWritten,//指向指向一个DWORD数值,该数值返回实际//写入的字节数
LPOVERLAPPEDlpOverlapped//重叠操作时,该参数指向一个OVERLAPPED结构,
//同步操作时,该参数为NULL。
在用ReadFile和WriteFile读写串口时,既可以同步执行,也可以重叠执行。
在同步执行时,函数直到操作完成后才返回。
这意味着同步执行时线程会被阻塞,从而导致效率下降。
在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/O操作在后台进行。
ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定,如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的;
如果未指定重叠标志,则读写操作应该是同步的。
ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。
ReadFile函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。
而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。
如果操作成功,这两个函数都返回TRUE。
需要注意的是,当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。
例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING,这说明重叠操作还未完成。
同步方式读写串口代码如下:
//同步读串口
charstr[100];
DWORDwCount;
//读取的字节数
BOOLbReadStat;
COMSTATComStat;
DWORDdwErrorFlags;
DWORDdwStrLen;
ClearCommError(hCom,&
dwErrorFlags,&
ComStat);
dwStrLen=ComStat.cbInQue;
if(dwStrLen<
=0)
AfxMessageBox("
串口没有数据!
returnFALSE;
bReadStat=ReadFile(hCom,strRec,dwStrLen,&
wCount,NULL);
if(!
bReadStat)
读串口失败!
strRec[wCount]=NULL;
//同步写串口
DWORDdwBytesWrite=100;
CStringSTRSEND(_T(“BBAAC”));
BOOLbWriteStat;
bWriteStat=WriteFile(hCom,STRSEND,STRSEND.GetLength(),&
dwBytesWrite,
bWriteStat)
写串口失败!
PurgeComm(hCom,PURGE_TXABORT|
PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
对以上代码再作简要说明:
在使用ReadFile函数进行读操作前,应先使用
ClearCommError函数清除错误。
ClearCommError函数的原型如下:
BOOLClearCommError(
HANDLEhFile,//串口句柄
LPDWORDlpErrors,//指向接收错误码的变量
LPCOMSTATlpStat//指向通讯状态缓冲区
该函数获得通信错误并报告串口的当前状态,同时,该函数清除串口的错误标志
以便继续输入、输出操作。
参数lpErrors指向一个接收多误码的变量。
错误码定义如下:
Value
Description
CE_BREAK2
Thehardwaredetectedabreakcondition.硬件检测到终端条件
CE_FRAME8
Thehardwaredetectedaframingerror.硬件检测到帧错误
CE_IOE16
AnI/Oerroroccurredduringcommunicationswiththedevice.设备通信发生一个I/O错误
CE_MODE32
Therequestedmodeisnotsupported,orthehFileparameterisinvalid.Ifthisvalueisspecified,itistheonlyvaliderror.不被支持的模式,或者是无效的句柄.如果这个值被指定,则是唯一的有效错误
CE_OVERRUN128
Acharacter-bufferoverrunhasoccurred.Thenextcharacterislost.字符缓冲区溢出,下一个字符将丢失
CE_RXOVER512
Aninputbufferoverflowhasoccurred.
Thereiseithernoroomintheinputbuffer,oracharacterwasreceivedaftertheend-of-file(EOF)character.接收缓冲区发生溢出错误.接收缓冲区没有足够的空间,或者有字符出现在了EOF字符后
CE_RXPARITY1024
Thehardwaredetectedaparityerror.硬件检测到了奇偶校验错误
CE_TXFULL2048
Theapplicationtriedtotransmitacharacter,buttheoutputbufferwasfull.应用程序尝试发送一个字符,但是发送缓冲区已经满了.
参数lpStat指向一个COMSTAT结构,该结构返回串口状态信息。
COMSTAT结
构包含串口的信息,结构定义如下:
typedefstruct_COMSTAT{//cst
DWORDfCtsHold:
1;
//TxwaitingforCTSsignal
DWORDfDsrHold:
//TxwaitingforDSRsignal
DWORDfRlsdHold:
//TxwaitingforRLSDsignal
DWORDfXoffHold:
//Txwaiting,XOFFcharrec'
'
d
DWORDfXoffSent:
//Txwaiting,XOFFcharsent
DWORDfEof:
//EOFcharactersent
DWORDfTxim:
//characterwaitingforTx
DWORDfReserved:
25;
//reserved
DWORDcbInQue;
//bytesininputbuffer
DWORDcbOutQue;
//bytesinoutputbuffer
}COMSTAT,*LPCOMSTAT;
本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数。
在重叠操作时,操作还未完成ReadFile和WriteFile函数就返回。
重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。
有两种方法可以等待操作完成:
一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员;
另一种方法是调用GetOverlappedResult函数等待,后面将演示说明。
下面我们先简单说一下OVERLAPPED结构和GetOverlappedResult函数:
OVERLAPPED结构
OVERLAPPED结构包含了重叠I/O的一些信息,定义如下:
typedefstruct_OVERLAPPED{//o
DWORDInternal;
DWORDInternalHigh;
DWORDOffset;
DWORDOffsetHigh;
HANDLEhEvent;
}OVERLAPPED;
在使用ReadFile和WriteFile重叠操作时,线程需要创建OVERLAPPED结构以供这两个函数使用。
线程通过OVERLAPPED结构获得当前的操作状态,该结构最重要的成员是hEvent。
hEvent是读写事件。
当串口使用异步通讯时,函数返回时操作可能还没有完成,程序可以通过检查该事件得知是否读写完毕。
当调用ReadFile,WriteFile函数的时候,该成员会自动被置为无信号状态;
当重叠操作完成后,该成员变量会自动被置为有信号状态。
GetOverlappedResult函数
BOOLGetOverlappedResult(
HANDLEhFile,//串口的句柄
//指向重叠操作开始时指定的OVERLAPPED结构
LPOVERLAPPEDlpOverlapped,
//指向一个32位变量,该变量的值返回实际读写操作传输的字节数。
LPDWORDlpNumberOfBytesTransferred,
//该参数用于指定函数是否一直等到重叠操作结束。
//如果该参数为TRUE,函数直到操作结束才返回。
//如果该参数为FALSE,函数直接返回,这时如果操作没有完成,
//通过调用GetLastError()函数会返回ERROR_IO_INCOMPLETE。
BOOLbWait
该函数返回重叠操作的结果,用来判断异步操作是否完成,它是通过判断OVERLAPPED结构中的hEvent是否被置位来实现的。
异步读串口的示例代码:
charlpInBuffer[1024];
DWORDdwBytesRead=1024;
OVERLAPPEDm_osRead;
memset(&
m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
dwBytesRead)
BOOLbReadStatus;
bReadStatus=ReadFile(hCom,lpInBuffer,
dwBytesRead,&
m_osRead);
bReadStatus)//如果ReadFile函数返回FALSE
//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
if(GetLastError()==ERROR_IO_PENDING)
//使用WaitForSingleObject函数等待,直到读操作完
//成或延时已达到2秒钟
WaitForSingleObject(m_osRead.hEvent,2000);
//当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 串口 编程