#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "PORT.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
DCB dcb;
COMMTIMEOUTS CommTimerOuts;
HANDLE hCom= INVALID_HANDLE_VALUE;
OVERLAPPED m_overlappedRead;
OVERLAPPED m_overlappedWrite;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//通訊端口是否打開(kāi)
inline bool IsOpen()
{
return hCom != INVALID_HANDLE_VALUE;
}
//設置超時(shí)
void SetTimerOut(unsigned long dwTimerOut= 5000)
{
if(!IsOpen())
{
return;
}
CommTimerOuts.ReadIntervalTimeout= MAXDWORD;
CommTimerOuts.ReadTotalTimeoutConstant= 0;
CommTimerOuts.ReadTotalTimeoutMultiplier= 0;
CommTimerOuts.WriteTotalTimeoutConstant= dwTimerOut;
CommTimerOuts.WriteTotalTimeoutMultiplier= 0;
SetCommTimeouts(hCom, &CommTimerOuts);
}
//設置DCB參數
bool SetDCBParm(unsigned long xBabd, unsigned char xDataSize,
unsigned char xParity, unsigned char xStopBit)
{
if(!IsOpen())
{
return false;
}
if (!GetCommState(hCom, &dcb))
{
#ifdef _DEBUG
printf ("錯誤: %d << 等到通訊口參數失敗.\n", GetLastError());
#endif
ClosePort();
return (false);
}
//設置通訊參數
dcb.DCBlength= sizeof(DCB);
dcb.BaudRate = xBabd; // set the baud rate
dcb.ByteSize = xDataSize; // data size, xmit, and rcv
dcb.Parity = xParity; // no parity bit
dcb.StopBits = xStopBit; // one stop bit
if (!SetCommState(hCom, &dcb))
{
#ifdef _DEBUG
printf ("錯誤: %d << 設置通訊端口參數失敗.\n", GetLastError());
#endif
ClosePort();
return (false);
}
return true;
}
//設置端口緩沖區大小
bool SetPortBuffSize(unsigned long InputBuffSize, unsigned long OutputBuffSize)
{
if(!IsOpen())
{
return false;
}
if(!SetupComm(hCom, InputBuffSize, OutputBuffSize))
{
#ifdef _DEBUG
printf ("錯誤: %d << 設置通訊端口緩沖失敗.\n", GetLastError());
#endif
ClosePort();
return (false);
}
return true;
}
//清理所有緩沖區
void ClearBuffer()
{
if(!IsOpen())
{
return;
}
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
}
//當前接收緩沖區字節數目;
unsigned long GetInBuffCount()
{
if(!IsOpen())
{
return(0);
}
DWORD dwErrorFalgs;
COMSTAT Comstat;
ClearCommError(hCom, &dwErrorFalgs, &Comstat);
return Comstat.cbInQue;
}
//當前發(fā)送緩沖區字節數目;
unsigned long GetOutBuffCount()
{
if(!IsOpen())
{
return false;
}
DWORD dwErrorFalgs;
COMSTAT Comstat;
ClearCommError(hCom, &dwErrorFalgs, &Comstat);
return Comstat.cbOutQue;
}
///打開(kāi)串口////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool OpenPort(unsigned long xPort, unsigned long xBabd, unsigned char xDataSize,
unsigned char xParity, unsigned char xStopBit, unsigned long InputBuffSize,
unsigned long OutputBuffSize, unsigned long dwTimerOut)
{
if(IsOpen())
{
ClosePort();
}
//設置事件
memset(&m_overlappedRead,0,sizeof(OVERLAPPED));
m_overlappedRead.hEvent= CreateEvent(NULL,FALSE,TRUE,"portread");
ASSERT(m_overlappedRead.hEvent != INVALID_HANDLE_VALUE);
memset(&m_overlappedWrite,0,sizeof(OVERLAPPED));
m_overlappedWrite.hEvent= CreateEvent(NULL,FALSE,TRUE,"portwrite");
ASSERT(m_overlappedWrite.hEvent != INVALID_HANDLE_VALUE);
//取得串口字符
char com_str[255];
strcpy(com_str, "COM");
ltoa(xPort, com_str + 3, 10);
//打開(kāi)通訊端口
hCom = CreateFile(com_str,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL
);
if (hCom == INVALID_HANDLE_VALUE)
{
#ifdef _DEBUG
printf ("錯誤: %d << 打開(kāi)通訊口失敗,請檢查是否已經(jīng)安裝串口設備.\n", GetLastError());
#endif
return (false);
}
SetPortBuffSize(InputBuffSize,OutputBuffSize);
SetDCBParm(xBabd,xDataSize,xParity,xStopBit);
SetTimerOut(dwTimerOut);
//清理緩沖器
PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
//啟動(dòng)成功
#ifdef _DEBUG
printf ("成功開(kāi)啟端口 %d.\n", com_str);
#endif
return(true);
}
//關(guān)閉串口;
void ClosePort()
{
if(IsOpen())
{
CloseHandle(hCom);
hCom= INVALID_HANDLE_VALUE;
}
//ResetEvent(m_overlappedRead.hEvent);
//ResetEvent(m_overlappedWrite.hEvent);
if(m_overlappedRead.hEvent!=NULL)
{
CloseHandle(m_overlappedRead.hEvent);
}
if(m_overlappedWrite.hEvent!=NULL)
{
CloseHandle(m_overlappedWrite.hEvent);
}
}
//異步讀數據
unsigned long ReadChar(unsigned long dwBufferLength, char *buff, unsigned long dwWaitTime=20)
{
if(!IsOpen())
{
return(0);
}
DWORD dwError;
COMSTAT Stat;
if(::ClearCommError(hCom, &dwError, &Stat) && dwError > 0) //清除錯誤
{
::PurgeComm(hCom, PURGE_RXABORT | PURGE_RXCLEAR); /*清除輸入緩沖區*/
return 0;
}
if(!Stat.cbInQue)// 緩沖區無(wú)數據
{
return 0;
}
unsigned long uReadLength = 0;
dwBufferLength = dwBufferLength - 1 > Stat.cbInQue ? Stat.cbInQue : dwBufferLength - 1;
if(!::ReadFile(hCom, buff, dwBufferLength, &uReadLength, &m_overlappedRead)) //2000 下 ReadFile 始終返回 True
{
if(::GetLastError() == ERROR_IO_PENDING) // 結束異步I/O
{
WaitForSingleObject(m_overlappedRead.hEvent, dwWaitTime); //等待20ms
if(!::GetOverlappedResult(hCom, &m_overlappedRead, &uReadLength, false))
{
if(::GetLastError() != ERROR_IO_INCOMPLETE)//其他錯誤
{
uReadLength = 0;
}
}
}
else
{
uReadLength = 0;
}
}
return uReadLength;
}
//異步寫(xiě)數據
unsigned long WriteChar(unsigned long dwBufferLength, char *buff)
{
if(!IsOpen())
{
return 0;
}
DWORD dwError;
if(ClearCommError(hCom, &dwError, NULL) && dwError > 0) //清除錯誤
{
PurgeComm(hCom, PURGE_TXABORT | PURGE_TXCLEAR);
}
unsigned long uWriteLength = 0;
if(!WriteFile(hCom, buff, dwBufferLength, &uWriteLength, &m_overlappedWrite))
{
if(GetLastError() == ERROR_IO_PENDING)
{
DWORD m_tmp=0;
m_tmp= WaitForSingleObject(m_overlappedWrite.hEvent, 1000);
if(m_tmp== WAIT_TIMEOUT || m_tmp== WAIT_ABANDONED)
{
return(0);
}
else if(m_tmp== WAIT_OBJECT_0)
{
if(!GetOverlappedResult(hCom,&m_overlappedWrite,&uWriteLength,false))
{
return(0);
}
else
{
return uWriteLength;
}
}
uWriteLength = 0;
}
}
return uWriteLength;
}