ProtocolModbus.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. // ProtocolPMC916.cpp: implementation of the CProtocolModbus class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "ProtocolModbus.h"
  6. #include "winsock2.h"
  7. #include "modbusrtu.h"
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. //////////////////////////////////////////////////////////////////////
  14. // Construction/Destruction
  15. //////////////////////////////////////////////////////////////////////
  16. CProtocolModbus::CProtocolModbus() : CProtocol()
  17. {
  18. InitializeCriticalSection( &m_csReadFinished );
  19. InitializeCriticalSection( &m_csWrFinished );
  20. MTVERIFY( m_hSemComm = CreateEvent( NULL, TRUE, TRUE, 0 ) );
  21. }
  22. CProtocolModbus::~CProtocolModbus()
  23. {
  24. DeleteCriticalSection( &m_csReadFinished );
  25. DeleteCriticalSection( &m_csWrFinished );
  26. MTVERIFY( CloseHandle( m_hSemComm ) );
  27. }
  28. int CProtocolModbus::WorkMain(SETBASEPARAM SetBasePara, int nDataLen, char chMsg[80])
  29. {
  30. if(!m_pComm)
  31. return ERR_CODE_MODBUS_RTU_COM_FAULT; // 串口通信故障
  32. int nRet;
  33. nRet = RequestStatus(SetBasePara);
  34. if( nRet != 0 )
  35. {
  36. return nRet; // 串口忙
  37. }
  38. nRet = ResponseStatus(SetBasePara.nAddr, SetBasePara.nRegNum, nDataLen, chMsg);
  39. return nRet;
  40. }
  41. int CProtocolModbus:: WriteCommand(SETBASEPARAM SetBasePara, double dbData, int nDataLen)
  42. {
  43. int iResult = 0;
  44. if(!m_pComm)
  45. return ERR_CODE_MODBUS_RTU_COM_FAULT;
  46. iResult = RequestWrStatus(SetBasePara, dbData, nDataLen);
  47. if (iResult == 0)
  48. return ResponseWrStatus(SetBasePara.nAddr, SetBasePara.nRegNum, nDataLen);
  49. else
  50. return iResult;
  51. }
  52. int CProtocolModbus::ResponseStatus( int nAddr, int nRegNum, int nDataLen, char chMsg[80])
  53. {
  54. RESPONSE_STRUCT structResponse;
  55. memset( &structResponse, 0, sizeof(RESPONSE_STRUCT) );
  56. if (nDataLen <= 0)
  57. {
  58. SetEvent( m_hSemComm );
  59. //LOG4C((LOG_NOTICE, "ModbusRtu设备地址:%d, 变量长度小于等于0,为非法变量", nAddr));
  60. return ERR_CODE_MODBUS_RTU_COM_VARLEN;
  61. }
  62. int nLen = sizeof(RESPONSE_STRUCT) - sizeof(structResponse.StrRtnMsg) + nDataLen;
  63. char *pBuffer = new char[ nLen ];
  64. memset(pBuffer, 0, nLen);
  65. int nProcessLen = 0;
  66. int nReadLen = 0;
  67. nReadLen = ReadMessage((BYTE *)pBuffer, nLen);
  68. if( nReadLen <= 0)
  69. {
  70. // 串口没有读到数据
  71. SetEvent( m_hSemComm );
  72. if( pBuffer != NULL)
  73. {
  74. delete[] pBuffer;
  75. pBuffer = NULL;
  76. }
  77. return ERR_CODE_MODBUS_RTU_COM_READ_NO_DATA;
  78. }
  79. // 判断校验
  80. int iCrc = GetCRC((byte*) pBuffer, (nLen - sizeof(structResponse.Crc)));
  81. //BYTE btCrc = GetCheckCode(pBuffer,
  82. // nLen - sizeof(structResponse.Lrc) - sizeof(structResponse.End));
  83. //char chAsc[3] = {0};
  84. //sprintf(chAsc, "%X", btCrc);
  85. BYTE high = iCrc>>8&0xff;
  86. BYTE low = iCrc&0xff;
  87. if( !( ((byte)pBuffer[nLen - 2] == low) && ((byte)pBuffer[nLen - 1] ==high) ) )
  88. {
  89. LOG4C((LOG_NOTICE, "ModbusRtu设备地址:%d, crc校验出错!", nAddr));
  90. SetEvent( m_hSemComm );
  91. if( pBuffer != NULL)
  92. {
  93. delete[] pBuffer;
  94. pBuffer = NULL;
  95. }
  96. return ERR_CODE_MODBUS_RTU_COM_LRC_LOST;
  97. }
  98. EnterCriticalSection( &m_csWrFinished );
  99. //for( int i = 0; i < 4 * nRegNum; i++ )
  100. for( int i = 0; i < nDataLen; i++ )
  101. {
  102. chMsg[i] = pBuffer[sizeof(STATUS_STRUCT) + i];
  103. }
  104. LeaveCriticalSection(&m_csWrFinished);
  105. // 设置串口等待事件为有信号
  106. SetEvent( m_hSemComm );
  107. if( pBuffer != NULL)
  108. {
  109. delete[] pBuffer;
  110. pBuffer = NULL;
  111. }
  112. return 0;
  113. }
  114. int CProtocolModbus::RequestStatus(SETBASEPARAM SetBasePara)
  115. {
  116. int iLen = sizeof(REQUESTPARAM);
  117. REQUESTPARAM RequestPara;
  118. memset( &RequestPara, 0, iLen );
  119. RequestPara.AddrCode = SetBasePara.nAddr; //地址码
  120. RequestPara.FuncCode = SetBasePara.FuncCode; //功能码
  121. RequestPara.StartAddr = htons(SetBasePara.nStartAddr); //起始地址
  122. RequestPara.RequestRegNum = htons(SetBasePara.nRegNum); //寄存器数
  123. BYTE *pDataBuf = new BYTE[ iLen - sizeof(RequestPara.Crc) ];
  124. memset(pDataBuf, 0, iLen - sizeof(RequestPara.Crc) );
  125. memcpy(pDataBuf, &RequestPara, iLen - sizeof(RequestPara.Crc) );
  126. int iCrc = GetCRC( pDataBuf, iLen - 2 );
  127. BYTE high = iCrc>>8&0xff;
  128. BYTE low = iCrc&0xff;
  129. RequestPara.Crc[0] = low;
  130. RequestPara.Crc[1] = high;
  131. if( WaitForSingleObject( m_hSemComm, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口
  132. {
  133. //TRACE("Rtu设备设置串口无信号!\r\n");
  134. ResetEvent( m_hSemComm );
  135. int nResult = WriteMessage( (BYTE *)&RequestPara, iLen );
  136. if( nResult == iLen )
  137. {
  138. }
  139. else
  140. {
  141. if( pDataBuf )
  142. {
  143. delete []pDataBuf;
  144. pDataBuf = NULL;
  145. }
  146. SetEvent( m_hSemComm );
  147. return EER_CODE_MODBUS_RTU_COM_WRITE_DATA;
  148. }
  149. }
  150. else
  151. {
  152. if( pDataBuf )
  153. {
  154. delete []pDataBuf;
  155. pDataBuf = NULL;
  156. }
  157. return ERR_CODE_MODBUS_RTU_COM_BUSY;
  158. }
  159. if( pDataBuf )
  160. {
  161. delete []pDataBuf;
  162. pDataBuf = NULL;
  163. }
  164. return 0;
  165. }
  166. int CProtocolModbus::RequestWrStatus( SETBASEPARAM SetBasePara, double dbData, int nDataLen)
  167. {
  168. REQUESTWRPARAM tagRequestWrite;
  169. int nLen = sizeof(REQUESTWRPARAM);
  170. memset( &tagRequestWrite, 0, nLen );
  171. //BYTE AddrCode[2]; //地址码
  172. //BYTE FuncCode[2]; //功能码
  173. //BYTE StartAddr[4]; //起始地址
  174. //BYTE RequestRegNum[4]; //读取的寄存器个数
  175. //BYTE Data[8]; //设置的数据
  176. //BYTE Crc[2]; //校验码位
  177. tagRequestWrite.AddrCode = SetBasePara.nAddr; //地址码
  178. tagRequestWrite.FuncCode = SetBasePara.FuncCode; //功能码
  179. tagRequestWrite.StartAddr = htons(SetBasePara.nStartAddr); //起始地址
  180. tagRequestWrite.SetValue = htons((int)dbData);
  181. BYTE *pDataBuf = new BYTE[ nLen - sizeof(tagRequestWrite.Crc) ];
  182. memset(pDataBuf, 0, nLen - sizeof(tagRequestWrite.Crc) );
  183. memcpy(pDataBuf, &tagRequestWrite, nLen - sizeof(tagRequestWrite.Crc) );
  184. int iCrc = GetCRC( pDataBuf, nLen - 2 );
  185. BYTE high = iCrc>>8&0xff;
  186. BYTE low = iCrc&0xff;
  187. tagRequestWrite.Crc[0] = low;
  188. tagRequestWrite.Crc[1] = high;
  189. ResetEvent( m_hSemComm );
  190. int nResult = WriteMessage( (BYTE *)&tagRequestWrite, nLen );
  191. if( nResult == nLen )
  192. {
  193. }
  194. else
  195. {
  196. delete []pDataBuf;
  197. SetEvent( m_hSemComm );
  198. return EER_CODE_MODBUS_RTU_COM_WRITE_DATA;
  199. }
  200. SetEvent( m_hSemComm );
  201. delete[]pDataBuf;
  202. return 0;
  203. }
  204. int CProtocolModbus::ResponseWrStatus(int nAddr, int nRegNum, int nDataLen)
  205. {
  206. REQUESTWRPARAM RequestWrPara;
  207. int iLen = sizeof(REQUESTWRPARAM);
  208. memset(&RequestWrPara, 0, iLen);
  209. char *pBuffer = new char[iLen];
  210. memset(pBuffer, 0, iLen);
  211. int iProcessLen = 0;
  212. //int iReadLen = ReadMessage((BYTE *)&RequestWrPara, iLen);
  213. int iReadLen = ReadMessage((BYTE *)pBuffer, iLen);
  214. if( iReadLen <= 0) // 串口没有读到数据
  215. {
  216. if( pBuffer )
  217. {
  218. delete[] pBuffer;
  219. pBuffer = NULL;
  220. }
  221. return ERR_CODE_MODBUS_RTU_COM_READ_NO_DATA;
  222. }
  223. else if(iReadLen< iLen)
  224. {
  225. TRACE("长度没有收够,断续接收,直到收完为止!\r\n");
  226. SetEvent( m_hSemComm );
  227. if( pBuffer != NULL)
  228. {
  229. delete[] pBuffer;
  230. pBuffer = NULL;
  231. }
  232. return ERR_CODE_MODBUS_RTU_COM_FAULT;
  233. }
  234. else if( iReadLen > iLen )//实际读到包长度大于要求包的长度
  235. {
  236. // 完全代码,不一定能执行到
  237. TRACE("接收的长度超时所需的长度,认为是非法包,扔掉\r\n");
  238. SetEvent( m_hSemComm );
  239. if( pBuffer != NULL)
  240. {
  241. delete[] pBuffer;
  242. pBuffer = NULL;
  243. }
  244. return ERR_CODE_MODBUS_RTU_COM_READ_LEN_OVER;
  245. }
  246. int iCrc = GetCRC( (BYTE *)pBuffer, iLen - sizeof(RequestWrPara.Crc) );
  247. BYTE high = iCrc>>8&0xff;
  248. BYTE low = iCrc&0xff;
  249. if( !( ((byte)pBuffer[iLen - 2] == low) && ((byte)pBuffer[iLen - 1] ==high) ) )
  250. {
  251. TRACE("lrc 校验失败!\r\n");
  252. SetEvent( m_hSemComm );
  253. if( pBuffer != NULL)
  254. {
  255. delete[] pBuffer;
  256. pBuffer = NULL;
  257. }
  258. return ERR_CODE_MODBUS_RTU_COM_LRC_LOST;
  259. }
  260. EnterCriticalSection( &m_csWrFinished );
  261. memset(&m_RequestWrParam, 0, sizeof(REQUESTWRPARAM));
  262. int iTmpLen = sizeof(m_RequestWrParam.AddrCode) +
  263. sizeof(m_RequestWrParam.FuncCode) +
  264. sizeof(m_RequestWrParam.StartAddr) +
  265. sizeof(m_RequestWrParam.SetValue);
  266. memcpy( &m_RequestWrParam, pBuffer, iTmpLen);//起始位、地址码、功能码、起始地址、数据
  267. iTmpLen = iTmpLen;
  268. memcpy( &m_RequestWrParam.Crc, pBuffer + iTmpLen, 2);//校验位
  269. iTmpLen = iTmpLen + 2;
  270. LeaveCriticalSection(&m_csWrFinished);
  271. // 设置串口等待事件为有信号
  272. if( pBuffer != NULL)
  273. {
  274. delete[] pBuffer;
  275. pBuffer = NULL;
  276. }
  277. SetEvent( m_hSemComm );
  278. return 0;
  279. }
  280. UINT CProtocolModbus::GetCRC(BYTE *pBuf, int len)
  281. {
  282. unsigned int Genpoly=0xA001;
  283. unsigned int CRC=0xFFFF;
  284. unsigned int index;
  285. while(len--)
  286. {
  287. CRC=CRC^(unsigned int)*pBuf++;
  288. for(index=0;index<8;index++)
  289. {
  290. if((CRC & 0x0001)==1) CRC=(CRC>>1)^Genpoly;
  291. else (CRC=CRC>>1);
  292. }
  293. }
  294. return(CRC);
  295. }
  296. BOOL CProtocolModbus::InitParam(PPORTPARAM pPortParam, CCommAsyn *pComm)
  297. {
  298. int addr=pPortParam->StartAddr;
  299. m_pComm=pComm;
  300. return TRUE;
  301. }
  302. void strReverse( char *str )
  303. {
  304. int l = strlen(str);
  305. for( int i = 0; i < l; i++ )
  306. {
  307. for(int i = 0; i < l; i++)
  308. {
  309. if( str[i] >= 'A' && str[i] <= 'Z' )
  310. {
  311. str[i] += 32;
  312. }
  313. else if(str[i] >= 'a' && str[i] <= 'z')
  314. {
  315. str[i] -= 32;
  316. }
  317. }
  318. }
  319. }
  320. char lowercase2uppercase(BYTE btSrc)
  321. {
  322. if( btSrc >= 'a' && btSrc <= 'z' )
  323. {
  324. return btSrc - 'a' + 'A';
  325. }
  326. return btSrc;
  327. }
  328. char ByteToAscii(BYTE btSrc)
  329. {
  330. char chDest;
  331. if( btSrc < 10 )
  332. {
  333. chDest = (char)(btSrc % 10 + '0');
  334. chDest = lowercase2uppercase(chDest);
  335. return chDest;
  336. }
  337. else
  338. {
  339. chDest = ByteToAscii( btSrc / 10 ) + (char)( btSrc % 10 + '0' );
  340. chDest = lowercase2uppercase(chDest);
  341. return chDest;
  342. }
  343. }
  344. WORD AsciiToBYTE(BYTE btSrc)
  345. {
  346. WORD chDest = (WORD)btSrc;
  347. if ((btSrc >= 'A')&&(btSrc <= 'F'))
  348. {
  349. chDest = chDest - 'A' + 10;
  350. }
  351. else if ((btSrc >= 'a')&&(btSrc <= 'f'))
  352. {
  353. chDest = chDest - 'a' + 10;
  354. }
  355. else if ((btSrc >= '0')&&(btSrc <= '9'))
  356. {
  357. chDest -= '0';
  358. }
  359. return chDest;
  360. }