// ProtocolPMC916.cpp: implementation of the CProtocolModbus class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ProtocolModbus.h" #include "winsock2.h" #include "Upskehua.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, "DLL_UPS_KE_HUA" ) ); } CProtocolModbus::~CProtocolModbus() { DeleteCriticalSection( &m_csReadFinished ); DeleteCriticalSection( &m_csWrFinished ); MTVERIFY( CloseHandle( m_hSemComm ) ); } int CProtocolModbus::WorkMain( int nCommPort, int nAddr, char szCmd[32], char chSendMsg[32], int nDataLen, char chMsg[UPS_KE_HUA_MAX_MSG]) { if(!m_pComm) return ERR_CODE_UPSKEHUA_COM_FAULT; // 串口通信故障 int nRet; nRet = RequestStatus(chSendMsg); if( nRet != 0 ) { return nRet; // 串口忙 } nRet = ResponseStatus(szCmd, nDataLen, chMsg); return nRet; } int CProtocolModbus::ResponseStatus(char szCmd[32], int nDataLen, char chMsg[UPS_KE_HUA_MAX_MSG]) { int nLen = 0; int nProcessLen = 0; int nReadLen = 0; RESPONSE_STRUCT structResponse; nLen = sizeof(RESPONSE_STRUCT); memset( &structResponse, 0, nLen ); if (nDataLen <= 0) { TRACE("变量长度小于等于0,为非法变量"); return ERR_CODE_UPSKEHUA_COM_VARLEN; } char *pBuffer = new char[ nLen ]; memset(pBuffer, 0, nLen); nReadLen = ReadMessage((BYTE *)pBuffer, nLen); if( nReadLen <= 0) { // 串口没有读到数据 TRACE("串口没有读到数据!\r\n"); SetEvent( m_hSemComm ); if( pBuffer != NULL) { delete[] pBuffer; pBuffer = NULL; } return ERR_CODE_UPSKEHUA_COM_READ_NO_DATA; } else if( nReadLen < nLen ) { if (pBuffer[0] == '?')//无效应答包 { delete[] pBuffer; pBuffer = NULL; return ERR_CODE_UPSKEHUA_COM_INVALIDRES; } TRACE("长度没有收够,断续接收,止到收完为止!\r\n"); SetEvent( m_hSemComm ); if( pBuffer ) { delete[] pBuffer; pBuffer = NULL; } return ERR_CODE_UPSKEHUA_COM_FAULT; } else if( nReadLen > nLen ) { // 完全代码,不一定能执行到 TRACE("接收的长度超时所需的长度,认为是非法包,扔掉\r\n"); SetEvent( m_hSemComm ); if( pBuffer != NULL) { delete[] pBuffer; pBuffer = NULL; } return ERR_CODE_UPSKEHUA_COM_READ_LEN_OVER; } else if(nReadLen == nLen) { if (pBuffer[0] == '?')//无效应答包 { delete[] pBuffer; pBuffer = NULL; SetEvent( m_hSemComm ); return ERR_CODE_UPSKEHUA_COM_INVALIDRES; } } EnterCriticalSection( &m_csWrFinished ); memcpy(chMsg, pBuffer + 1, nLen - 1); LeaveCriticalSection(&m_csWrFinished); // 设置串口等待事件为有信号 SetEvent( m_hSemComm ); if( pBuffer != NULL) { delete[] pBuffer; pBuffer = NULL; } return 0; } int CProtocolModbus::RequestStatus(char chSendMsg[32])// { if( WaitForSingleObject( m_hSemComm, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口 { int nDataLen = strlen(chSendMsg); ResetEvent( m_hSemComm ); int nResult = WriteMessage((unsigned char *)chSendMsg, nDataLen); if( nResult == nDataLen ) { } else { SetEvent( m_hSemComm ); return EER_CODE_UPSKEHUA_COM_REGNUM; } } else { return ERR_CODE_UPSKEHUA_COM_BUSY; } return 0; } BOOL CProtocolModbus::InitParam(PPORTPARAM pPortParam, CCommAsyn *pComm) { int addr=pPortParam->StartAddr; m_pComm=pComm; return TRUE; } int CProtocolModbus:: WriteCommand(char DataBuffer[80], int nDataLen) { int iResult = 0; if(!m_pComm) return ERR_CODE_UPSKEHUA_COM_FAULT; iResult = RequestWrStatus(DataBuffer, nDataLen); if (iResult == 0) return ResponseWrStatus(DataBuffer, nDataLen); else return iResult; } int CProtocolModbus::RequestWrStatus( char DataBuffer[80], int nDataLen)//请求写数据 { if( WaitForSingleObject( m_hSemComm, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口 { ResetEvent( m_hSemComm ); int iResult = WriteMessage((unsigned char *)DataBuffer, nDataLen); if (iResult == nDataLen) { return 0; } else { SetEvent( m_hSemComm ); return EER_CODE_UPSKEHUA_COM_WRITE_DATA; } } else { return EER_CODE_UPSKEHUA_COM_WRITE_DATA; } } int CProtocolModbus::ResponseWrStatus( char DataBuffer[80], int nDataLen) { char chBuf = 0; int iReadLen = ReadMessage((BYTE *)&chBuf, sizeof(chBuf)); if( iReadLen <= 0) // 串口没有读到数据 { SetEvent( m_hSemComm ); return ERR_CODE_UPSKEHUA_COM_READ_NO_DATA; } SetEvent( m_hSemComm ); if (chBuf == '>') { return 0; } else return ERR_CODE_UPSKEHUA_COM_INVALIDRES; } 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; }