// ProtocolPMC916.cpp: implementation of the CProtocolModbus class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ProtocolModbus.h" #include "winsock2.h" #include "icpdas.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_IcpdasComm" ) ); } CProtocolModbus::~CProtocolModbus() { DeleteCriticalSection( &m_csReadFinished ); DeleteCriticalSection( &m_csWrFinished ); MTVERIFY( CloseHandle( m_hSemComm ) ); } int CProtocolModbus::WorkMain( int nAddr, //设备地址 BYTE Start,//起始位 BYTE StartAddr[2],//起始地址 int nRegNum,//读取的寄存器个数 BYTE FuncCode[2], int nDataLen, BYTE byWithAddrFlag, char chMsg[80]) { if(!m_pComm) return ERR_CODE_ICPDAS_COM_FAULT; // 串口通信故障 int nRet; nRet = RequestStatus( nAddr, Start, StartAddr, nRegNum, FuncCode); if( nRet != 0 ) { return nRet; // 串口忙 } nRet = ResponseStatus(nDataLen, byWithAddrFlag, chMsg); return nRet; } int CProtocolModbus::ResponseStatus(int nDataLen, BYTE byWithAddrFlag, char chMsg[80]) { int nLen = 0; int nProcessLen = 0; int nReadLen = 0; RESPONSE_STRUCT structResponse; memset( &structResponse, 0, sizeof(RESPONSE_STRUCT) ); if (nDataLen <= 0) { TRACE("变量长度小于等于0,为非法变量"); return ERR_CODE_ICPDAS_COM_VARLEN; } if (byWithAddrFlag == '1') nLen = sizeof(RESPONSE_STRUCT) - sizeof(structResponse.StrRtnMsg) - sizeof(structResponse.StatusStruct.RtnByteNum) + nDataLen; else if (byWithAddrFlag == '0') nLen = sizeof(RESPONSE_STRUCT) - sizeof(structResponse.StrRtnMsg) - sizeof(structResponse.StatusStruct.RtnByteNum) - sizeof(structResponse.StatusStruct.AddrCode) + nDataLen; 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_ICPDAS_COM_READ_NO_DATA; } else if( nReadLen < nLen ) { if (pBuffer[0] == '?')//无效应答包 { delete[] pBuffer; pBuffer = NULL; return ERR_CODE_ICPDAS_COM_INVALIDRES; } TRACE("长度没有收够,断续接收,止到收完为止!\r\n"); #if DEBUG_PROTOCOL SetEvent( m_hSemComm ); if( pBuffer ) { delete[] pBuffer; pBuffer = NULL; } return ERR_CODE_ICPDAS_COM_FAULT; #else nProcessLen += nReadLen; nReadLen = ReadMessage( (BYTE *)(pBuffer + nProcessLen), nLen - nProcessLen ); while( nReadLen != nLen - nProcessLen ) { if( nReadLen == 0 ) { SetEvent( m_hSemComm ); if( pBuffer ) { delete[] pBuffer; pBuffer = NULL; } return ERR_CODE_ICPDAS_COM_READ_NO_DATA; // 还是没有收到数据,直接返回 } nProcessLen += nReadLen; nReadLen = ReadMessage( (BYTE *)(pBuffer + nProcessLen), nLen - nProcessLen); } if( nReadLen == nLen ) { //goto NormalProcess; if( pBuffer != NULL) { delete[] pBuffer; pBuffer = NULL; } SetEvent( m_hSemComm ); return ERR_CODE_ICPDAS_COM_FAULT; } #endif } else if( nReadLen > nLen ) { // 完全代码,不一定能执行到 TRACE("接收的长度超时所需的长度,认为是非法包,扔掉\r\n"); SetEvent( m_hSemComm ); if( pBuffer != NULL) { delete[] pBuffer; pBuffer = NULL; } return ERR_CODE_ICPDAS_COM_READ_LEN_OVER; } else if(nReadLen == nLen) { if (pBuffer[0] == '?')//无效应答包 { delete[] pBuffer; pBuffer = NULL; SetEvent( m_hSemComm ); return ERR_CODE_ICPDAS_COM_INVALIDRES; } } // 判断校验 EnterCriticalSection( &m_csWrFinished ); int nCrease = 0; memset(&m_structResponse, 0,sizeof(RESPONSE_STRUCT)); nCrease = sizeof(m_structResponse.StatusStruct.Start); memcpy( &m_structResponse.StatusStruct.Start, pBuffer, nCrease ); if (byWithAddrFlag == '1') { memcpy( &m_structResponse.StatusStruct.AddrCode, pBuffer + nLen, sizeof(m_structResponse.StatusStruct.AddrCode) ); nCrease += sizeof(m_structResponse.StatusStruct.AddrCode); } for( int i = 0; i < nDataLen; i++ ) { chMsg[i] = pBuffer[nCrease + i]; //m_structResponse.StrRtnMsg[i] = pBuffer[nCrease + i]; } m_structResponse.StatusStruct.RtnByteNum = nDataLen; LeaveCriticalSection(&m_csWrFinished); // 设置串口等待事件为有信号 SetEvent( m_hSemComm ); if( pBuffer != NULL) { delete[] pBuffer; pBuffer = NULL; } return 0; } int CProtocolModbus::RequestStatus( int nAddr, //设备地址 BYTE Start, //起始位 BYTE StartAddr[2], //起始地址 int nRegNum, //读取的寄存器个数 BYTE FuncCode[2]) //功能码 { int ivarid = 55; // CProtocol* protocol; int iLen = sizeof(REQUESTPARAM); char *pBuf = new char[iLen]; int iSendLen = 0; REQUESTPARAM RequestPara; memset(&RequestPara, 0, iLen); RequestPara.Start = Start; memcpy(RequestPara.StartAddr, StartAddr, sizeof(RequestPara.StartAddr)); memcpy(RequestPara.FuncCode, FuncCode, sizeof(RequestPara.FuncCode)); RequestPara.END = 0x0D; memcpy(pBuf, &RequestPara.Start, sizeof(RequestPara.Start)); iSendLen = iSendLen + sizeof(RequestPara.Start); BYTE szAddr[2] = {0}; szAddr[0] = ByteToAscii((nAddr >> 4) & 0x0f); szAddr[1] = ByteToAscii(nAddr & 0x0f); memcpy(pBuf + iSendLen, szAddr, sizeof(szAddr)); iSendLen = iSendLen + sizeof(szAddr); if (RequestPara.FuncCode[0] == 'L') { memcpy(pBuf + iSendLen, RequestPara.FuncCode, sizeof(RequestPara.FuncCode)); iSendLen = iSendLen + sizeof(RequestPara.FuncCode); } else if (RequestPara.FuncCode[0] == '-' && RequestPara.FuncCode[1] == '1') { ; } else { memcpy(pBuf + iSendLen, RequestPara.FuncCode + 1, sizeof(RequestPara.FuncCode) - 1); iSendLen = iSendLen + sizeof(RequestPara.FuncCode) - 1; } memcpy(pBuf + iSendLen, &RequestPara.END, sizeof(RequestPara.END)); iSendLen = iSendLen + sizeof(RequestPara.END); if( WaitForSingleObject( m_hSemComm, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口 { ResetEvent( m_hSemComm ); int nResult = WriteMessage((unsigned char *)pBuf, iSendLen); if( nResult == iSendLen ) { } else { delete []pBuf; SetEvent( m_hSemComm ); return EER_CODE_ICPDAS_COM_WRITE_DATA; } } else { delete []pBuf; return ERR_CODE_ICPDAS_COM_BUSY; } delete []pBuf; 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_ICPDAS_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_ICPDAS_COM_WRITE_DATA; } } else { return EER_CODE_ICPDAS_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_ICPDAS_COM_READ_NO_DATA; } SetEvent( m_hSemComm ); if (chBuf == '>') { return 0; } else { return ERR_CODE_ICPDAS_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; }