异步串口通信VC++
本文参考MSDN及相关网上文章。
//////////////////////////////////////////////
//MyComm.h 多机控制 异步串口通信
//说不定能有用上的。
//////////////////////////////////////////////
class CMyComm
{
public:
CMyComm();
virtual ~CMyComm();
void PreOpenSetupQueue(DWORD dwInQueue, DWORD dwOutQueue);
// size of input buffer, size of output buffer
BOOL Open(int nPort, int nBaud);
//默认无校验,每个字节发送11个bit,异步方式。
//若设置校验后,校验错则字节被替换为0x7E
BOOL SetupQueue(DWORD dwInQueue, DWORD dwOutQueue);
// size of input buffer, size of output buffer
BOOL ResetParity(char Parity);//parity = 'N', 'O', 'E', 'M', 'S' 不区分大小写
//分别表示 no, odd, even, mark, space
// 在Open()前设置无效。
BOOL SendData(LPCVOID lpBuf, DWORD dwToWrite);
DWORD ReadData(LPVOID lpBuf, DWORD dwToRead);
void Close();
protected:
HANDLE m_hCom;
BOOL m_bOpened;
OVERLAPPED m_osReader;
OVERLAPPED m_osWriter;
DWORD m_dwInBuf;
DWORD m_dwOutBuf;
};
//////////////////////////////////////////////////////////
//MyComm.cpp
#include "stdafx.h"
#include "MyComm.h"
///////////////////////////////////////////
CMyComm::CMyComm()
{
m_bOpened = FALSE;
m_dwInBuf = 512;
m_dwOutBuf = 512;
m_hCom = NULL;
}
void CMyComm::PreOpenSetupQueue(DWORD dwInQueue, DWORD dwOutQueue)
{
m_dwInBuf = dwInQueue;
m_dwOutBuf = dwOutQueue;
}
BOOL CMyComm::Open(int nPort, int nBaud)
{
ASSERT(nPort > 0 || nPort < 5 || nBaud >= 110 || nBaud <= 128000);
if( m_bOpened ) return TRUE;
char szPort[15];
char lpDef[15];
DCB dcb = {0};
dcb.DCBlength = sizeof(dcb);
wsprintf(szPort, "COM%d", nPort);
wsprintf(lpDef, "%d,n,8,1", nBaud);
m_hCom = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if( m_hCom == INVALID_HANDLE_VALUE ) return FALSE;
FillMemory(&m_osReader, sizeof(OVERLAPPED), 0);
FillMemory(&m_osWriter, sizeof(OVERLAPPED), 0);
m_osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_osWriter.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
int byteUsedTime = 14400 / nBaud +1;
COMMTIMEOUTS timeouts = {20 + byteUsedTime, byteUsedTime, 1000, byteUsedTime , 20};
dcb.fParity = TRUE;
dcb.fErrorChar = TRUE;
dcb.ErrorChar = '~';
if( m_osReader.hEvent == NULL || m_osWriter.hEvent == NULL
|| !SetCommTimeouts(m_hCom, &timeouts)
|| !BuildCommDCB(lpDef, &dcb) || !SetupComm(m_hCom, m_dwInBuf, m_dwOutBuf)) {
if( m_osReader.hEvent != NULL )
CloseHandle( m_osReader.hEvent );
if( m_osWriter.hEvent != NULL )
CloseHandle( m_osWriter.hEvent );
CloseHandle( m_hCom );
return FALSE;
}
m_bOpened = TRUE;
return m_bOpened;
}
BOOL CMyComm::SetupQueue(DWORD dwInQueue, DWORD dwOutQueue)
{
if (m_hCom == NULL) return FALSE;
m_dwInBuf = dwInQueue;
m_dwOutBuf = dwOutQueue;
return SetupComm(m_hCom, m_dwInBuf, m_dwOutBuf);
}
BOOL CMyComm::ResetParity(char Parity)
{
if (m_hCom == NULL) return FALSE;
DCB dcb;
dcb.DCBlength = sizeof( DCB );
if (!GetCommState(m_hCom, &dcb)) return FALSE;
BYTE cParity;
Parity = tolower(Parity);
switch (Parity) {
case 'o':
cParity = 1;
break;
case 'e':
cParity = 2;
break;
case 'm':
cParity = 3;
break;
case 's':
cParity = 4;
break;
default:
cParity = 0;
break;
}
dcb.Parity = cParity;
return SetCommState(m_hCom, &dcb);
}
BOOL CMyComm::SendData(LPCVOID lpBuf, DWORD dwToWrite)
{
TRACE("SSSSSSSSSSSSS 00\n");
if( !m_bOpened || m_hCom == NULL ) return FALSE;
DWORD dwWritten;
if (WriteFile(m_hCom, lpBuf, dwToWrite, &dwWritten, &m_osWriter)) return TRUE;
if (GetLastError() != ERROR_IO_PENDING) return FALSE;
GetOverlappedResult(m_hCom, &m_osWriter, &dwWritten, TRUE);
TRACE("SSSSSSSSSSSSS 11\n");
return (dwToWrite == dwWritten);
}
DWORD CMyComm::ReadData(LPVOID lpBuf, DWORD dwToRead)
{
TRACE("RRRRRRRRRRRR 00\n");
if( !m_bOpened || m_hCom == NULL ) return 0;
DWORD dwRead;
if (ReadFile(m_hCom, lpBuf, dwToRead, &dwRead, &m_osReader) ) return dwRead;
if (GetLastError() != ERROR_IO_PENDING) return 0;
if (WaitForSingleObject(m_osReader.hEvent, INFINITE) != WAIT_OBJECT_0 )
return 0;
if (!GetOverlappedResult(m_hCom, &m_osReader, &dwRead, FALSE) )
return 0;
TRACE("RRRRRRRRRRRR 11\n");
return dwRead;
}
void CMyComm::Close()
{
if (m_osReader.hEvent != NULL) CloseHandle( m_osReader.hEvent );
if (m_osWriter.hEvent != NULL) CloseHandle( m_osWriter.hEvent );
if (m_hCom != NULL) CloseHandle( m_hCom );
m_bOpened = FALSE;
}
CMyComm::~CMyComm()
{
Close();
}
///////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// main.cpp
char Buf[40];
int nArray[3];
CMyComn myCom;
UINT SendDataProc(LPVOID pParam);
void OnCommSendReceive()
{
myCom.PreOpenSetupQueue(12, 12);
if (!myCom.Open(2, 4800)) return;
//如果想改变校验位,在此位置,如:myCom.ResetParity('m');
FillMemory(Buf, 40, 0);
nArray[0] = 0;
nArray[1] = 17;
nArray[2] = 88888;
AfxBeginThread(SendDataProc, (LPVOID)(12));
TRACE("EEEEEEEE\n");
int nRead = myCom.ReadData(Buf, 12);
int* nA = (int*) Buf;
TRACE("AAAAAAAAAAAAAA %d, %d %d %d\n",nRead, nA[0], nA[1], nA[1]);
}
UINT SendDataProc(LPVOID pParam)
{
return myCom.SendData((LPVOID)nArray, (DWORD) pParam);
}