#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
HANDLE hComm;
OVERLAPPED m_ov;
COMSTAT comstat;
DWORD m_dwCommEvents;
//如果在调用CreateFile创建句柄时指
//定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进
//行的操作就应该是重叠的;如果未指定
//重叠标志,则读写操作应该是同步的
//在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从
//而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费
//时的I/O操作在后台进行
bool openport(char *portname)//打开一个串口
{
hComm = CreateFile(portname,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
return FALSE;
else
return true;
}
bool setupdcb(int rate_arg)
{
DCB dcb;
int rate= rate_arg;
memset(&dcb,0,sizeof(dcb)); //在一段内存块中填充某个给定的值,是对较大的结构//体或数组进行清零操作的一种最快方法
if(!GetCommState(hComm,&dcb))//获取当前DCB配置
{
return FALSE;
}
/* -------------------------------------------------------------------- */
// set DCB to configure the serial port
dcb.DCBlength = sizeof(dcb);
/* ---------- Serial Port Config ------- */
dcb.BaudRate = rate;
dcb.Parity = NOPARITY;
dcb.fParity = 0;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;
dcb.fOutxCtsFlow = 0;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = 0;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutX = 0;
dcb.fInX = 0;
/* ----------------- misc parameters ----- */
dcb.fErrorChar = 0;
dcb.fBinary = 1;
dcb.fNull = 0;
dcb.fAbortOnError = 0;
dcb.wReserved = 0;
dcb.XonLim = 2;
dcb.XoffLim = 4;
dcb.XonChar = 0x13;
dcb.XoffChar = 0x19;
dcb.EvtChar = 0;
/* -------------------------------------------------------------------- */
// set DCB
if(!SetCommState(hComm,&dcb))
{
return false;
}
else
return true;
}
//在用readfile和writefile读写串行口时,需要考虑超时问题, 读写串口的超时有两
//种:间隔超时和总超时, 写操作只支持总超时,而读操作两种超时均支持, 如果所有
//写超时参数均为0,那么就不使用写超时。
bool setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant)
{
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout=ReadInterval; //读间隔超时
timeouts.ReadTotalTimeoutConstant=ReadTotalconstant; //读时间系数
timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier; //读时间常量
timeouts.WriteTotalTimeoutConstant=WriteTotalconstant; // 写时间系数
timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier; //写时间常//量, 总超时的计算公式是:总超时=时间系数×要求读/写的字符数+时间常量
if(!SetCommTimeouts(hComm, &timeouts))
{
return false;
}
else
return true;
}
void ReceiveChar(){
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
char RXBuff;
while(true){
bResult = ClearCommError(hComm, &dwError, &comstat);
// 在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误
if(comstat.cbInQue==0)// COMSTAT结构返回串口状态信息
//本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数
continue;
if(bRead){
bResult = ReadFile(hComm, // Handle to COMM port串口的句柄
&RXBuff,// RX Buffer Pointer// 读入的数据存储的地址,即读入的数据将存//储在以该指针的值为首地址的一片内存区
1,// Read one byte要读入的数据的字节数,
&BytesRead, // Stores number of bytes read, 指向一个DWORD//数值,该数值返回读操作实际读入的字节数
&m_ov); // pointer to the m_ov structure// 重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL
printf("%c",RXBuff);
if (!bResult){// 当ReadFile和WriteFile返回FALSE时,不一定就是操作失//败,线程应该调用GetLastError函数分析返回的结果
switch (dwError = GetLastError()){
case ERROR_IO_PENDING:
bRead = FALSE;
break;
default:break;
}
}else{
bRead = TRUE;
}
} // close if (bRead)
if (!bRead){
bRead = TRUE;
bResult = GetOverlappedResult(hComm, // Handle to COMM port
&m_ov, // Overlapped structure
&BytesRead, // Stores number of bytes read
TRUE); // Wait flag
}
}
}
BOOL WriteChar(BYTE* m_szWriteBuffer,DWORD m_nToSend){
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD BytesSent = 0;
HANDLE m_hWriteEvent;
ResetEvent(m_hWriteEvent);
if (bWrite){
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
// Clear buffer
bResult = WriteFile(hComm, // Handle to COMM Port, 串口的句柄
m_szWriteBuffer, // Pointer to message buffer in calling finction
// 即以该指针的值为首地址的nNumberOfBytesToWrite
// 个字节的数据将要写入串口的发送数据缓冲区
m_nToSend, // Length of message to send, 要写入的数据的字节数
&BytesSent, // Where to store the number of bytes sent
// 指向指向一个DWORD数值,该数值返回实际写入的字节数
&m_ov ); // Overlapped structure
// 重叠操作时,该参数指向一个OVERLAPPED结构,
// 同步操作时,该参数为NULL
if (!bResult){ // 当ReadFile和WriteFile返回FALSE时,不一定就是操作失
//败,线程应该调用GetLastError函数分析返回的结果
DWORD dwError = GetLastError();
switch (dwError){
case ERROR_IO_PENDING: //GetLastError函数返回//ERROR_IO_PENDING。这说明重叠操作还未完成
// continue to GetOverlappedResults()
BytesSent = 0;
bWrite = FALSE;
break;
default:break;
}
}
} // end if(bWrite)
if (!bWrite){
bWrite = TRUE;
bResult = GetOverlappedResult(hComm, // Handle to COMM port
&m_ov, // Overlapped structure
&BytesSent, // Stores number of bytes sent
TRUE); // Wait flag
// deal with the error code
if (!bResult){
printf("GetOverlappedResults() in WriteFile()");
}
} // end if (!bWrite)
// Verify that the data size send equals what we tried to send
if (BytesSent != m_nToSend){
printf("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)m_szWriteBuffer));
}
return true;
}
void main(){
if(openport("com4"))
printf("open comport success\n");
if(setupdcb(115200))
printf("setupDCB success\n");
if(setuptimeout(0,0,0,0,0)) //如果所有写超时参数均为0,那么就不使用写超时
printf("setuptimeout success\n");
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // 在读写串口之前,还要用PurgeComm()函数清空缓冲区
//PURGE_TXABORT 中断所有写操作并立即返回,即使写操作还没有完成。
//PURGE_RXABORT 中断所有读操作并立即返回,即使读操作还没有完成。
//PURGE_TXCLEAR 清除输出缓冲区
//PURGE_RXCLEAR 清除输入缓冲区
//WriteChar("please send data now",20);
printf("received data:\n");
ReceiveChar( );
system("pause");
}