SynSerial.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. #include "StdAfx.h"
  2. #include "SynSerial.h"
  3. int CSynSerial::s_nCurPos = 0;
  4. byte CSynSerial::s_byBuffer[BUFFER_LEN];
  5. ThreadSection CSynSerial::s_csClearBuffer;
  6. CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
  7. , m_dwInQueue(1024)
  8. , m_dwOutQueue(1024)
  9. {
  10. memset(&m_dcb, 0, sizeof(DCB));
  11. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  12. memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
  13. m_hEvent = NULL;
  14. m_hThread = NULL;
  15. // 初始化重叠对象;
  16. ZeroMemory(&m_writeOverlapped,sizeof(m_writeOverlapped));
  17. if (m_writeOverlapped.hEvent != NULL) {
  18. ResetEvent(m_writeOverlapped.hEvent);
  19. m_writeOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  20. }
  21. ZeroMemory(&m_readOverlapped,sizeof(m_readOverlapped));
  22. if (m_readOverlapped.hEvent != NULL) {
  23. ResetEvent(m_readOverlapped.hEvent);
  24. m_readOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  25. }
  26. }
  27. CSynSerial::~CSynSerial(void)
  28. {
  29. EndofThread();
  30. CloseSerialPort();
  31. }
  32. BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwBaudRate, IN CONST BYTE & bySize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST INT & nInterval)
  33. {
  34. ASSERT(byCommPort);
  35. CloseSerialPort();
  36. _stprintf_s(m_szSerialPort, _T("\\\\.\\com%d"), (int)byCommPort);
  37. m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
  38. if (m_hSerialPort == INVALID_HANDLE_VALUE)
  39. {
  40. // 打开串口失败;
  41. DWORD dwError = GetLastError();
  42. return FALSE;
  43. }
  44. BOOL bResult = FALSE;
  45. // SetupComm设置缓冲区大小;
  46. bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
  47. if (!bResult)
  48. {
  49. CloseHandle(m_hSerialPort);
  50. m_hSerialPort = INVALID_HANDLE_VALUE;
  51. DWORD dwError = GetLastError();
  52. return FALSE;
  53. }
  54. // 在串口读写之前,清除缓冲区;
  55. bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
  56. if (!bResult)
  57. {
  58. CloseHandle(m_hSerialPort);
  59. m_hSerialPort = INVALID_HANDLE_VALUE;
  60. DWORD dwError = GetLastError();
  61. return FALSE;
  62. }
  63. // GetCommState获取设备控制块状态;
  64. memset(&m_dcb, 0, sizeof(DCB));
  65. bResult = GetCommState(m_hSerialPort, &m_dcb);
  66. if (!bResult) {
  67. CloseHandle(m_hSerialPort);
  68. m_hSerialPort = INVALID_HANDLE_VALUE;
  69. DWORD dwError = GetLastError();
  70. return FALSE;
  71. }
  72. m_dcb.Parity = byParity;
  73. if (m_dcb.Parity == NOPARITY)
  74. m_dcb.fParity = FALSE;
  75. else
  76. m_dcb.fParity = TRUE;
  77. m_dcb.BaudRate = dwBaudRate;
  78. m_dcb.ByteSize = bySize;
  79. m_dcb.StopBits = byStopBits;
  80. if (m_dcb.ByteSize == 8)
  81. m_dcb.StopBits = ONESTOPBIT;
  82. // SetCommState设置设备的控制块状态;
  83. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  84. bResult = SetCommState(m_hSerialPort, &m_dcb);
  85. if (!bResult) {
  86. CloseHandle(m_hSerialPort);
  87. m_hSerialPort = INVALID_HANDLE_VALUE;
  88. DWORD dwError = GetLastError();
  89. return FALSE;
  90. }
  91. // 获取设备的超时值;
  92. bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
  93. if (!bResult) {
  94. CloseHandle(m_hSerialPort);
  95. m_hSerialPort = INVALID_HANDLE_VALUE;
  96. DWORD dwError = GetLastError();
  97. return FALSE;
  98. }
  99. // 两字符之间最大的延时,设置0表示参数不起作用;
  100. m_cts.ReadIntervalTimeout = 50;
  101. m_cts.ReadTotalTimeoutMultiplier = 100;
  102. m_cts.ReadTotalTimeoutConstant = 8000;
  103. m_cts.WriteTotalTimeoutMultiplier = 100;
  104. m_cts.WriteTotalTimeoutConstant = 5000;
  105. // 设置设备的超时值;
  106. bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
  107. if (!bResult) {
  108. CloseHandle(m_hSerialPort);
  109. m_hSerialPort = INVALID_HANDLE_VALUE;
  110. DWORD dwError = GetLastError();
  111. return FALSE;
  112. }
  113. return TRUE;
  114. }
  115. BOOL CSynSerial::ReOpenSerialPort()
  116. {
  117. ASSERT(_tcslen(m_szSerialPort));
  118. CloseSerialPort();
  119. m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
  120. if (m_hSerialPort == INVALID_HANDLE_VALUE)
  121. {
  122. // 打开串口失败;
  123. DWORD dwError = GetLastError();
  124. return FALSE;
  125. }
  126. BOOL bResult = FALSE;
  127. // SetupComm设置缓冲区大小;
  128. bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
  129. if (!bResult)
  130. {
  131. CloseHandle(m_hSerialPort);
  132. m_hSerialPort = INVALID_HANDLE_VALUE;
  133. DWORD dwError = GetLastError();
  134. return FALSE;
  135. }
  136. // 在串口读写之前,清除缓冲区;
  137. bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
  138. if (!bResult)
  139. {
  140. CloseHandle(m_hSerialPort);
  141. m_hSerialPort = INVALID_HANDLE_VALUE;
  142. DWORD dwError = GetLastError();
  143. return FALSE;
  144. }
  145. // SetCommState设置设备的控制块状态;
  146. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  147. bResult = SetCommState(m_hSerialPort, &m_dcb);
  148. if (!bResult)
  149. {
  150. CloseHandle(m_hSerialPort);
  151. m_hSerialPort = INVALID_HANDLE_VALUE;
  152. DWORD dwError = GetLastError();
  153. return FALSE;
  154. }
  155. // 设置设备的超时值;
  156. bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
  157. if (!bResult)
  158. {
  159. CloseHandle(m_hSerialPort);
  160. m_hSerialPort = INVALID_HANDLE_VALUE;
  161. DWORD dwError = GetLastError();
  162. return FALSE;
  163. }
  164. return TRUE;
  165. }
  166. void CSynSerial::CloseSerialPort()
  167. {
  168. if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
  169. CloseHandle(m_hSerialPort);
  170. m_hSerialPort = INVALID_HANDLE_VALUE;
  171. }
  172. BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byByteSize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST DWORD & dwInQueue, IN CONST DWORD & dwOutQueue)
  173. {
  174. if (!IsOpen())
  175. return FALSE;
  176. BOOL bResult = FALSE;
  177. // GetCommState获取设备控制块状态;
  178. memset(&m_dcb, 0, sizeof(DCB));
  179. bResult = GetCommState(m_hSerialPort, &m_dcb);
  180. if (!bResult)
  181. {
  182. DWORD dwError = GetLastError();
  183. return FALSE;
  184. }
  185. m_dcb.Parity = byParity;
  186. if (m_dcb.Parity == NOPARITY)
  187. m_dcb.fParity = FALSE;
  188. else
  189. m_dcb.fParity = TRUE;
  190. m_dcb.BaudRate = dwBaudRate;
  191. m_dcb.ByteSize = byByteSize;
  192. m_dcb.StopBits = byStopBits;
  193. if (m_dcb.ByteSize == 8)
  194. m_dcb.StopBits = ONESTOPBIT;
  195. // SetCommState设置设备的控制块状态;
  196. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  197. bResult = SetCommState(m_hSerialPort, &m_dcb);
  198. if (!bResult)
  199. {
  200. DWORD dwError = GetLastError();
  201. return FALSE;
  202. }
  203. // 获取设备的超时值;
  204. bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
  205. if (!bResult)
  206. {
  207. DWORD dwError = GetLastError();
  208. return FALSE;
  209. }
  210. // 两字符之间最大的延时,设置0表示参数不起作用;
  211. m_cts.ReadIntervalTimeout = 50;
  212. m_cts.ReadTotalTimeoutMultiplier = 100;
  213. m_cts.ReadTotalTimeoutConstant = 8000;
  214. m_cts.WriteTotalTimeoutMultiplier = 100;
  215. m_cts.WriteTotalTimeoutConstant = 3000;
  216. // 设置设备的超时值;
  217. bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
  218. if (!bResult)
  219. {
  220. DWORD dwError = GetLastError();
  221. return FALSE;
  222. }
  223. return TRUE;
  224. }
  225. void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
  226. {
  227. }
  228. void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
  229. {
  230. }
  231. bool CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
  232. {
  233. if (!IsOpen())
  234. return false;
  235. if (pWirteBuf == NULL || !::AfxIsValidAddress(pWirteBuf, nWriteSize, FALSE))
  236. {
  237. return false;
  238. }
  239. DWORD dwErrorFlags;
  240. DWORD dwBytesWritten = 0; // 实际写入的字节数;
  241. // 写前, 清除错误;
  242. COMSTAT ComStat;
  243. ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
  244. // 写前,清空缓存区;
  245. PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  246. if ( !WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, &m_writeOverlapped) ) {
  247. DWORD dwError = GetLastError();
  248. if ( ERROR_IO_PENDING == GetLastError() ) {
  249. while(!GetOverlappedResult(m_hSerialPort, &m_writeOverlapped, &dwBytesWritten, FALSE)){
  250. #if 0
  251. printf("\t\t写串口出错: %d,%d,%d,%d,%d,%d\n",
  252. GetLastError(), m_writeOverlapped.Internal, m_writeOverlapped.InternalHigh,
  253. m_writeOverlapped.Offset, m_writeOverlapped.OffsetHigh,dwBytesWritten);
  254. #endif
  255. }
  256. }
  257. }
  258. #ifdef _DEBUG
  259. if (dwBytesWritten == nWriteSize)
  260. printf("\t写串口成功:%s\n", pWirteBuf);
  261. else
  262. printf("\t写串口失败:%s\n",pWirteBuf);
  263. #endif
  264. // 返回写入字节数;
  265. return (dwBytesWritten == nWriteSize);
  266. }
  267. DWORD CSynSerial::ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout /* = 300 */)
  268. {
  269. if (!IsOpen())
  270. return 0;
  271. if (pReadBuf == NULL || !::AfxIsValidAddress(pReadBuf, dwReadSize, FALSE))
  272. {
  273. return 0;
  274. }
  275. DWORD dwError = 0;
  276. DWORD dwRealRead = 0;
  277. if ( !ClearCommError(m_hSerialPort, &dwError, NULL) ) {
  278. PurgeComm(m_hSerialPort, PURGE_TXABORT|PURGE_TXCLEAR);
  279. }
  280. if ( !ReadFile(m_hSerialPort, pReadBuf, dwReadSize, &dwRealRead, &m_readOverlapped) ) {
  281. if ( STATUS_PENDING == m_readOverlapped.Internal ) {
  282. while(!GetOverlappedResult(m_hSerialPort, &m_readOverlapped, &dwRealRead, FALSE)){
  283. #if 0
  284. static int i = 0;
  285. static TCHAR szLog[MAX_PATH] ;
  286. Sleep(20);
  287. _stprintf_s(szLog,"\t\t读串口出错: %d = %d,%d,%d,%d,%d,%d\n", ++i,
  288. GetLastError(), m_readOverlapped.Internal, m_readOverlapped.InternalHigh,
  289. m_readOverlapped.Offset, m_readOverlapped.OffsetHigh, dwRealRead);
  290. OutputDebugString(szLog);
  291. #endif
  292. // 是否仍在等待;
  293. if ( STATUS_PENDING != m_readOverlapped.Internal ) {
  294. break;
  295. }
  296. // 线程是否结束;
  297. if ( m_hThread && WaitForSingleObject(m_hEvent, 0) == WAIT_OBJECT_0 )
  298. break;
  299. }
  300. }
  301. }
  302. return m_readOverlapped.InternalHigh;
  303. }
  304. void CSynSerial::StartThread()
  305. {
  306. if ( m_hEvent || m_hThread )
  307. return;
  308. m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  309. if ( m_hEvent == NULL )
  310. return;
  311. m_hThread = CreateThread(NULL, 0, ThreadWatch, this, 0, NULL);
  312. if ( m_hThread == NULL ) {
  313. SetEvent(m_hEvent);
  314. CloseHandle(m_hEvent);
  315. m_hEvent = NULL;
  316. }
  317. }
  318. void CSynSerial::EndofThread()
  319. {
  320. // 设置有信号;
  321. if ( m_hEvent ) {
  322. SetEvent(m_hEvent);
  323. }
  324. // 等待线程结束;
  325. if ( m_hThread ) {
  326. WaitForSingleObject(m_hThread, INFINITE);
  327. CloseHandle(m_hThread);
  328. m_hThread = NULL;
  329. }
  330. if ( m_hEvent )
  331. CloseHandle(m_hEvent);
  332. m_hEvent = NULL;
  333. }
  334. void CSynSerial::SwapBuffers(TCHAR *szValue, DWORD dwRealRead)
  335. {
  336. #if 0 // 过于复杂的逻辑处理
  337. int nLeft = 0;
  338. bool bFist = true; // 是否填充完整过;
  339. int nIndex = 0;
  340. if ( s_nCurPos + dwRealRead <= BUFFER_LEN ) {
  341. memcpy_s(&s_byBuffer[s_nCurPos], BUFFER_LEN-s_nCurPos, szValue, dwRealRead);
  342. s_nCurPos += dwRealRead;
  343. } else {
  344. nLeft = dwRealRead - (nIndex = BUFFER_LEN - s_nCurPos);
  345. // 先将尾部填充;
  346. memcpy_s(&s_byBuffer[s_nCurPos], BUFFER_LEN-s_nCurPos, szValue, BUFFER_LEN-s_nCurPos);
  347. // 剩余是否大于缓冲区;
  348. while ( nLeft > BUFFER_LEN ) {
  349. // 先复制尾部;
  350. nIndex += BUFFER_LEN;
  351. memcpy_s(s_byBuffer, BUFFER_LEN, &szValue[nIndex], BUFFER_LEN);
  352. nLeft -= BUFFER_LEN;
  353. }
  354. s_nCurPos = nLeft;
  355. // 处理最后剩余的数据;
  356. if ( nLeft != 0 ) {
  357. memcpy_s(s_byBuffer, nLeft, &szValue[nIndex], nLeft);
  358. }
  359. }
  360. m_strbuffer.append(szValue, dwRealRead);
  361. // 超过10倍才清空;
  362. if ( m_strbuffer.size() > BUFFER_LEN*3) {
  363. m_strbuffer.resize(0);
  364. m_strbuffer.clear();
  365. // 如果遇到\0开头,显示空字符,但实现有内容;
  366. m_strbuffer.append((char*)&s_byBuffer[s_nCurPos], BUFFER_LEN - s_nCurPos);
  367. m_strbuffer.append((char*)s_byBuffer, s_nCurPos);
  368. }
  369. #else
  370. if ( m_strbuffer.length() > BUFFER_LEN * 10 ) {
  371. int nIndex = 0;
  372. m_strbuffer = m_strbuffer.substr(BUFFER_LEN * 9);
  373. if ( (nIndex = m_strbuffer.find_first_of('\r')) != std::string::npos )
  374. m_strbuffer = m_strbuffer.substr(nIndex+1);
  375. }
  376. m_strbuffer.append(szValue, dwRealRead);
  377. #endif
  378. printf("内容:%s\n", m_strbuffer.c_str());
  379. }
  380. DWORD CSynSerial::ThreadWatch(LPVOID lpVoid)
  381. {
  382. int nLeft = 0;
  383. bool bFist = true; // 是否填充完整过;
  384. int nIndex = 0;
  385. DWORD dwRealRead;
  386. TCHAR szValue[1024] = {0};
  387. CSynSerial *pthat = (CSynSerial*)lpVoid;
  388. do
  389. {
  390. memset(szValue, 0, 1024);
  391. if ( (dwRealRead = pthat->ReadComm((BYTE*)szValue, 1024)) > 0) {
  392. AutoThreadSection aSection(&s_csClearBuffer);
  393. #ifdef _DEBUG
  394. OutputDebugString(_T("内容:"));
  395. OutputDebugString(szValue);
  396. OutputDebugString(_T("\n"));
  397. #endif
  398. #if 1
  399. if ( pthat->m_strbuffer.length() > BUFFER_LEN * 10 ) {
  400. int nIndex = 0;
  401. pthat->m_strbuffer = pthat->m_strbuffer.substr(BUFFER_LEN * 9);
  402. if ( (nIndex = pthat->m_strbuffer.find_first_of('\r')) != std::string::npos )
  403. pthat->m_strbuffer = pthat->m_strbuffer.substr(nIndex+1);
  404. }
  405. pthat->m_strbuffer.append(szValue, dwRealRead);
  406. #else // 这里如果不及时清除,内存越来越大;
  407. pthat->m_strbuffer.append(szValue, dwRealRead);
  408. #endif
  409. }
  410. } while ( WaitForSingleObject(pthat->m_hEvent, 30) == WAIT_TIMEOUT );
  411. #ifdef _DEBUG
  412. printf("线程结束\n");
  413. #endif
  414. return 0;
  415. }
  416. bool CSynSerial::FindWord(std::string strWord, int nWatchTime )
  417. {
  418. bool found = false;
  419. int nSize = nWatchTime/30;
  420. for ( int i = 0; i < nSize; i++ ) {
  421. if ( m_strbuffer.find(strWord) != std::string::npos ) {
  422. found = true;
  423. break;
  424. }
  425. Sleep(30);
  426. }
  427. return found;
  428. }