#include <windows.h>
#include <stdio.h>
#include <l_str.h>
#include <comm.h>
static LPSTR defaultSetting = "COM1\x0 baud=9600 parity=N data=8 stop=1";
#define INCREASE_BUF_LEN 1024
CComm::CComm(CommCallbackFunc fOnReceive, void *parm)
: m_hHasData(NULL)
, m_hPort(INVALID_HANDLE_VALUE) // invalidate to start
, m_baudRate(9600)
, m_Parity(NOPARITY)
, m_StopBits(ONESTOPBIT)
, m_nPort(1)
, m_hThread(NULL)
, m_bWantExitThread(FALSE)
, m_bThreadExited(TRUE)
, m_fOnReceive(fOnReceive)
, m_parm(parm)
, m_nBytesUnread(0)
, m_nBufLen(INCREASE_BUF_LEN)
{
m_ovRead.hEvent = m_ovWrite.hEvent = NULL;
memset(&m_ovRead, 0, sizeof(m_ovRead));
memset(&m_ovWrite, 0, sizeof(m_ovWrite));
if ((m_ovRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL )) == NULL)
throw "can't create event1 in CComm::CComm";
if ((m_ovWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL )) == NULL)
throw "can't create event2 in CComm::CComm";
m_hHasData = CreateEvent(NULL, TRUE, FALSE, NULL);
m_pRecvBuf = 0;
}
CComm::~CComm()
{
Close();
if (m_ovRead.hEvent != NULL)
CloseHandle(m_ovRead.hEvent);
if (m_ovWrite.hEvent != NULL)
CloseHandle(m_ovWrite.hEvent);
if (m_pRecvBuf)
delete m_pRecvBuf;
}
void WINAPI CComm::THWorker(CComm *comm)
{
try {
comm->Worker();
}catch(...){ // const char *s) {
// TRACE("Exception in CComm::THworker %s", s);
comm->m_bThreadExited = TRUE;
}
}
void CComm::Worker()
{
m_bThreadExited = TRUE;
if (m_hPort == INVALID_HANDLE_VALUE ||
!SetCommMask(m_hPort, EV_RXCHAR ) ) {
return;
}
m_bThreadExited = FALSE;
m_bWantExitThread = FALSE;
while ( !m_bWantExitThread ) {
DWORD dwEvtMask = 0;
WaitCommEvent( m_hPort, &dwEvtMask, NULL );
if(m_bWantExitThread)
break;
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) {
Sleep(10);
OnReceive();
if(m_fOnReceive != NULL)
m_fOnReceive(this, m_parm);
}
}
m_bThreadExited = TRUE;
}
void CComm::SetBaud( int baud )
{
if(m_baudRate != baud) {
m_baudRate = baud;
if(IsOpen()) {
Close();
Open();
}
}
}
void CComm::SetPort( int n )
{
if(m_nPort != n) {
m_nPort = n;
if(IsOpen()) {
Close();
Open();
}
}
}
int CComm::GetInCount()
{
COMSTAT statPort;
DWORD dwErrorCode;
if(IsOpen()) {
ClearCommError(m_hPort, &dwErrorCode, &statPort);
return statPort.cbInQue;
}
return 0;
}
BOOL CComm::Open()
{
char sCom[20];
COMMTIMEOUTS CommTimeOuts ;
if(IsOpen())
Close();
InitializeCriticalSection(&m_BufSection);
m_pRecvBuf = new char[m_nBufLen];
if (m_pRecvBuf == 0){
return FALSE;
}
sprintf(sCom, "COM%d", m_nPort);
m_hPort = CreateFile(sCom, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
if (m_hPort == INVALID_HANDLE_VALUE) {
// TRACE("Error Open %s", sCom);
return FALSE;
}
// get any early notifications
SetCommMask( m_hPort, EV_RXCHAR ) ;
// setup device buffers
SetupComm(m_hPort, COMM_BUF_LEN, COMM_BUF_LEN);
// purge any information in the buffer
PurgeComm(m_hPort, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR);
// set up for overlapped I/O
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 1500;
CommTimeOuts.ReadTotalTimeoutConstant = 15000;
// write timeout = WriteTotalTimeoutMultiplier * bytes_to_send + WriteTotalTimeoutConstant
// CBR_9600 is approximately 1byte/ms. so if baud rate < 9600
// we can use CBR_9600/rate to estimate the timeout.
// if > 9600, use 1. here, we use 10 to all.
CommTimeOuts.WriteTotalTimeoutMultiplier = 100;
CommTimeOuts.WriteTotalTimeoutConstant = 2000; //-1; //!! orginal is 0 ;
SetCommTimeouts( m_hPort, &CommTimeOuts ) ;
DCB dcbPort;
dcbPort.DCBlength = sizeof( DCB ) ;
if (GetCommState(m_hPort, &dcbPort)) {
// fill in the fields of the structure
dcbPort.BaudRate = m_baudRate;
dcbPort.ByteSize = 8;
dcbPort.Parity = m_Parity;
dcbPort.StopBits = m_StopBits;
/*
// no flow control
dcbPort.fOutxCtsFlow = FALSE;
dcbPort.fOutxDsrFlow = FALSE;
dcbPort.fOutX = FALSE;
dcbPort.fInX = FALSE;
*/
/*
// DsrDtrFlowControl
dcbPort.fOutxCtsFlow = FALSE;
dcbPort.fOutxDsrFlow = TRUE;
dcbPort.fDtrControl = DTR_CONTROL_HANDSHAKE;
dcbPort.fOutX = FALSE;
dcbPort.fInX = FALSE;
*/
/*
// xon/xoff control
dcbPort.fOutxCtsFlow = FALSE;
dcbPort.fOutxDsrFlow = FALSE;
dcbPort.fOutX = TRUE;
dcbPort.fInX = TRUE;
dcbPort.XonChar = 0x11;
dcbPort.XoffChar = 0x13;
dcbPort.XoffLim = 512;
dcbPort.XonLim = 512;
*/
dcbPort.fBinary = TRUE ;
// dcbPort.fParity = TRUE ;
SetCommState(m_hPort, &dcbPort);
EscapeCommFunction( m_hPort, SETDTR ) ;
}
DWORD dwThreadId;
m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)THWorker,
this, CREATE_SUSPENDED, &dwThreadId);
if(m_hThread==NULL)
throw "CComm::Open can't create worker thread";
m_nBytesUnread = 0;
// SetThreadPriority(m_hThread, THREAD_PRIORITY_ABOVE_NORMAL);
ResumeThread(m_hThread);
return TRUE;
}
BOOL CComm::Open(const char * lpSetting)
{
DCB d; char sCom[32];
LPSTR lps = NULL;
const char * lpCommName;
memset(&d, 0, sizeof(d));
lpCommName = lpSetting;
if (lpSetting != NULL && (lps = strchr(lpSetting, ':')) != NULL)
lps += 1;
if (lpCommName == NULL)
lpCommName = defaultSetting;
if (lps == NULL){
lps = defaultSetting + 6;
}
if (strnicmp(lpCommName, "COM", 3) != 0)
return FALSE;
COMMCONFIG cc; DWORD dwSize = sizeof(cc);
getaword(sCom, (char *)lpCommName, ':');
memset(&cc, 0, sizeof(cc));
cc.dcb.DCBlength = sizeof(DCB);
BOOL bisok = GetDefaultCommConfig(sCom, &cc, &dwSize);
memcpy(&d, &cc.dcb, sizeof(d));
if (BuildCommDCB(lps, &d) == 0) // ep. "baud=1200 parity=N data=8 stop=1 "
return FALSE;
m_Parity = d.Parity;
m_StopBits = d.StopBits;
m_nPort = int(lpCommName[3] - '0');
m_baudRate = d.BaudRate;
return Open();
}
void CComm::Close()
{
if(!m_bThreadExited) {
m_bWantExitThread = TRUE;
SetCommMask( m_hPort, 0 ) ;
if (WaitForSingleObject(m_hThread, 2000) != WAIT_OBJECT_0)
TerminateThread(m_hThread, 0);
CloseHandle(m_hThread);
m_hThread = NULL;
}
if (m_hPort != INVALID_HANDLE_VALUE) {
EscapeCommFunction( m_hPort, CLRDTR ) ;
// purge any outstanding reads/writes and close device handle
PurgeComm( m_hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
CloseHandle(m_hPort);
m_hPort = INVALID_HANDLE_VALUE;
}
m_nBytesUnread = 0;
DeleteCriticalSection(&m_BufSection);
if (m_pRecvBuf != 0){
delete[] m_pRecvBuf; m_pRecvBuf = 0;
}
m_nBufLen = INCREASE_BUF_LEN;
}
int CComm::ReadComm(void *lpszBlock, int nMaxLength) // return bytes write
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
// only try to read number of bytes in queue
ClearCommError( m_hPort, &dwErrorFlags, &ComStat ) ;
dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
if(dwLength==0)
return 0;
if ((fReadStat = ReadFile(m_hPort, lpszBlock, dwLength, &dwLength, &m_ovRead)) == 0){
if (GetLastError() == ERROR_IO_PENDING){
// OutputDebugString("\n\rIO Pending");
// We have to wait for read to complete.
// This function will timeout according to the
// CommTimeOuts.ReadTotalTimeoutConstant variable
// Every time it times out, check for port errors
while(!GetOverlappedResult( m_hPort, &m_ovRead, &dwLength, TRUE )){
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
// normal result if not finished
con
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
serialport.rar (2个子文件)
comm.h 2KB
comm.cpp 13KB
共 2 条
- 1
资源评论
- wnarutou2016-10-31不错,值得学习
- lcn20132017-11-27很好,不错的封装
- fanfuns2012-06-21写的很不错的串口通信接口
liangar
- 粉丝: 2
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功