123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- // ProtocolPMC916.cpp: implementation of the CProtocolModbus class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "ProtocolModbus.h"
- #include "winsock2.h"
- #include "modbusrtu.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CProtocolModbus::CProtocolModbus() : CProtocol()
- {
- InitializeCriticalSection( &m_csReadFinished );
- InitializeCriticalSection( &m_csWrFinished );
- MTVERIFY( m_hSemComm = CreateEvent( NULL, TRUE, TRUE, 0 ) );
- }
- CProtocolModbus::~CProtocolModbus()
- {
- DeleteCriticalSection( &m_csReadFinished );
- DeleteCriticalSection( &m_csWrFinished );
- MTVERIFY( CloseHandle( m_hSemComm ) );
- }
- int CProtocolModbus::WorkMain(SETBASEPARAM SetBasePara, int nDataLen, char chMsg[80])
- {
- if(!m_pComm)
- return ERR_CODE_MODBUS_RTU_COM_FAULT; // 串口通信故障
- int nRet;
- nRet = RequestStatus(SetBasePara);
- if( nRet != 0 )
- {
- return nRet; // 串口忙
- }
- nRet = ResponseStatus(SetBasePara.nAddr, SetBasePara.nRegNum, nDataLen, chMsg);
- return nRet;
- }
- int CProtocolModbus:: WriteCommand(SETBASEPARAM SetBasePara, double dbData, int nDataLen)
- {
- int iResult = 0;
- if(!m_pComm)
- return ERR_CODE_MODBUS_RTU_COM_FAULT;
- iResult = RequestWrStatus(SetBasePara, dbData, nDataLen);
- if (iResult == 0)
- return ResponseWrStatus(SetBasePara.nAddr, SetBasePara.nRegNum, nDataLen);
- else
- return iResult;
- }
- int CProtocolModbus::ResponseStatus( int nAddr, int nRegNum, int nDataLen, char chMsg[80])
- {
- RESPONSE_STRUCT structResponse;
- memset( &structResponse, 0, sizeof(RESPONSE_STRUCT) );
- if (nDataLen <= 0)
- {
- SetEvent( m_hSemComm );
- //LOG4C((LOG_NOTICE, "ModbusRtu设备地址:%d, 变量长度小于等于0,为非法变量", nAddr));
- return ERR_CODE_MODBUS_RTU_COM_VARLEN;
- }
- int nLen = sizeof(RESPONSE_STRUCT) - sizeof(structResponse.StrRtnMsg) + nDataLen;
- char *pBuffer = new char[ nLen ];
- memset(pBuffer, 0, nLen);
- int nProcessLen = 0;
- int nReadLen = 0;
- nReadLen = ReadMessage((BYTE *)pBuffer, nLen);
- if( nReadLen <= 0)
- {
- // 串口没有读到数据
- SetEvent( m_hSemComm );
- if( pBuffer != NULL)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- return ERR_CODE_MODBUS_RTU_COM_READ_NO_DATA;
- }
- // 判断校验
- int iCrc = GetCRC((byte*) pBuffer, (nLen - sizeof(structResponse.Crc)));
- //BYTE btCrc = GetCheckCode(pBuffer,
- // nLen - sizeof(structResponse.Lrc) - sizeof(structResponse.End));
- //char chAsc[3] = {0};
- //sprintf(chAsc, "%X", btCrc);
- BYTE high = iCrc>>8&0xff;
- BYTE low = iCrc&0xff;
- if( !( ((byte)pBuffer[nLen - 2] == low) && ((byte)pBuffer[nLen - 1] ==high) ) )
- {
- LOG4C((LOG_NOTICE, "ModbusRtu设备地址:%d, crc校验出错!", nAddr));
- SetEvent( m_hSemComm );
- if( pBuffer != NULL)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- return ERR_CODE_MODBUS_RTU_COM_LRC_LOST;
- }
- EnterCriticalSection( &m_csWrFinished );
- //for( int i = 0; i < 4 * nRegNum; i++ )
- for( int i = 0; i < nDataLen; i++ )
- {
- chMsg[i] = pBuffer[sizeof(STATUS_STRUCT) + i];
- }
- LeaveCriticalSection(&m_csWrFinished);
- // 设置串口等待事件为有信号
- SetEvent( m_hSemComm );
- if( pBuffer != NULL)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- return 0;
- }
- int CProtocolModbus::RequestStatus(SETBASEPARAM SetBasePara)
- {
- int iLen = sizeof(REQUESTPARAM);
- REQUESTPARAM RequestPara;
- memset( &RequestPara, 0, iLen );
- RequestPara.AddrCode = SetBasePara.nAddr; //地址码
- RequestPara.FuncCode = SetBasePara.FuncCode; //功能码
- RequestPara.StartAddr = htons(SetBasePara.nStartAddr); //起始地址
- RequestPara.RequestRegNum = htons(SetBasePara.nRegNum); //寄存器数
- BYTE *pDataBuf = new BYTE[ iLen - sizeof(RequestPara.Crc) ];
- memset(pDataBuf, 0, iLen - sizeof(RequestPara.Crc) );
- memcpy(pDataBuf, &RequestPara, iLen - sizeof(RequestPara.Crc) );
- int iCrc = GetCRC( pDataBuf, iLen - 2 );
- BYTE high = iCrc>>8&0xff;
- BYTE low = iCrc&0xff;
- RequestPara.Crc[0] = low;
- RequestPara.Crc[1] = high;
- if( WaitForSingleObject( m_hSemComm, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口
- {
- //TRACE("Rtu设备设置串口无信号!\r\n");
- ResetEvent( m_hSemComm );
- int nResult = WriteMessage( (BYTE *)&RequestPara, iLen );
- if( nResult == iLen )
- {
- }
- else
- {
- if( pDataBuf )
- {
- delete []pDataBuf;
- pDataBuf = NULL;
- }
- SetEvent( m_hSemComm );
- return EER_CODE_MODBUS_RTU_COM_WRITE_DATA;
- }
- }
- else
- {
- if( pDataBuf )
- {
- delete []pDataBuf;
- pDataBuf = NULL;
- }
- return ERR_CODE_MODBUS_RTU_COM_BUSY;
- }
- if( pDataBuf )
- {
- delete []pDataBuf;
- pDataBuf = NULL;
- }
- return 0;
- }
- int CProtocolModbus::RequestWrStatus( SETBASEPARAM SetBasePara, double dbData, int nDataLen)
- {
- REQUESTWRPARAM tagRequestWrite;
- int nLen = sizeof(REQUESTWRPARAM);
- memset( &tagRequestWrite, 0, nLen );
- //BYTE AddrCode[2]; //地址码
- //BYTE FuncCode[2]; //功能码
- //BYTE StartAddr[4]; //起始地址
- //BYTE RequestRegNum[4]; //读取的寄存器个数
- //BYTE Data[8]; //设置的数据
- //BYTE Crc[2]; //校验码位
- tagRequestWrite.AddrCode = SetBasePara.nAddr; //地址码
- tagRequestWrite.FuncCode = SetBasePara.FuncCode; //功能码
- tagRequestWrite.StartAddr = htons(SetBasePara.nStartAddr); //起始地址
- tagRequestWrite.SetValue = htons((int)dbData);
- BYTE *pDataBuf = new BYTE[ nLen - sizeof(tagRequestWrite.Crc) ];
- memset(pDataBuf, 0, nLen - sizeof(tagRequestWrite.Crc) );
- memcpy(pDataBuf, &tagRequestWrite, nLen - sizeof(tagRequestWrite.Crc) );
- int iCrc = GetCRC( pDataBuf, nLen - 2 );
- BYTE high = iCrc>>8&0xff;
- BYTE low = iCrc&0xff;
- tagRequestWrite.Crc[0] = low;
- tagRequestWrite.Crc[1] = high;
- ResetEvent( m_hSemComm );
- int nResult = WriteMessage( (BYTE *)&tagRequestWrite, nLen );
- if( nResult == nLen )
- {
- }
- else
- {
- delete []pDataBuf;
- SetEvent( m_hSemComm );
- return EER_CODE_MODBUS_RTU_COM_WRITE_DATA;
- }
- SetEvent( m_hSemComm );
- delete[]pDataBuf;
- return 0;
- }
- int CProtocolModbus::ResponseWrStatus(int nAddr, int nRegNum, int nDataLen)
- {
- REQUESTWRPARAM RequestWrPara;
- int iLen = sizeof(REQUESTWRPARAM);
- memset(&RequestWrPara, 0, iLen);
- char *pBuffer = new char[iLen];
- memset(pBuffer, 0, iLen);
- int iProcessLen = 0;
- //int iReadLen = ReadMessage((BYTE *)&RequestWrPara, iLen);
- int iReadLen = ReadMessage((BYTE *)pBuffer, iLen);
- if( iReadLen <= 0) // 串口没有读到数据
- {
- if( pBuffer )
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- return ERR_CODE_MODBUS_RTU_COM_READ_NO_DATA;
- }
- else if(iReadLen< iLen)
- {
- TRACE("长度没有收够,断续接收,直到收完为止!\r\n");
- SetEvent( m_hSemComm );
- if( pBuffer != NULL)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- return ERR_CODE_MODBUS_RTU_COM_FAULT;
- }
- else if( iReadLen > iLen )//实际读到包长度大于要求包的长度
- {
- // 完全代码,不一定能执行到
- TRACE("接收的长度超时所需的长度,认为是非法包,扔掉\r\n");
- SetEvent( m_hSemComm );
- if( pBuffer != NULL)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- return ERR_CODE_MODBUS_RTU_COM_READ_LEN_OVER;
- }
- int iCrc = GetCRC( (BYTE *)pBuffer, iLen - sizeof(RequestWrPara.Crc) );
- BYTE high = iCrc>>8&0xff;
- BYTE low = iCrc&0xff;
- if( !( ((byte)pBuffer[iLen - 2] == low) && ((byte)pBuffer[iLen - 1] ==high) ) )
- {
- TRACE("lrc 校验失败!\r\n");
- SetEvent( m_hSemComm );
- if( pBuffer != NULL)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- return ERR_CODE_MODBUS_RTU_COM_LRC_LOST;
- }
- EnterCriticalSection( &m_csWrFinished );
- memset(&m_RequestWrParam, 0, sizeof(REQUESTWRPARAM));
- int iTmpLen = sizeof(m_RequestWrParam.AddrCode) +
- sizeof(m_RequestWrParam.FuncCode) +
- sizeof(m_RequestWrParam.StartAddr) +
- sizeof(m_RequestWrParam.SetValue);
- memcpy( &m_RequestWrParam, pBuffer, iTmpLen);//起始位、地址码、功能码、起始地址、数据
- iTmpLen = iTmpLen;
- memcpy( &m_RequestWrParam.Crc, pBuffer + iTmpLen, 2);//校验位
- iTmpLen = iTmpLen + 2;
- LeaveCriticalSection(&m_csWrFinished);
- // 设置串口等待事件为有信号
- if( pBuffer != NULL)
- {
- delete[] pBuffer;
- pBuffer = NULL;
- }
- SetEvent( m_hSemComm );
- return 0;
- }
- UINT CProtocolModbus::GetCRC(BYTE *pBuf, int len)
- {
- unsigned int Genpoly=0xA001;
- unsigned int CRC=0xFFFF;
- unsigned int index;
- while(len--)
- {
- CRC=CRC^(unsigned int)*pBuf++;
- for(index=0;index<8;index++)
- {
- if((CRC & 0x0001)==1) CRC=(CRC>>1)^Genpoly;
- else (CRC=CRC>>1);
- }
- }
- return(CRC);
- }
- BOOL CProtocolModbus::InitParam(PPORTPARAM pPortParam, CCommAsyn *pComm)
- {
- int addr=pPortParam->StartAddr;
- m_pComm=pComm;
- return TRUE;
- }
- void strReverse( char *str )
- {
- int l = strlen(str);
- for( int i = 0; i < l; i++ )
- {
- for(int i = 0; i < l; i++)
- {
- if( str[i] >= 'A' && str[i] <= 'Z' )
- {
- str[i] += 32;
- }
- else if(str[i] >= 'a' && str[i] <= 'z')
- {
- str[i] -= 32;
- }
- }
- }
- }
- char lowercase2uppercase(BYTE btSrc)
- {
- if( btSrc >= 'a' && btSrc <= 'z' )
- {
- return btSrc - 'a' + 'A';
- }
- return btSrc;
- }
- char ByteToAscii(BYTE btSrc)
- {
- char chDest;
- if( btSrc < 10 )
- {
- chDest = (char)(btSrc % 10 + '0');
- chDest = lowercase2uppercase(chDest);
- return chDest;
- }
- else
- {
- chDest = ByteToAscii( btSrc / 10 ) + (char)( btSrc % 10 + '0' );
- chDest = lowercase2uppercase(chDest);
- return chDest;
- }
- }
- WORD AsciiToBYTE(BYTE btSrc)
- {
- WORD chDest = (WORD)btSrc;
- if ((btSrc >= 'A')&&(btSrc <= 'F'))
- {
- chDest = chDest - 'A' + 10;
- }
- else if ((btSrc >= 'a')&&(btSrc <= 'f'))
- {
- chDest = chDest - 'a' + 10;
- }
- else if ((btSrc >= '0')&&(btSrc <= '9'))
- {
- chDest -= '0';
- }
- return chDest;
- }
|