/*-----------------------
Developed by Nefarian Zhu
Version 1.00 for Alpha LTD
All rights reserved .
QQ 909990295
------------------------*/
#ifndef H_H_CSERIALPORT
#define H_H_CSERIALPORT
#include <iostream>
#include <windows.h>
#include <process.h>
//Define function pointer
typedef void(*pFunction)(void);
class CSerialPort
{
private:
HANDLE m_hCom, m_hEvent;
DCB m_dcb;
COMMTIMEOUTS m_to;
COMSTAT m_comStat;
DWORD m_dwRead, m_dwWrite;
DWORD m_inBufSize, m_outBufSize;
pFunction m_pDelegateFunc;
BOOL m_bCloseCom;
BOOL m_bThreadRunning;
private:
template <class ToType, class FromType>
void GetMemberFuncAddr_VC6(ToType& addr,FromType f);
void static ThreadProc(void *pThis);
public:
CSerialPort();
~CSerialPort();
BOOL ScanComs(char *pPortsName);
BOOL Open(LPCTSTR lpCom = "COM1");
BOOL Setting(LPCTSTR lpConfig = "9600,n,8,1");
BOOL SetBufferSize(DWORD cbInQue = 512, DWORD cbOutQue = 512);
BOOL SetCommTimeouts(DWORD dwReadTimeOut = 100,
DWORD dwWriteTimeOut = 100);
BOOL Read(LPVOID lpBuffer);
BOOL Write(LPVOID lpBuffer,DWORD nNumberOfBytesToWrite);
BOOL Close();
template <class FromType>
void BindDelegateFunc(FromType f);
};
CSerialPort::CSerialPort()
{
m_hCom = NULL;
m_hEvent = CreateEvent(NULL, true, false, NULL);
memset(&m_dcb, 0, sizeof(DCB));
memset(&m_to, 0, sizeof(COMMTIMEOUTS));
memset(&m_comStat, 0, sizeof(COMSTAT));
m_dwRead = 0;
m_dwWrite = 0;
m_inBufSize = 512;
m_outBufSize = 512;
m_pDelegateFunc = NULL;
m_bCloseCom = FALSE;
m_bThreadRunning = FALSE;
}
CSerialPort::~CSerialPort()
{
if (m_hCom != NULL)
Close();
}
//Function to get address of member function in class
template <class ToType, class FromType>
void CSerialPort::GetMemberFuncAddr_VC6(ToType& addr,FromType f)
{
union
{
FromType _f;
ToType _t;
}ut;
ut._f = f;
addr = ut._t;
}
//Get all local host coms from Regedit
BOOL CSerialPort::ScanComs(char *pPortsName)
{
HKEY hkey = 0;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_READ, &hkey);
DWORD dIndex = 0;
DWORD dwNameRead = 128;
DWORD dwValuRead = 128;
char szName[128] = "";
char szValue[128] = "";
short sIndex = 0;
while (RegEnumValue(hkey, dIndex++, szName,
&dwNameRead, NULL, NULL,
(LPBYTE)szValue, &dwValuRead) == ERROR_SUCCESS)
{
strcat(pPortsName, szValue);
strcat(pPortsName, "\n");
memset(szValue, 0, sizeof(szValue));
dwValuRead = 128;
}
}
//Open specified com
BOOL CSerialPort::Open(LPCTSTR lpCom)
{
m_hCom = CreateFile(lpCom, GENERIC_READ | GENERIC_WRITE,
0, 0, OPEN_EXISTING, 0, 0);
if (m_hCom == INVALID_HANDLE_VALUE)
{
return FALSE;
}
else
{
return TRUE;
}
}
//Set com (baudrate,parity,stopbits)
BOOL CSerialPort::Setting(LPCTSTR lpConfig)
{
BuildCommDCB(lpConfig, &m_dcb);
SetCommState(m_hCom,&m_dcb);
}
//Set com IO buff size
BOOL CSerialPort::SetBufferSize(DWORD cbInQue, DWORD cbOutQue)
{
m_inBufSize = cbInQue;
m_outBufSize = cbOutQue;
SetupComm(m_hCom, m_inBufSize, m_outBufSize);
}
//Set com IO time for timeout
BOOL CSerialPort::SetCommTimeouts(DWORD dwReadTimeOut, DWORD dwWriteTimeOut)
{
m_to.ReadTotalTimeoutConstant = dwReadTimeOut;
m_to.WriteTotalTimeoutConstant = dwWriteTimeOut;
::SetCommTimeouts(m_hCom, &m_to);
}
//Read com from output buff
BOOL CSerialPort::Read(LPVOID lpBuffer)
{
DWORD dwError = 0;
ClearCommError(m_hCom, &dwError, &m_comStat);
if ( (m_comStat.cbInQue == 0) || (dwError != 0) )
{
return FALSE;
}
ReadFile(m_hCom, lpBuffer, m_comStat.cbInQue, &m_dwRead, NULL);
}
//Write data to input buff
BOOL CSerialPort::Write(LPVOID lpBuffer,DWORD nNumberOfBytesToWrite)
{
WriteFile(m_hCom, lpBuffer, nNumberOfBytesToWrite, &m_dwWrite, NULL);
}
//Close com
BOOL CSerialPort::Close()
{
if (m_bThreadRunning == TRUE)
{
m_bCloseCom = TRUE;
WaitForSingleObject(m_hEvent, 2000);
}
CloseHandle(m_hCom);
}
//Bind fuction to deal with RX_CHAR event
template <class FromType>
void CSerialPort::BindDelegateFunc(FromType f)
{
DWORD dwAddr = 0;
GetMemberFuncAddr_VC6(dwAddr, f);
assert(dwAddr != 0);
m_pDelegateFunc = (pFunction)dwAddr;
_beginthread(ThreadProc,0,this);
}
//Thread proc for RX_CHAR
void CSerialPort::ThreadProc(void *pThis)
{
CSerialPort *pCSerialPort = (CSerialPort*)pThis;
pCSerialPort->m_bThreadRunning = TRUE;
while (TRUE)
{
if (pCSerialPort->m_bCloseCom == TRUE)
{
SetEvent(pCSerialPort->m_hEvent);
pCSerialPort->m_bThreadRunning = FALSE;
return;
}
DWORD dwError = 0;
ClearCommError(pCSerialPort->m_hCom, &dwError, &pCSerialPort->m_comStat);
if ( (pCSerialPort->m_comStat.cbInQue == 0) || (dwError != 0) )
{
Sleep(10);
continue;
}
else
{
pCSerialPort->m_pDelegateFunc();
}
}
}
#endif /*-----H_H_CSERIALPORT-----*/
我寫的串口同步通信類------適合初學者
最新推荐文章于 2024-02-15 20:36:47 发布