📄 ceseries.cpp
字号:
// CEseries.cpp : implementation file
//
#include "stdafx.h"
#include "CcerisePort.h"
#include "CEseries.h"
#ifdef _DEBUG
//#define new DEBUG_NEW@
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CCEseries
IMPLEMENT_DYNCREATE(CCEseries, CCmdTarget)
CCEseries::CCEseries()
{
m_hcomm = INVALID_HANDLE_VALUE;
}
CCEseries::~CCEseries()
{
}
BEGIN_MESSAGE_MAP(CCEseries, CCmdTarget)
//{{AFX_MSG_MAP(CCEseries)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCEseries message handlers
bool CCEseries::CloseProt()
{
if(m_hcomm == INVALID_HANDLE_VALUE)
{
return TRUE;
}
CloseReadThread();
//CloseWriteThread();
if(!CloseHandle(m_hcomm))
{
return FALSE;
}
else
{ m_hcomm = INVALID_HANDLE_VALUE;
return TRUE;
}
}
void CCEseries::CloseReadThread()
{
SetEvent(m_hreadcloseEvent);
SetCommMask(m_hcomm,0);
PurgeComm(m_hcomm,PURGE_RXCLEAR);
if(WaitForSingleObject(m_hreadThread,1000) == WAIT_TIMEOUT)
{
TerminateThread(m_hreadThread,0);
}
m_hreadThread = NULL;
}
bool CCEseries::OpenProt(CWnd *pProtOwner, UINT ProtNo, UINT baud,UINT parity,UINT databits,UINT stopBITS)
{
DCB dcb;
char szProt[15];
//已经打开直接返回
if(m_hcomm != INVALID_HANDLE_VALUE)
{
return TRUE;
}
ASSERT(pProtOwner != NULL);
ASSERT(ProtNo>0 && ProtNo<5);
//设置串口名字
sprintf(szProt,"COM%d",ProtNo);
//打开串口
m_hcomm = CreateFile(
szProt,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if(m_hcomm == INVALID_HANDLE_VALUE)
{
TRACE(_T("CreateFile返回无效句柄"));
return FALSE;
}
dcb.BaudRate = baud; //波特率
dcb.fBinary = TRUE; //必须为TRUE,支持2进制
dcb.fParity = TRUE; //支持校验
dcb.ByteSize = databits; //数据位
dcb.Parity = ODDPARITY; //奇校验
dcb.StopBits = stopBITS; //停止位
dcb.fOutxCtsFlow = FALSE; // No CTS output flow control
dcb.fOutxDsrFlow = FALSE; // No DSR output flow control
dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type
dcb.fDsrSensitivity = FALSE; // DSR sensitivity
dcb.fTXContinueOnXoff = TRUE; // XOFF continues Tx
dcb.fOutX = FALSE; // No XON/XOFF out flow control
dcb.fInX = FALSE; // No XON/XOFF in flow control
dcb.fErrorChar = FALSE; // Disable error replacement
dcb.fNull = FALSE; // Disable null stripping
dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control
dcb.fAbortOnError = FALSE; // 当串口发生错误,并不终止串口读写
if(!GetCommState(m_hcomm,&dcb))
{
int Error = GetLastError();
TRACE(_T("SetCommState erroe"));
return FALSE;
}
//设置串口读写时间
COMMTIMEOUTS Commtimeouts;
GetCommTimeouts(m_hcomm,&Commtimeouts);
Commtimeouts.ReadIntervalTimeout = MAXDWORD;
Commtimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
Commtimeouts.ReadTotalTimeoutConstant = 50;
Commtimeouts.WriteTotalTimeoutMultiplier = 50;
Commtimeouts.WriteTotalTimeoutConstant = 2000;
if(!SetCommTimeouts(m_hcomm,&Commtimeouts))
{
AfxMessageBox("设置超时失败");
return FALSE;
}
m_portowner=pProtOwner;
//指定端口事件
SetCommMask(m_hcomm,EV_RXCHAR);
//分配设备内存
SetupComm(m_hcomm,4096,4096);
//清除缓存信息
PurgeComm(m_hcomm,PURGE_TXCLEAR|PURGE_RXCLEAR);
//创建读写事件
m_hreadcloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_hwritecloseEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
//创建读线程
m_hreadThread = CreateThread(NULL,0,ReadTheadFun,this,0,
&m_hreadThreadID);
//创建写线程
//m_hwriteThread = CreateThread(NULL,0,WriteThreadFunc,this,0,
// &m_hwriteThreadID);
TRACE(_T("串口打开成功"));
return TRUE;
}
DWORD CCEseries::WriteThreadFunc(LPVOID lparme)
{
CCEseries *cEseries = (CCEseries*)lparme;
MSG msg;
DWORD dwWriteLen = 0;
BYTE *buf = NULL;
while(TRUE)
{
//得到线程消息
if(PeekMessage(&msg,0,0,0,PM_NOREMOVE))
{
if(msg.hwnd != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
if(msg.message == CM_THREADCOMMWRITE)
{
buf = (BYTE*)msg.lParam;
dwWriteLen = msg.wParam;
try
{
WriteProt(cEseries->m_hcomm,buf,dwWriteLen);
}catch(...)
{
//
}
//delete [] buf;
}
}
if(WaitForSingleObject(cEseries->m_hreadcloseEvent,500) ==
WAIT_OBJECT_0)
{
break;
}
cEseries->m_hreadThread = NULL;
}
return 0;
}
DWORD CCEseries::ReadTheadFun(LPVOID lparam)
{
CCEseries *Ceseries=(CCEseries*)lparam;
DWORD evtMask = 0;
BYTE *Readbuf = NULL;//
DWORD ActualReadLen = 0;
DWORD WillReadLen;
DWORD dwReadErrors;
COMSTAT cmstate;
OVERLAPPED osReader = {0};
BOOL bResult = TRUE;
ASSERT(Ceseries->m_hcomm != INVALID_HANDLE_VALUE);
PurgeComm(Ceseries->m_hcomm,PURGE_TXCLEAR|PURGE_RXCLEAR);
AfxMessageBox("串口没有数据1");
Sleep(2000);
SetCommMask(Ceseries->m_hcomm,EV_RXCHAR|EV_CTS|EV_DSR);
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL)
{
AfxMessageBox("错误");
}
// Error creating overlapped event; abort.
ResetEvent(osReader.hEvent);
while(TRUE)
{
bResult = WaitCommEvent(Ceseries->m_hcomm,&evtMask,&osReader);
if(!bResult)
{
switch(dwReadErrors = GetLastError())
{
case ERROR_IO_PENDING:
{
Sleep(2000);
AfxMessageBox("串口没有数据");
break;
}
case 87:
{ Sleep(2000);
AfxMessageBox("串口系统错误");
break;
}
default:
{
AfxMessageBox("串口其他错误");
Sleep(2000);
break;
}
}
}
else
{
if((evtMask & EV_RXCHAR) == EV_RXCHAR)
{
ClearCommError(Ceseries->m_hcomm,&dwReadErrors,&cmstate);
WillReadLen = cmstate.cbInQue;
if(WillReadLen<=0)
{
continue;
}
Readbuf = new BYTE[WillReadLen];
// DWORD dwRead;
DWORD dwRes;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED asReader = {0};
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.
asReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ASSERT(osReader.hEvent != NULL);
if (!fWaitingOnRead)
{
// Issue read operation.
if (!ReadFile(Ceseries->m_hcomm, Readbuf, WillReadLen, &ActualReadLen, &osReader))
{
if (GetLastError() != ERROR_IO_PENDING)
{// read not delayed?
// Error in communications; report it.
AfxMessageBox("错误");
}
else
{
fWaitingOnRead = TRUE;
}
}
else
{
AfxMessageBox("成功读数据");
}
}
if (fWaitingOnRead)
{
dwRes = WaitForSingleObject(osReader.hEvent, 500);
switch(dwRes)
{
// Read completed.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(Ceseries->m_hcomm, &osReader, &ActualReadLen, FALSE))
// Error in communications; report it.
AfxMessageBox("错误");
else
AfxMessageBox("成功");
if(ActualReadLen>0)
{
//回调函数启动
Ceseries->m_OnSeriseRead(Ceseries->m_portowner,Readbuf,
ActualReadLen);
}
// Reset flag so that another opertion can be issued.
fWaitingOnRead = FALSE;
break;
case WAIT_TIMEOUT:
// Operation isn't complete yet. fWaitingOnRead flag isn't
// changed since I'll loop back around, and I don't want
// to issue another read until the first one finishes.
//
// This is a good time to do some background work.
break;
default:
// Error in the WaitForSingleObject; abort.
// This indicates a problem with the OVERLAPPED structure's
// event handle.
break;
}
}
}
//ReadFile(Ceseries->m_hcomm,Readbuf,WillReadLen,&ActualReadLen,0);
}
//如果接收到读线程退出信号则退出
if(WaitForSingleObject(Ceseries->m_hreadcloseEvent,500) ==
WAIT_OBJECT_0)
{
break;
}
}
CloseHandle(osReader.hEvent);
return 0;
}
BOOL CCEseries::WriteProt(HANDLE hcomm, const BYTE *buf, DWORD buflen)
{
OVERLAPPED osWrite = {0};
// Create this write operation's OVERLAPPED structure's hEvent.
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
{
// error creating overlapped event handle
return FALSE;
}
DWORD dwNumByteWrite =0;
bool fRes;
DWORD dwRes;
DWORD dwHaveByteWrite = 0;
ASSERT(hcomm != INVALID_HANDLE_VALUE);
//AfxMessageBox("准备发送");
if(!WriteFile(hcomm,buf,buflen,&dwNumByteWrite,&osWrite))
{
if(GetLastError() != ERROR_IO_PENDING)
{
// WriteFile failed, but isn't delayed. Report error and abort.
fRes = FALSE;
}
// // Write is pending
else
{
dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
switch(dwRes)
{
// OVERLAPPED structure's event has been signaled.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hcomm, &osWrite, &dwNumByteWrite, FALSE))
fRes = FALSE;
else
// Write operation completed successfully.
// dwHaveByteWrite = dwHaveByteWrite+dwNumByteWrite;
//写入完成
//AfxMessageBox("数据发送");
// Sleep(2000);
fRes = TRUE;
break;
default:
// An error has occurred in WaitForSingleObject.
// This usually indicates a problem with the
// OVERLAPPED structure's event handle.
fRes = FALSE;
break;
}
}
}
else
fRes = TRUE;
CloseHandle(osWrite.hEvent);
return fRes;
}
BOOL CCEseries::WritePort(const BYTE *buf, DWORD buflen)
{
//将要发的消息传到消息队列中
if(PostThreadMessage(m_hwriteThreadID,CM_THREADCOMMWRITE,
WPARAM(buflen),WPARAM(buf)))
{
return TRUE;
}
//int Error = GetLastError();
return FALSE;
}
BOOL CCEseries::SetSeriesTimeout(COMMTIMEOUTS CommTimeout)
{
ASSERT(m_hcomm = INVALID_HANDLE_VALUE);
return SetCommTimeouts(m_hcomm,&CommTimeout);
}
void CCEseries::CloseWriteThread()
{
SetEvent(m_hwritecloseEvent);
//SetCommMask(m_hcomm,0);
PurgeComm(m_hcomm,PURGE_RXCLEAR);
if(WaitForSingleObject(m_hwriteThread,10000) == WAIT_TIMEOUT)
{
TerminateThread(m_hwriteThread,0);
}
m_hwriteThread = NULL;
}
BYTE * CCEseries::CRC(BYTE CrcSrcCode[], int CodeLength)
{
unsigned short CRC_Code[]={0x0000, 0x1189, 0x2312,
0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a,
0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393,
0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb,
0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210,
0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58,
0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291,
0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9,
0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116,
0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e,
0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197,
0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf,
0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014,
0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c,
0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095,
0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd,
0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a,
0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52,
0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b,
0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3,
0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618,
0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50,
0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699,
0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1,
0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e,
0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956,
0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f,
0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7,
0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c,
0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854,
0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d,
0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5,
0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78}; //CRC_Code[]数组就是一个余数表
WORD fcs = 0xFFFF;
int i = 0;
while (CodeLength > 2)
{
fcs = ((fcs >> 8) ^ CRC_Code[(fcs ^ CrcSrcCode[i]) & 0xff]);
CodeLength--;
i++;
}
fcs = ~fcs; // ---
CrcSrcCode[i++] = (byte) (fcs & 0xFF);
CrcSrcCode[i] = (byte) ((fcs >> 8) & 0xFF);
return CrcSrcCode;
}
BYTE* CCEseries::GetaddtoCrc(BYTE *data, int len)
{
BYTE *SendBuff = new BYTE[len+2];
ZeroMemory(SendBuff, len+2);
for(int i =0;i<len;i++)
{
SendBuff[i] = data[i];
}
BYTE * CommandAddCRC = NULL;
CommandAddCRC = CRC(SendBuff,len+2);
return CommandAddCRC;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -