ProtocolModbus.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. // ProtocolPMC916.cpp: implementation of the CProtocolModbus class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "ProtocolModbus.h"
  6. #include "winsock2.h"
  7. #include "stulz.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, int iCmdPos, int iCmdLen, char chMsg[10])
  29. {
  30. if(!m_pComm)
  31. return ERR_CODE_AIR_STULZ_COM_FAULT; // 串口通信故障
  32. int nRet;
  33. nRet = RequestStatus(SetBasePara);
  34. if( nRet != 0 )
  35. {
  36. return nRet; // 串口忙
  37. }
  38. nRet = ResponseStatus( nDataLen, iCmdPos, iCmdLen, chMsg);
  39. return nRet;
  40. }
  41. int CProtocolModbus:: WriteCommand(char DataBuffer[80], char ResDataBuffer[2])
  42. {
  43. int iResult = 0;
  44. if(!m_pComm)
  45. return ERR_CODE_AIR_STULZ_COM_FAULT;
  46. iResult = RequestWrStatus(DataBuffer);
  47. if (iResult == 0)
  48. return ResponseWrStatus(ResDataBuffer);
  49. else
  50. return iResult;
  51. }
  52. //nDataLen 数据的总长度,iCmdPos 命令位置,iCmdLen 变量数据长度,chMsg 变量数据
  53. int CProtocolModbus::ResponseStatus(int nDataLen, int iCmdPos, int iCmdLen, char chMsg[10])
  54. {
  55. RESPONSE_STRUCT structResponse;
  56. memset( &structResponse, 0, sizeof(RESPONSE_STRUCT) );
  57. if (nDataLen <= 0)
  58. {
  59. TRACE("变量长度小于等于0,为非法变量");
  60. return ERR_CODE_AIR_STULZ_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. TRACE("串口没有读到数据!\r\n");
  72. SetEvent( m_hSemComm );
  73. if( pBuffer != NULL)
  74. {
  75. delete[] pBuffer;
  76. pBuffer = NULL;
  77. }
  78. return ERR_CODE_AIR_STULZ_COM_READ_NO_DATA;
  79. }
  80. else if( nReadLen < nLen )
  81. {
  82. TRACE("长度没有收够,断续接收,止到收完为止!\r\n");
  83. #if DEBUG_PROTOCOL
  84. SetEvent( m_hSemComm );
  85. if( pBuffer )
  86. {
  87. delete[] pBuffer;
  88. pBuffer = NULL;
  89. }
  90. return ERR_CODE_AIR_STULZ_COM_FAULT;
  91. #else
  92. nProcessLen += nReadLen;
  93. nReadLen = ReadMessage( (BYTE *)(pBuffer + nProcessLen), nLen - nProcessLen );
  94. while( nReadLen != nLen - nProcessLen )
  95. {
  96. if( nReadLen == 0 )
  97. {
  98. SetEvent( m_hSemComm );
  99. if( pBuffer )
  100. {
  101. delete[] pBuffer;
  102. pBuffer = NULL;
  103. }
  104. return ERR_CODE_AIR_STULZ_COM_READ_NO_DATA; // 还是没有收到数据,直接返回
  105. }
  106. nProcessLen += nReadLen;
  107. nReadLen = ReadMessage( (BYTE *)(pBuffer + nProcessLen), nLen - nProcessLen);
  108. }
  109. if( nReadLen == nLen )
  110. {
  111. //goto NormalProcess;
  112. if( pBuffer != NULL)
  113. {
  114. delete[] pBuffer;
  115. pBuffer = NULL;
  116. }
  117. return ERR_CODE_AIR_STULZ_COM_FAULT;
  118. }
  119. #endif
  120. }
  121. else if( nReadLen > nLen )
  122. {
  123. // 完全代码,不一定能执行到
  124. TRACE("接收的长度超时所需的长度,认为是非法包,扔掉\r\n");
  125. SetEvent( m_hSemComm );
  126. if( pBuffer != NULL)
  127. {
  128. delete[] pBuffer;
  129. pBuffer = NULL;
  130. }
  131. return ERR_CODE_AIR_STULZ_COM_READ_LEN_OVER;
  132. }
  133. else if( nReadLen == nLen ) // 长度刚好
  134. {
  135. unsigned char chRegNum = pBuffer[2];
  136. // 判断数据长度
  137. if (chRegNum == (unsigned char)nDataLen) goto NormalProcess;
  138. if( chRegNum > (unsigned char)nDataLen)
  139. {
  140. TRACE("请求寄存器个数超时所需的长度,认为是非法包,收完扔掉\r\n");
  141. #if DEBUG_PROTOCOL
  142. SetEvent( m_hSemComm );
  143. if( pBuffer )
  144. {
  145. delete[] pBuffer;
  146. pBuffer = NULL;
  147. }
  148. return ERR_CODE_AIR_STULZ_COM_READ_LEN_OVER;
  149. #else
  150. nProcessLen += nReadLen;
  151. nReadLen = ReadMessage( (BYTE *)(pBuffer + nProcessLen), chRegNum - nDataLen);
  152. SetEvent( m_hSemComm );
  153. if( pBuffer != NULL)
  154. {
  155. delete[] pBuffer;
  156. pBuffer = NULL;
  157. }
  158. return ERR_CODE_AIR_STULZ_COM_READ_LEN_OVER;
  159. #endif
  160. }
  161. else//小于
  162. {
  163. TRACE("读到数据长度小于需要的数据长度!\r\n");
  164. SetEvent( m_hSemComm );
  165. if( pBuffer != NULL)
  166. {
  167. delete[] pBuffer;
  168. pBuffer = NULL;
  169. }
  170. return ERR_CODE_AIR_STULZ_COM_READ_LEN_OVER;
  171. }
  172. }
  173. NormalProcess:
  174. // 判断校验
  175. int iCrc = GetCheckSum((byte*) pBuffer, nLen - 2);
  176. BYTE high = iCrc>>8&0xff;
  177. BYTE low = iCrc&0xff;
  178. if( !( ((byte)pBuffer[nLen - 2] == low) && ((byte)pBuffer[nLen - 1] ==high) ) )
  179. {
  180. TRACE("crc 校验失败!\r\n");
  181. SetEvent( m_hSemComm );
  182. if( pBuffer != NULL)
  183. {
  184. delete[] pBuffer;
  185. pBuffer = NULL;
  186. }
  187. return ERR_CODE_AIR_STULZ_COM_LRC_LOST;
  188. }
  189. EnterCriticalSection( &m_csWrFinished );
  190. memcpy( &m_structResponse.StatusStruct, pBuffer, sizeof(STATUS_STRUCT) );
  191. int nIndex = 0;
  192. for( int i = iCmdPos; i < (iCmdPos + iCmdLen); i++ )
  193. {
  194. int nTmp = sizeof(STATUS_STRUCT) + i;
  195. chMsg[nIndex] = pBuffer[sizeof(STATUS_STRUCT) + i];
  196. nIndex++;
  197. }
  198. LeaveCriticalSection(&m_csWrFinished);
  199. // 设置串口等待事件为有信号
  200. SetEvent( m_hSemComm );
  201. if( pBuffer != NULL)
  202. {
  203. delete[] pBuffer;
  204. pBuffer = NULL;
  205. }
  206. return 0;
  207. }
  208. int CProtocolModbus::RequestStatus(SETBASEPARAM SetBasePara)
  209. {
  210. REQUESTPARAM RequestPara;
  211. int iLen = sizeof(REQUESTPARAM);
  212. #if 0
  213. if (SetBasePara.nStartAddr==0)
  214. iLen -=sizeof(RequestPara .StartAddr);
  215. #endif
  216. if (SetBasePara.FuncCode==1 || //长状态请求1
  217. SetBasePara.FuncCode==33 || //长状态请求2
  218. SetBasePara.FuncCode==9 || //控制器状态2
  219. SetBasePara.FuncCode==10 ||//控制器ID
  220. SetBasePara.FuncCode==11 ||//单元配置
  221. SetBasePara.FuncCode==12)//c5000增加项
  222. {
  223. iLen -= sizeof(RequestPara.StartAddr);
  224. }
  225. char *pData = new char[iLen];
  226. memset( pData, 0, iLen );
  227. memset( &RequestPara, 0, iLen );
  228. RequestPara.AddrCode = SetBasePara.nAddr; //地址码
  229. RequestPara.FuncCode = SetBasePara.FuncCode; //功能码
  230. RequestPara.StartAddr = SetBasePara.nStartAddr; //起始地址
  231. int iTmpLen = sizeof(RequestPara.AddrCode) + sizeof(RequestPara.FuncCode);// + sizeof(RequestPara.Number);
  232. memcpy(pData, &RequestPara, iTmpLen);
  233. if (SetBasePara.FuncCode==1 || //长状态请求1
  234. SetBasePara.FuncCode==33 || //长状态请求2
  235. SetBasePara.FuncCode==9 || //控制器状态2
  236. SetBasePara.FuncCode==10 ||//控制器ID
  237. SetBasePara.FuncCode==11 ||//单元配置
  238. SetBasePara.FuncCode==12)//c5000增加项
  239. {
  240. RequestPara.Number = 2; //下面字节数
  241. memcpy( pData + iTmpLen, &RequestPara.Number, sizeof(RequestPara.Number) );
  242. iTmpLen += sizeof(RequestPara.Number);
  243. }
  244. else
  245. {
  246. memcpy(pData + iTmpLen, &RequestPara.StartAddr, sizeof(RequestPara .StartAddr));
  247. iTmpLen +=sizeof(RequestPara .StartAddr);
  248. RequestPara.Number = 3; //下面字节数
  249. memcpy(pData + iTmpLen, &RequestPara.Number, sizeof(RequestPara.Number) );
  250. iTmpLen += sizeof(RequestPara.Number);
  251. }
  252. SHORT iCheck = GetCheckSum( (BYTE*)pData, iTmpLen);
  253. BYTE high = iCheck>>8&0xff;
  254. BYTE low = iCheck&0xff;
  255. #if 1
  256. RequestPara.Crc[0] = low;
  257. RequestPara.Crc[1] = high;
  258. #else
  259. RequestPara.Crc[0] = high;
  260. RequestPara.Crc[1] = low;
  261. #endif
  262. memcpy(pData + iTmpLen, RequestPara.Crc, sizeof(RequestPara.Crc));
  263. if( WaitForSingleObject( m_hSemComm, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口
  264. {
  265. ResetEvent( m_hSemComm );
  266. int nResult = WriteMessage( (BYTE *)pData, iLen );
  267. if( nResult == iLen )
  268. {
  269. }
  270. else
  271. {
  272. delete []pData;
  273. SetEvent( m_hSemComm );
  274. return EER_CODE_AIR_STULZ_COM_WRITE_DATA;
  275. }
  276. }
  277. else
  278. {
  279. delete []pData;
  280. return ERR_CODE_AIR_STULZ_COM_BUSY;
  281. }
  282. delete[]pData;
  283. return 0;
  284. }
  285. int CProtocolModbus::RequestWrStatus(char DataBuffer[80])//请求写数据
  286. {
  287. char tmpData[4] = {0};
  288. memcpy(tmpData, DataBuffer, sizeof(tmpData));
  289. int iCheck = GetCheckSum( (BYTE*)tmpData, sizeof(tmpData));
  290. BYTE high = iCheck>>8&0xff;
  291. BYTE low = iCheck&0xff;
  292. DataBuffer[4] = low;
  293. DataBuffer[5] = high;
  294. if( WaitForSingleObject( m_hSemComm, 0 ) == WAIT_OBJECT_0 ) // 有信号才写串口
  295. {
  296. ResetEvent( m_hSemComm );
  297. int iResult = WriteMessage((unsigned char *)DataBuffer, sizeof(tmpData) + 2);
  298. if (iResult == ( sizeof(tmpData) + 2))
  299. return 0;
  300. else
  301. {
  302. SetEvent( m_hSemComm );
  303. return EER_CODE_AIR_STULZ_COM_WRITE_DATA;
  304. }
  305. }
  306. else
  307. {
  308. return EER_CODE_AIR_STULZ_COM_WRITE_DATA;
  309. }
  310. }
  311. int CProtocolModbus::ResponseWrStatus(char ResDataBuffer[2])
  312. {
  313. char chBuffer[6] = {0};
  314. int iProcessLen = 0;
  315. int iLen = sizeof(chBuffer);
  316. int iReadLen = ReadMessage((BYTE *)chBuffer, iLen);
  317. if( iReadLen <= 0) // 串口没有读到数据
  318. {
  319. SetEvent( m_hSemComm );
  320. return ERR_CODE_AIR_STULZ_COM_READ_NO_DATA;
  321. }
  322. else if(iReadLen< iLen)
  323. {
  324. TRACE("长度没有收够,断续接收,直到收完为止!\r\n");
  325. iProcessLen += iReadLen;
  326. iReadLen = ReadMessage( (BYTE *)(chBuffer + iProcessLen), iLen - iProcessLen );
  327. while( iReadLen != iLen - iProcessLen )
  328. {
  329. if( iReadLen == 0 )
  330. {
  331. SetEvent( m_hSemComm );
  332. return ERR_CODE_AIR_STULZ_COM_READ_NO_DATA;// 还是没有收到数据,直接返回
  333. }
  334. iProcessLen += iReadLen;
  335. iReadLen = ReadMessage( (BYTE *)(chBuffer + iProcessLen), iLen - iProcessLen);
  336. }
  337. if( iReadLen == iLen )
  338. {
  339. SetEvent( m_hSemComm );
  340. return ERR_CODE_AIR_STULZ_COM_FAULT;
  341. }
  342. }
  343. else if( iReadLen > iLen )//实际读到包长度大于要求包的长度
  344. {
  345. // 完全代码,不一定能执行到
  346. TRACE("接收的长度超时所需的长度,认为是非法包,扔掉\r\n");
  347. SetEvent( m_hSemComm );
  348. return ERR_CODE_AIR_STULZ_COM_READ_LEN_OVER;
  349. }
  350. else if (iReadLen == iLen)//读到的包长度相等
  351. {
  352. // 判断寄存器的个数正确吗?
  353. if (chBuffer[1] == 7 && chBuffer[2] == 3)
  354. {
  355. goto NormalProcess;
  356. }
  357. else
  358. {
  359. SetEvent( m_hSemComm );
  360. return ERR_CODE_AIR_STULZ_COM_READ_LEN_OVER;
  361. }
  362. }
  363. NormalProcess:
  364. char tmpData[4] = {0};
  365. memcpy(tmpData, chBuffer, sizeof(tmpData));
  366. int iCheck = GetCheckSum( (BYTE*)tmpData, sizeof(tmpData));
  367. BYTE high = iCheck>>8&0xff;
  368. BYTE low = iCheck&0xff;
  369. //DataBuffer[4] = low;
  370. //DataBuffer[5] = high;
  371. if( !( chBuffer[4] == low && chBuffer[5] == high ) )
  372. {
  373. TRACE("应答数据校验失败!\r\n");
  374. SetEvent( m_hSemComm );
  375. return ERR_CODE_AIR_STULZ_COM_LRC_LOST;
  376. }
  377. ResDataBuffer[0] = chBuffer[3];
  378. // 设置串口等待事件为有信号
  379. SetEvent( m_hSemComm );
  380. return 0;
  381. }
  382. WORD CProtocolModbus::GetCheckSum(BYTE *pBuf, int len)
  383. {
  384. WORD iSum = 0;
  385. WORD iCompliment;
  386. unsigned char chCompliment[2] = {0};
  387. for(int i=0; i<len; i++)//求和
  388. iSum += pBuf[i];
  389. #if 0
  390. if( iSum < 0 )
  391. {
  392. WORD iCompliment = iSum ;
  393. iCompliment = ~iCompliment;//取反
  394. iCompliment++;
  395. }
  396. else
  397. {
  398. iCompliment = iSum;
  399. }
  400. #else
  401. iCompliment = iSum ;
  402. iCompliment = ~iCompliment;//取反
  403. iCompliment++;
  404. #endif
  405. return iCompliment;
  406. }
  407. BOOL CProtocolModbus::InitParam(PPORTPARAM pPortParam, CCommAsyn *pComm)
  408. {
  409. int addr=pPortParam->StartAddr;
  410. m_pComm=pComm;
  411. return TRUE;
  412. }
  413. void strReverse( char *str )
  414. {
  415. int l = strlen(str);
  416. for( int i = 0; i < l; i++ )
  417. {
  418. for(int i = 0; i < l; i++)
  419. {
  420. if( str[i] >= 'A' && str[i] <= 'Z' )
  421. {
  422. str[i] += 32;
  423. }
  424. else if(str[i] >= 'a' && str[i] <= 'z')
  425. {
  426. str[i] -= 32;
  427. }
  428. }
  429. }
  430. }
  431. char lowercase2uppercase(BYTE btSrc)
  432. {
  433. if( btSrc >= 'a' && btSrc <= 'z' )
  434. {
  435. return btSrc - 'a' + 'A';
  436. }
  437. return btSrc;
  438. }
  439. char ByteToAscii(BYTE btSrc)
  440. {
  441. char chDest;
  442. if( btSrc < 10 )
  443. {
  444. chDest = (char)(btSrc % 10 + '0');
  445. chDest = lowercase2uppercase(chDest);
  446. return chDest;
  447. }
  448. else
  449. {
  450. chDest = ByteToAscii( btSrc / 10 ) + (char)( btSrc % 10 + '0' );
  451. chDest = lowercase2uppercase(chDest);
  452. return chDest;
  453. }
  454. }
  455. WORD AsciiToBYTE(BYTE btSrc)
  456. {
  457. WORD chDest = (WORD)btSrc;
  458. if ((btSrc >= 'A')&&(btSrc <= 'F'))
  459. {
  460. chDest = chDest - 'A' + 10;
  461. }
  462. else if ((btSrc >= 'a')&&(btSrc <= 'f'))
  463. {
  464. chDest = chDest - 'a' + 10;
  465. }
  466. else if ((btSrc >= '0')&&(btSrc <= '9'))
  467. {
  468. chDest -= '0';
  469. }
  470. return chDest;
  471. }