📄 win95界面下的vc++串口通讯程序.txt
字号:
+ ReadToTaltimeoutConstant
WriteTotalTimeout = (WriteTotalTimeoutMuliplier * bytes_to_write)
+ WritetoTotalTimeoutConstant
NOTE:在设置超时时参数0为无限等待,既无超时
参数MAXDWORD为立即返回
超时设置:
GetCommTimeouts(hComm,&timeouts);
SetCommTimeouts(hComm,&timeouts);
10.查询方式读写数据
例程:
COMMTIMEOUTS to;
DWORD ReadThread(LPDWORD lpdwParam)
{
BYTE inbuff[100];
DWORD nBytesRead;
if(!(cp.dwProvCapabilities&PCF_INTTIMEOUTS))
return 1L;
memset(&to,0,sizeof(to));
to.ReadIntervalTimeout = MAXDWORD;
SetCommTimeouts(hComm,&to);
while(bReading)
{
if(!ReadFile(hComm,inbuff,100,&nBytesRead,NULL))
locProcessCommError(GetLastError());
else
if(nBytesRead)
locProcessBytes(inbuff,nBytesRead);
}
PurgeComm(hComm,PURGE_RXCLEAR);
return 0L;
}
NOTE:
PurgeComm()是一个清除函数,它可以中止任何未决的后台读或写,并且
可以冲掉I/O缓冲区.
BOOL PurgeComm(HANDLE hFile,DWORD dwFlags);
dwFlages的有效值:
PURGE_TXABORT: 中止后台写操作
PRUGE_RXABORT: 中止后台读操作
PRUGE_TXCLEAR: 清除发送缓冲区
PRUGE_RXCLEAR: 清除接收缓冲区
技巧:
可通过ClearCommError()来确定接收缓区中处于等待的字节数。
BOOL ClearCommError(
HANDLE hFile, // handle to communications device
LPDWORD lpErrors, // pointer to variable to receive error codes
LPCOMSTAT lpStat // pointer to buffer for communications status
);
ClearCommError()将返回一个COMSTAT结构:
typedef struct _COMSTAT { // cst
DWORD fCtsHold : 1; // Tx waiting for CTS signal
DWORD fDsrHold : 1; // Tx waiting for DSR signal
DWORD fRlsdHold : 1; // Tx waiting for RLSD signal
DWORD fXoffHold : 1; // Tx waiting, XOFF char rec`d
DWORD fXoffSent : 1; // Tx waiting, XOFF char sent
DWORD fEof : 1; // EOF character sent
DWORD fTxim : 1; // character waiting for Tx
DWORD fReserved : 25; // reserved
DWORD cbInQue; // bytes in input buffer
DWORD cbOutQue; // bytes in output buffer
} COMSTAT, *LPCOMSTAT;
其中的cbInQue和cbOutQue中即为缓冲区字节。
11.同步I/O读写数据
COMMTIOMOUTS to;
DWORD ReadThread(LPDWORD lpdwParam)
{
BYTE inbuff[100];
DWORD nByteRead,dwErrorMask,nToRead;
COMSTAT comstat;
if(!cp.dwProvCapabilities&PCF_TOTALTIMEOUTS)
return 1L;
memset(&to,0,sizeof(to));
to.ReadTotalTimeoutMultiplier = 5;
to.ReadTotalTimeoutConstant = 50;
SetCommTimeouts(hComm,&to);
while(bReading)
{
ClearCommError(hComm,&dwErrorMask,&comstat);
if(dwErrorMask)
locProcessCommError(dwErrorMask);
if(comstat.cbInQue >100)
nToRead = 100;
else
nToRead = comstat.cbInQue;
if(nToRead == 0)
continue;
if(!ReadFile(hComm,inbuff,nToRead,&nBytesRead,NULL))
locProcessCommError(GetLastError());
else
if(nBytesRead)
locProcessBytes(inbuff,nBytesRead);
}
return 0L;
}
12.异步I/O读写数据
当CreateFile()中的fdwAttrsAndFlags参数为FILE_FLAG_OVERLAPPEN时,
端口是为异步I/O打开的,此时可以在ReadFile的最后一个参数中指定一个
OVERLAPPED结构,使数据的读操作在后台进行。WINDOWS 95包括了异步
I/O的许多变种。
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;
对于串行口仅hEvent成员有效,其于成员必须为0。
例程:
COMMTIMEOUTS to;
...
DWORD ReadThread((LPDWORD lpdwParam)
{
BYTE inbuff[100];
DWORD nRytesRead,endtime,lrc;
static OVERLAPPED o;
if(!cp.dwProvCapabilities & PCF_TOTALTIMEOUTS)
return 1L;
memset(&to,0,sizeof(to));
to.ReadTotalTimeoutMultiplier = 5;
to.ReadTotalTimeoutConstant = 1000;
SetCommTimeouts(hComm,&to);
o.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
while(bReading)
{
if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o))
{
nBytesRead = 0;
if(lrc=GetLastError() == ERROR_IO_PENDING)
{
endtime = GetTickCount() + 1000;
while(!GetOverlappedResult(hComm,&o,&nBytesRead,FALSE))
if(GetTickCount() > endtime) break;
}
if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
}
else
{
if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
ResetEvent(o.hEvent);
}
}
PurgeComm(hComm,PURGE_RXCLEAR);
return 0L;
}
这一例程是对一开始读缓冲区就读到所需的字节时的处理:
while(bReading)
{
if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o))
{
if((lrc=GetLastError()) ==ERROR_IO_PENDING)
{
if(GetOverlappedResult(hComm,&o,&nBytesRead,TRUE))
{
if(nBytesRead)
locProcessBytesa(inbuff,nBytesRead);
}
else
locProcessCommError(GetLastError());
}
else
locProcessCommError(GetLastError));
}
else
if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
ResetEvent(o.hEvent);
}
13.事件驱I/O读写:
GetCommMask(hComm,&dwMask)
Windows 95报告给应用程序的事件由此方法返回。
SetCommMasl(hComm,&dwMask)
添加或修改Windows 95所报告的事件列表。
事件掩码如下:
EV_BREAK 检测到输入为止
EV_CTS CTS(清除发送)信号改变状态
EV_DSR DSR(数据设置就绪)信号改变状态
EV_ERR 发生了线路状态错误.
线路状态错误为:
CE_FRAME(帧错误)
CE_OVERRUN(接收缓冲区超限)
CE_RXPARITY(奇偶校验错误)
EV_RING 检测到振铃
EV_RLSD RLSD(接收线路信号检测)信号改变状态
EV_EXCHAR 接收到一个字符,并放入输入缓冲区
EV_RXFLAG 接收到事件字符(DCB成员的EvtChar成员),度放入输入缓冲区
EV_TXEMPTY 输出缓冲区中最后一个字符发送出去
在用SetCommMask指定了有用的事件后,应用程序可调用WaitCommEvent()来等
待事件发生.
BOOL WaitCommEvent(
HANDLE hFile, // handle of communications device
LPDWORD lpEvtMask, // address of variable for event that occurred
LPOVERLAPPED lpOverlapped, // address of overlapped structure
);
此方法可以以同步或异步方式操作
例程:
COMMTIMEOUTS to;
...
DWORD ReadTherad(LPDWORD lpdwParam)
{
BYTE binbuff[100];
DWORD nBytesRead,dwEvent,dwError;
COMSTAT cs;
SetCommMask(hComm,EV_RXHAR);
while(bReading)
{
if(WaitCommEvent(hComm,&dwEvent,NULL))
{
ClearCommError(hComm,&dwError,&cs);
if((dwEvent&EV_RXCHAR)&&cs.cbInQue)
{
if(!ReadFile(hComm,inbuff,cs.cbInQue,&nBytesRead,NULL)
locProcessCommError(GetLastError());
}
else
{
if(nByteRead)
locProcessBytes(inbuff,nBytesRead);
}
else
locProcessCommError(GetLastError());
}
PurgeComm(hComm,PURGE_RXCLEAR);
return 0L;
}
NOTE: SetCommMask(hComm,0)可使WaitCommEvent()中止.
可使用GetCommmodemStatus()方法,例程:
if(cp.dwProvCapabilities&PCF_RTSCTS)
{
SetCommMask(hComm,EV_CTS);
WaitCommEvent(hComm,&dwMask,NULL);
if(dwMask&EV_CTS)
{
GetCommModemStatus(hComm,&dwStatus)
if(dwStatus&MS_CTS_ON) /* CTS stransition OFF-ON */
else /* CTS stransition ON-OFF */
}
}
MS_CTS_ON CTS为ON
MS_DSR_ON DSR为ON
MS_RING_ON RING为ON
MS_ELSD_ON RLSD为ON
14.错误
当发生错误时应用方法ClearCommError(hComm,&dwErrorMask,&constat)
得到错误掩码。
CE_BREAK 中止条件
CE_FRAME 帧错误
CW_IOE 一般I/O错误,常伴有更为详细的错误标志
CE_MODE 不支持请求的模式
CE_OVERRUN 缓冲区超限下一个字符将丢失
CE_RXOVER 接收缓冲区超限
CE_RXPARITY 奇偶校验错误
CE_TXFULL 发送缓冲区满
CE_DNS 没有选择并行设备
CE_PTO 并行设备发生超时
CE_OOP 并行设备缺纸
15.控制命令
EscapeCommFunction()可将硬件信号置ON或OFF,模拟XON或XOFF
BOOL EscapeCommFunction(
HANDLE hFile, // handle to communications device
DWORD dwFunc // extended function to perform
);
dwFunc的有效值(可用‘|’同时使用多个值)
CLRDTR DTR置OFF
CLRRTS RTS置OFF
SETDTR STR置ON
SETRTS TRS置ON
SETXOFF 模拟XOFF字符的接收
SETXON 模拟XON字符的接收
SETBREAK 在发送中产生一个中止
CLRBREAK 在发送中清除中止
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -