#define _StkComm_H
#include <Windows.h>
#include <process.h>
#include <string>
#include <list>
#include "def.h"
using namespace std;
//串口数据回调函数
typedef void(CALLBACK *OnComDataCallback)(DWORD dwSize, const char *pData);
class CStkComm
{
public:
CStkComm();
~CStkComm();
//打开串口
bool Open(DWORD dwPort, DWORD dwBaudRate, BYTE btParity = NOPARITY, BYTE btByteSize = 8, BYTE btStopBits = ONESTOPBIT);
//关闭串口
void Close();
void SetCommDataCallback(OnComDataCallback pComDataCallback);
void SendCommData(const string &str);
protected:
static unsigned __stdcall RecvCommDataThread(void *pParam);
static unsigned __stdcall SendCommDataThread(void *pParam);
private:
HANDLE m_hComm;
bool m_bRun;
HANDLE m_hRecv, m_hSend;
CRITICAL_SECTION m_cs;
list<string> m_listData;
OnComDataCallback m_pOnCommData;
};
#endif
#include "StkComm.h"
#include <assert.h>
CStkComm::CStkComm()
: m_hComm(INVALID_HANDLE_VALUE)
{
m_bRun = false;
m_pOnCommData = NULL;
m_hRecv = NULL;
m_hSend = NULL;
InitializeCriticalSection(&m_cs);
}
CStkComm::~CStkComm()
{
m_listData.clear();
DeleteCriticalSection(&m_cs);
}
bool CStkComm::Open(DWORD dwPort, DWORD dwBaudRate, BYTE btParity, BYTE btByteSize, BYTE btStopBits)
{
assert(dwPort>=1 && dwPort<=1024);
if(INVALID_HANDLE_VALUE != m_hComm)
{
CloseHandle(m_hComm);
m_hComm = INVALID_HANDLE_VALUE;
}
char szName[64] = "";
sprintf_s(szName,64,"COM%d",dwPort);
m_hComm = CreateFileA(szName,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if(INVALID_HANDLE_VALUE == m_hComm)
{
return false;
}
BOOL bRet = SetupComm(m_hComm,dwInQueue,dwOutQueue);
if(!bRet)
{
return false;
}
DCB dcb;
memset(&dcb,0,sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
bRet = GetCommState(m_hComm,&dcb);
if(!bRet)
{
return false;
}
dcb.BaudRate = dwBaudRate;
dcb.ByteSize = btByteSize;
dcb.Parity = btParity;
dcb.StopBits = btStopBits;
//dcb.fParity = (btParity != 0);
bRet = SetCommState(m_hComm,&dcb);
if(!bRet)
{
return false;
}
COMMTIMEOUTS CommTimeouts;
CommTimeouts.ReadIntervalTimeout = 500;//! 配置超时结构 字符最小间隔100ms
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 250;//! 读超时 阻塞I/O模式下250毫秒
CommTimeouts.WriteTotalTimeoutMultiplier = 0;
CommTimeouts.WriteTotalTimeoutConstant = 250;
bRet = SetCommTimeouts(m_hComm,&CommTimeouts);
if(!bRet)
{
return false;
}
m_bRun = true;
m_hRecv = (HANDLE)_beginthreadex(NULL,0,&RecvCommDataThread,this,0,NULL);
if(0 == m_hRecv)
{
return false;
}
m_hSend = (HANDLE)_beginthreadex(NULL,0,&SendCommDataThread,this,0,NULL);
if(0 == m_hSend)
{
return false;
}
return true;
}
void CStkComm::Close()
{
m_bRun = false;
if(0 != m_hRecv)
{
WaitForSingleObject(m_hRecv,INFINITE);
CloseHandle(m_hRecv);
}
if(0 != m_hSend)
{
WaitForSingleObject(m_hSend,INFINITE);
CloseHandle(m_hSend);
}
m_listData.clear();
if(INVALID_HANDLE_VALUE != m_hComm)
{
CloseHandle(m_hComm);
m_hComm = INVALID_HANDLE_VALUE;
}
}
void CStkComm::SetCommDataCallback(OnComDataCallback pComDataCallback)
{
m_pOnCommData = pComDataCallback;
}
void CStkComm::SendCommData(const string &str)
{
EnterCriticalSection(&m_cs);
m_listData.push_back(str);
LeaveCriticalSection(&m_cs);
}
unsigned __stdcall CStkComm::RecvCommDataThread(void *pParam)
{
CStkComm *p = (CStkComm*)pParam;
char buf[1024] = "";
DWORD dwRead;
COMSTAT ComStat;
DWORD dwErrorFlags;
while(p->m_bRun)
{
memset(buf,0,1024);
ClearCommError(p->m_hComm,&dwErrorFlags,&ComStat);
ReadFile(p->m_hComm,(LPVOID)buf,/*ComStat.cbInQue*/1024,&dwRead,NULL);
if(dwRead > 0)
{
p->m_pOnCommData(dwRead,buf);
}
Sleep(10);
}
return 0;
}
unsigned __stdcall CStkComm::SendCommDataThread(void *pParam)
{
CStkComm *p = (CStkComm*)pParam;
DWORD dwWrite;
while(p->m_bRun)
{
while(!p->m_listData.empty())
{
string str = p->m_listData.front();
WriteFile(p->m_hComm,str.c_str(),str.length(),&dwWrite,NULL);
EnterCriticalSection(&p->m_cs);
p->m_listData.pop_front();
LeaveCriticalSection(&p->m_cs);
}
Sleep(10);
}
return 0;
}