⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmbrtu.cpp

📁 实现了modbus RTU通讯协议的COM组件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// CMBRTU.cpp : Implementation of CCMBRTU
#include "stdafx.h"
#include "MBRTU.h"
#include "CMBRTU.h"
#include "Crc.h"


/////////////////////////////////////////////////////////////////////////////
// CCMBRTU

STDMETHODIMP CCMBRTU::OpenCom(BSTR bstrComParam)
{
	// TODO: Add your implementation code here
	int iLen = wcslen(bstrComParam) * 2 + 1;
	cParam = (char *)new BYTE[iLen];
	memset(cParam, 0, iLen);
	cReceive = (char *)new BYTE[2048];
	memset(cReceive, 0, 2048);
	cWrite = (char *)new BYTE[2048];
	memset(cWrite, 0, 2048);
	WideCharToMultiByte(                        \
                   CP_ACP,                      \
                   0,                           \
                   bstrComParam,                 \
                   -1,                          \
                   cParam,                    \
                   iLen,                        \
                   NULL,                        \
                   NULL);

	DCB dcb;
	char cCom[5];

	memset(cCom, 0, 5);

	memcpy(cCom, cParam, 4);

    hCom = CreateFile(cCom,
		GENERIC_READ | GENERIC_WRITE,
		0,    // comm devices must be opened w/exclusive-access 
		NULL, // no security attributes 
		OPEN_EXISTING, // comm devices must use OPEN_EXISTING 
		FILE_ATTRIBUTE_NORMAL,    // not overlapped I/O 
		NULL  // hTemplate must be NULL for comm devices 
		);

	if (hCom == INVALID_HANDLE_VALUE) 
	{
		return S_FALSE;
	}

	// Omit the call to SetupComm to use the default queue sizes.
	// Get the current configuration.

	if (!SetupComm(hCom, (DWORD)2048, (DWORD)2048))
	{
		CloseHandle(hCom);
		return S_FALSE;
	}

	if (!GetCommState(hCom, &dcb))
	{
		CloseHandle(hCom);
		return S_FALSE;
	}

	if (!BuildCommDCB(cParam,&dcb))
	{
		CloseHandle(hCom);
		return S_FALSE;
	}
	//由于是BuildCommDCB的bug才要加上下面的代码, bug是fParity = 0 
	if(dcb.Parity == ODDPARITY || dcb.Parity == EVENPARITY)
		dcb.fParity = 1;
	//dcb.fDtrControl = DTR_CONTROL_ENABLE;
	//dcb.fRtsControl = RTS_CONTROL_DISABLE;
	SetCommState(hCom, &dcb);
	
	if (!PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
	{
		CloseHandle(hCom);
		return S_FALSE;
	}

	//COMMTIMEOUTS co;
	//GetCommTimeouts(hCom, &co);
	//co.ReadIntervalTimeout = 0xFFFFFFFF; 
	//co.ReadTotalTimeoutConstant = 5000;
	//co.ReadTotalTimeoutMultiplier = 0;
	//co.WriteTotalTimeoutConstant = 5000;                                  
	//co.WriteTotalTimeoutMultiplier = 0;
	//SetCommTimeouts(hCom, &co);
	bConnect = TRUE;
	return S_OK;
}

STDMETHODIMP CCMBRTU::CloseCom()
{
	// TODO: Add your implementation code here
	if(bConnect)
	{
		CloseHandle(hCom);

		if (cParam)
		{
			delete cParam;
			cParam = NULL;
		}
		if (cReceive)
		{
			delete cReceive;
			cReceive = NULL;
		}
		if (cWrite)
		{
			delete cWrite;
			cWrite = NULL;
		}
	}
	return S_OK;
}



STDMETHODIMP CCMBRTU::ReadRegister(int iStation, int iStartAddr, int iLen, int *pRetLen)
{
	// TODO: Add your implementation code here
	BYTE cReadCmd[8];
	memset(cReadCmd, 0, 8);
	
	cReadCmd[0]  = iStation;
	cReadCmd[1]  = 3;
	cReadCmd[2]  = iStartAddr / 256;
	cReadCmd[3]  = iStartAddr % 256;
	cReadCmd[4]  = iLen / 256;
	cReadCmd[5]  = iLen % 256;

	CCrc crc;
	crc.CRC16((unsigned char *)cReadCmd, 6, cReadCmd[6], cReadCmd[7]);

	DWORD dwTotal = iLen * 2 + 5;

	DWORD dwEvent;
	//dwEvent = EV_TXEMPTY;
	SetCommMask(hCom, EV_TXEMPTY);
	DWORD dwTick = GetTickCount();
	DWORD dwWrite = 0;
	DWORD dwRead = 0;
	DWORD dwTemp = 0;

	if (WriteFile(hCom, cReadCmd, 8, &dwWrite, NULL))
	{
		WaitCommEvent(hCom, &dwEvent, NULL);
		memset(cReceive, 0, 2048);
		while(TRUE)
		{
			if(dwWrite == 8)
			{
				//dwError = 0;
				ClearCommError(hCom,&dwError,&cs); 
				if((!cs.cbInQue && dwTemp == dwTotal ) || (GetTickCount() > dwTick + 5000))
					break;
				dwRead = 0;
				ReadFile(hCom, cReceive + dwTemp, cs.cbInQue, &dwRead, NULL);
				dwTemp += dwRead;
			}
		}
	}

	if (dwTemp != dwTotal)
		return S_FALSE;

	if (cReceive[2] != iLen * 2)
		return S_FALSE;

	memcpy(cReceive, cReceive + 3, iLen * 2);

	*pRetLen = iLen * 2;

	return S_OK;
}


STDMETHODIMP CCMBRTU::GetRetVal(int iIndex, BYTE *pByte)
{
	// TODO: Add your implementation code here
	*pByte = cReceive[iIndex];
	return S_OK;
}

STDMETHODIMP CCMBRTU::GetRetVal_Cimplicity(int iIndex, int *piVal)
{
	// TODO: Add your implementation code here
	*piVal = cReceive[iIndex];
	return S_OK;
}

STDMETHODIMP CCMBRTU::WriteRegister(int iSation, int iStartAddr, int iLen)
{
	// TODO: Add your implementation code here
	BYTE cWriteCmd[2048];
	memset(cWriteCmd, 0, 2048);
	int iLength = iLen * 2; 
	
	cWriteCmd[0]  = iSation;
	cWriteCmd[1]  = 16;
	cWriteCmd[2]  = iStartAddr / 256;
	cWriteCmd[3]  = iStartAddr % 256;
	cWriteCmd[4]  = 0;
	cWriteCmd[5]  = iLen;
	cWriteCmd[6]  = iLength;

	for(int i = 0; i < iLength; i++)
	{
		cWriteCmd[i + 7] = cWrite[i];
	}

	CCrc crc;
	crc.CRC16((unsigned char *)cWriteCmd, 7 + iLength, cWriteCmd[7 + iLength], cWriteCmd[7 + iLength + 1]);

	DWORD dwTotal = 8;

	DWORD dwEvent;
	//dwEvent = EV_TXEMPTY;
	SetCommMask(hCom, EV_TXEMPTY);
	DWORD dwTick = GetTickCount();
	DWORD dwWrite = 0;
	DWORD dwRead = 0;
	DWORD dwTemp = 0;

	DWORD dwWriteLen = 7 + iLength + 2;
	
	if (WriteFile(hCom, cWriteCmd, dwWriteLen, &dwWrite, NULL))
	{
		WaitCommEvent(hCom, &dwEvent, NULL);
		memset(cReceive, 0, 2048);
		while(TRUE)
		{
			if(dwWrite == dwWriteLen)
			{
				//dwError = 0;
				ClearCommError(hCom,&dwError,&cs); 
				if((!cs.cbInQue && dwTemp == dwTotal ) || (GetTickCount() > dwTick + 5000))
					break;
				dwRead = 0;
				ReadFile(hCom, cReceive + dwTemp, cs.cbInQue, &dwRead, NULL);
				dwTemp += dwRead;
			}
		}
	}

	if (dwTemp != dwTotal)
		return S_FALSE;

	if (cReceive[1] != 16)
		return S_FALSE;

	return S_OK;
}

STDMETHODIMP CCMBRTU::SetRegVal(int iIndex, BYTE byteVal)
{
	// TODO: Add your implementation code here
	cWrite[iIndex] = byteVal;
	return S_OK;
}

STDMETHODIMP CCMBRTU::TwoByteToShort(BYTE byteHi, BYTE byteLo, short *psVal)
{
	// TODO: Add your implementation code here
	BYTE byteTemp[2];
	memset(byteTemp, 0, 2);
	byteTemp[0] = byteLo;
	byteTemp[1] = byteHi;
	memcpy(psVal, byteTemp, 2);
	return S_OK;
}

STDMETHODIMP CCMBRTU::ShortToTwoByte(short sVal, BYTE *pbyteHi, BYTE *pbyteLo)
{
	// TODO: Add your implementation code here
	BYTE byteVal[2];
	memcpy(byteVal, &sVal, 2);

	*pbyteLo = byteVal[0];
	*pbyteHi = byteVal[1];

	return S_OK;
}

STDMETHODIMP CCMBRTU::ReadCoils(int iStation, int iStartAddr, int iQuantity, int *pRetLen)
{
	// TODO: Add your implementation code here
	BYTE cReadCmd[8];
	memset(cReadCmd, 0, 8);
	
	cReadCmd[0]  = iStation;
	cReadCmd[1]  = 1;
	cReadCmd[2]  = iStartAddr / 256;
	cReadCmd[3]  = iStartAddr % 256;
	cReadCmd[4]  = iQuantity / 256;
	cReadCmd[5]  = iQuantity % 256;

	CCrc crc;
	crc.CRC16((unsigned char *)cReadCmd, 6, cReadCmd[6], cReadCmd[7]);
	int iLen = 0;
	iLen = iQuantity / 8;
	if (iQuantity % 8)
		iLen++;

	DWORD dwTotal = iLen + 5;

	DWORD dwEvent;
	SetCommMask(hCom, EV_TXEMPTY);
	DWORD dwTick = GetTickCount();
	DWORD dwWrite = 0;
	DWORD dwRead = 0;
	DWORD dwTemp = 0;

	if (WriteFile(hCom, cReadCmd, 8, &dwWrite, NULL))
	{
		WaitCommEvent(hCom, &dwEvent, NULL);
		memset(cReceive, 0, 2048);
		while(TRUE)
		{
			if(dwWrite == 8)
			{
				ClearCommError(hCom,&dwError,&cs); 
				if((!cs.cbInQue && dwTemp == dwTotal ) || (GetTickCount() > dwTick + 5000))
					break;
				dwRead = 0;
				ReadFile(hCom, cReceive + dwTemp, cs.cbInQue, &dwRead, NULL);
				dwTemp += dwRead;
			}
		}
	}

	if (dwTemp != dwTotal)
		return S_FALSE;

	if (cReceive[1] != 1)
		return S_FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -