·异步串口I/O:
BOOL GetCommMask(
HANDLE hFile,
LPDWORD lpEvtMask
);
BOOL SetCommMask(
HANDLE hFile,
DWORD dwEvtMask
);
BOOL WaitCommEvent(
HANDLE hFile,
LPDWORD lpEvtMask,
LPOVERLAPPED lpOverlapped
);
GetCommMask函数用于得到串口已经设置了的串口事件,参数hFile指定已打开的串口句柄,参数lpEvtMask用于存取得到的串口事件集。SetCommMask函数的功能与GetCommMask函数正好相反,用于设置串口事件集。WaitCommEvent函数用于等待预先设置的串口事件中的某一个事件发生,该函数将阻塞线程,直到预先设置的串口事件中的某一事件的发生。参数lpEvtMask用于存储已经发生的事件,参数lpOverlapped必须设置为NULL,因为在Windows CE中不支持重叠I/O操作。
串口时间表:
EV_BREAK |
检测到中断发生 |
EV_CTS |
CTS信号改变了状态 |
EV_DSR |
DSR信号改变了状态 |
EV_ERR |
串口驱动程序检测到了错误,如CE_RXPARITY,CE_OVERRUN,CE_FRAME |
EV_RING |
检测到振铃 |
EV_RLSD |
RLSD信号改变了状态 |
EV_RXCHAR |
接收到了一个字符 |
EV_RXFLAG |
接收到了一个事件字符 |
EV_TXEMPTY |
在输出缓冲区中的最后一个字符被发送 |
·设置端口读写超时:
BOOL GetCommTimeouts(
HANDLE hFile,
LPCOMMTIMEOUTS lpCommTimeouts
);
BOOL SetCommTimeouts(
HANDLE hFile,
LPCOMMTIMEOUTS lpCommTimeouts
);
在用ReadFile和WriteFile读写串口时,需要考虑超时问题。如果在指定的时间内没有读出或者写入指定数量的字节数据,那么ReadFile函数或者WriteFile函数就会返回。GetCommTimeouts函数用来查询当前的超时时间设置,该函数会填充一个COMMTIMEOUTS结构。SetCommTimeouts函数用来通过一个COMMTIMEOUTS结构设置超时时间。两个函数的返回值都是成功时返回非零值,失败时返回零。
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; /*读间隔超时*/
DWORD ReadTotalTimeoutMultiplier; /*读时间系数*/
DWORD ReadTotalTimeoutConstant; /*读时间常量*/
DWORD WriteTotalTimeoutMultiplier; /*写时间系数*/
DWORD WriteTotalTimeoutConstant; /*写时间常量*/
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
ReadIntervalTimeout:以毫秒为单位设置通信线路上的两个字符到达之间最大时间间隔。在ReadFile操作期间,从接收到第一个字符开始计时。如果任意两个字符到达之间的时间间隔超过这个最大值,则ReadFile操作完成,返回缓冲数据。如果该值设置为0,则不使用间隔超时。
ReadTotalTimeoutMultiplier:读时间系数。以毫秒为单位设置一个用来计算读操作总超时时间的时间系数。
ReadTotalTimeoutConstant:读时间常量。以毫秒为单位设置一个用来计算读操作总超时时间的时间常量。
读总超时时间 = 读时间系数*要读的字节数 + 读时间常量
WriteTotalTimeoutMultiplier:写时间系数。以毫秒为单位设置一个用来计算写操作总超时时间的时间系数。
WriteTotalTimeoutConstant:写时间常量。以毫秒为单位设置一个用来计算写操作总超时时间的时间常量。
写总超时时间 = 写时间系数*要写的字节数 + 写时间常量
超时有间隔超时和总超时两种类型。间隔超时是指在接收时两个字符之间的最大时延。从串口读取数据时,当接收到一个字节时,通信驱动程序启动一个内部定时器开始计时,在下一个字节到来之前,如果定时器时间超过了间隔超时时间,读操作就会被放弃。总超时是指读操作或者写操作总共花费的最大时间。写操作只支持总超时,读操作对两种类型的超时都支持。
如果应用程序将ReadIntervalTimeout和ReadTotalTimeoutMultiplier设置为MAXDWORD,并且将ReadTotalTimeoutConstant设置为大于0并且小于MAXDWORD的数,则调用ReadFile函数时,会有以下情况:
1 如果接收缓冲区中有字符存在,则ReadFile函数立即返回这些字符。
2 如果接收缓冲区中没有字符,则ReadFile函数会等待直到一个字符到达,然后立即返回。
3 若在ReadTotalTimeoutConstant设定的时间内没有任何字符到达,则ReadFile超时返回。
间隔超时和总超时的设置是不相关的。
下面列举一些情况:
1 有读间隔超时,读总超时,写总超时:将COMMTIMEOUTS结构中的五个成员设置为相应值。
2 有读总超时,写总超时:将ReadIntervalTimeout设置为0,将其他成员设置为相应值。
3 在读一次输入缓冲区中的内容后,读操作就立即完成,不管是否读入了要求的字符:将ReadIntervalTimeout设置为MAXDWORD,
将ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都设置为0。
4 ReadFile没有超时设置,直到有适当的字符数返回或者错误发生,该函数才返回:将ReadIntervalTimeout,ReadTotalTimeoutMultiplier和
ReadTotalTimeoutConstant都设置为0。
5 WriteFile没有超时设置:将WriteTotalTimeoutMultiplier和
WriteTotalTimeoutConstant都设置为0。
例:
——————————————————————————————————
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts(m_hComm, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = 100;/* 接收字符间最大时间间隔 */
CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
CommTimeOuts.ReadTotalTimeoutConstant = 100;/* 读数据总超时常量 */
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(m_hComm, &CommTimeOuts);
——————————————————————————————————
——————————————————————————————————
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts (m_hComm, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 10;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
SetCommTimeouts( m_hComm, &CommTimeOuts )