SynSerial.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include "StdAfx.h"
  2. #include "SynSerial.h"
  3. CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
  4. , m_dwInQueue(1024)
  5. , m_dwOutQueue(1024)
  6. {
  7. memset(&m_dcb, 0, sizeof(DCB));
  8. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  9. memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
  10. }
  11. CSynSerial::~CSynSerial(void)
  12. {
  13. CloseSerialPort();
  14. }
  15. 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)
  16. {
  17. ASSERT(byCommPort);
  18. CloseSerialPort();
  19. _stprintf_s(m_szSerialPort, _T("\\\\.\\com%d"), (int)byCommPort);
  20. m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
  21. if (m_hSerialPort == INVALID_HANDLE_VALUE)
  22. {
  23. // 打开串口失败;
  24. DWORD dwError = GetLastError();
  25. return FALSE;
  26. }
  27. BOOL bResult = FALSE;
  28. // SetupComm设置缓冲区大小;
  29. bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
  30. if (!bResult)
  31. {
  32. CloseHandle(m_hSerialPort);
  33. m_hSerialPort = INVALID_HANDLE_VALUE;
  34. DWORD dwError = GetLastError();
  35. return FALSE;
  36. }
  37. // 在串口读写之前,清除缓冲区;
  38. bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
  39. if (!bResult)
  40. {
  41. CloseHandle(m_hSerialPort);
  42. m_hSerialPort = INVALID_HANDLE_VALUE;
  43. DWORD dwError = GetLastError();
  44. return FALSE;
  45. }
  46. // GetCommState获取设备控制块状态;
  47. memset(&m_dcb, 0, sizeof(DCB));
  48. bResult = GetCommState(m_hSerialPort, &m_dcb);
  49. if (!bResult)
  50. {
  51. CloseHandle(m_hSerialPort);
  52. m_hSerialPort = INVALID_HANDLE_VALUE;
  53. DWORD dwError = GetLastError();
  54. return FALSE;
  55. }
  56. m_dcb.Parity = byParity;
  57. if (m_dcb.Parity == NOPARITY)
  58. m_dcb.fParity = FALSE;
  59. else
  60. m_dcb.fParity = TRUE;
  61. m_dcb.BaudRate = dwBaudRate;
  62. m_dcb.ByteSize = bySize;
  63. m_dcb.StopBits = byStopBits;
  64. if (m_dcb.ByteSize == 8)
  65. m_dcb.StopBits = ONESTOPBIT;
  66. // SetCommState设置设备的控制块状态;
  67. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  68. bResult = SetCommState(m_hSerialPort, &m_dcb);
  69. if (!bResult)
  70. {
  71. CloseHandle(m_hSerialPort);
  72. m_hSerialPort = INVALID_HANDLE_VALUE;
  73. DWORD dwError = GetLastError();
  74. return FALSE;
  75. }
  76. // 获取设备的超时值;
  77. bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
  78. if (!bResult)
  79. {
  80. CloseHandle(m_hSerialPort);
  81. m_hSerialPort = INVALID_HANDLE_VALUE;
  82. DWORD dwError = GetLastError();
  83. return FALSE;
  84. }
  85. // 两字符之间最大的延时,设置0表示参数不起作用;
  86. m_cts.ReadIntervalTimeout = 50;
  87. m_cts.ReadTotalTimeoutMultiplier = 100;
  88. m_cts.ReadTotalTimeoutConstant = 8000;
  89. m_cts.WriteTotalTimeoutMultiplier = 100;
  90. m_cts.WriteTotalTimeoutConstant = 5000;
  91. // 设置设备的超时值;
  92. bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
  93. if (!bResult)
  94. {
  95. CloseHandle(m_hSerialPort);
  96. m_hSerialPort = INVALID_HANDLE_VALUE;
  97. DWORD dwError = GetLastError();
  98. return FALSE;
  99. }
  100. return TRUE;
  101. }
  102. BOOL CSynSerial::ReOpenSerialPort()
  103. {
  104. ASSERT(_tcslen(m_szSerialPort));
  105. CloseSerialPort();
  106. m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
  107. if (m_hSerialPort == INVALID_HANDLE_VALUE)
  108. {
  109. // 打开串口失败;
  110. DWORD dwError = GetLastError();
  111. return FALSE;
  112. }
  113. BOOL bResult = FALSE;
  114. // SetupComm设置缓冲区大小;
  115. bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
  116. if (!bResult)
  117. {
  118. CloseHandle(m_hSerialPort);
  119. m_hSerialPort = INVALID_HANDLE_VALUE;
  120. DWORD dwError = GetLastError();
  121. return FALSE;
  122. }
  123. // 在串口读写之前,清除缓冲区;
  124. bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
  125. if (!bResult)
  126. {
  127. CloseHandle(m_hSerialPort);
  128. m_hSerialPort = INVALID_HANDLE_VALUE;
  129. DWORD dwError = GetLastError();
  130. return FALSE;
  131. }
  132. // SetCommState设置设备的控制块状态;
  133. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  134. bResult = SetCommState(m_hSerialPort, &m_dcb);
  135. if (!bResult)
  136. {
  137. CloseHandle(m_hSerialPort);
  138. m_hSerialPort = INVALID_HANDLE_VALUE;
  139. DWORD dwError = GetLastError();
  140. return FALSE;
  141. }
  142. // 设置设备的超时值;
  143. bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
  144. if (!bResult)
  145. {
  146. CloseHandle(m_hSerialPort);
  147. m_hSerialPort = INVALID_HANDLE_VALUE;
  148. DWORD dwError = GetLastError();
  149. return FALSE;
  150. }
  151. return TRUE;
  152. }
  153. void CSynSerial::CloseSerialPort()
  154. {
  155. if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
  156. CloseHandle(m_hSerialPort);
  157. m_hSerialPort = INVALID_HANDLE_VALUE;
  158. }
  159. 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)
  160. {
  161. if (!IsOpen())
  162. return FALSE;
  163. BOOL bResult = FALSE;
  164. // GetCommState获取设备控制块状态;
  165. memset(&m_dcb, 0, sizeof(DCB));
  166. bResult = GetCommState(m_hSerialPort, &m_dcb);
  167. if (!bResult)
  168. {
  169. DWORD dwError = GetLastError();
  170. return FALSE;
  171. }
  172. m_dcb.Parity = byParity;
  173. if (m_dcb.Parity == NOPARITY)
  174. m_dcb.fParity = FALSE;
  175. else
  176. m_dcb.fParity = TRUE;
  177. m_dcb.BaudRate = dwBaudRate;
  178. m_dcb.ByteSize = byByteSize;
  179. m_dcb.StopBits = byStopBits;
  180. if (m_dcb.ByteSize == 8)
  181. m_dcb.StopBits = ONESTOPBIT;
  182. // SetCommState设置设备的控制块状态;
  183. memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
  184. bResult = SetCommState(m_hSerialPort, &m_dcb);
  185. if (!bResult)
  186. {
  187. DWORD dwError = GetLastError();
  188. return FALSE;
  189. }
  190. // 获取设备的超时值;
  191. bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
  192. if (!bResult)
  193. {
  194. DWORD dwError = GetLastError();
  195. return FALSE;
  196. }
  197. // 两字符之间最大的延时,设置0表示参数不起作用;
  198. m_cts.ReadIntervalTimeout = 50;
  199. m_cts.ReadTotalTimeoutMultiplier = 100;
  200. m_cts.ReadTotalTimeoutConstant = 8000;
  201. m_cts.WriteTotalTimeoutMultiplier = 100;
  202. m_cts.WriteTotalTimeoutConstant = 3000;
  203. // 设置设备的超时值;
  204. bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
  205. if (!bResult)
  206. {
  207. DWORD dwError = GetLastError();
  208. return FALSE;
  209. }
  210. return TRUE;
  211. }
  212. void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
  213. {
  214. }
  215. void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
  216. {
  217. }
  218. DWORD CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
  219. {
  220. if (!IsOpen())
  221. return 0;
  222. if (pWirteBuf == NULL || !::AfxIsValidAddress(pWirteBuf, nWriteSize, FALSE))
  223. {
  224. return 0;
  225. }
  226. DWORD dwErrorFlags;
  227. DWORD dwBytesWritten = 0; // 实际写入的字节数;
  228. // 写前, 清除错误;
  229. COMSTAT ComStat;
  230. ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
  231. // 写前,清空缓存区;
  232. PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  233. if ( !WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, NULL) )
  234. {
  235. DWORD dwError = GetLastError();
  236. }
  237. // 返回写入字节数;
  238. return dwBytesWritten;
  239. }
  240. DWORD CSynSerial::ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout /* = 300 */)
  241. {
  242. if (!IsOpen())
  243. return 0;
  244. if (pReadBuf == NULL || !::AfxIsValidAddress(pReadBuf, dwReadSize, FALSE))
  245. {
  246. return 0;
  247. }
  248. DWORD dwBytesRead = 0;
  249. DWORD dwErrorFlags = 0;
  250. // ReadFile前,使用ClearCommError清除错误;
  251. COMSTAT ComStat = {0};
  252. DWORD dwLastLen = 0;
  253. ULONGLONG ulTick = GetTickCount64();
  254. // 直到有数据为止,超时3秒;
  255. while (true)
  256. {// cbInQue表示输入缓冲区的字节数;
  257. Sleep(timeout);
  258. ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
  259. if (GetTickCount64() - ulTick > 3000)
  260. break;
  261. // 防止读一次没读完,再读一次;二次长度一样表示读完;
  262. if (ComStat.cbInQue != 0 && dwLastLen == ComStat.cbInQue)
  263. break;
  264. dwLastLen = ComStat.cbInQue;
  265. }
  266. if (ComStat.cbInQue == 0)
  267. {
  268. // 串口超时,无数据返回;
  269. return 0;
  270. }
  271. dwBytesRead = ComStat.cbInQue;
  272. if (dwReadSize < dwBytesRead)
  273. {
  274. dwBytesRead = dwReadSize;
  275. }
  276. if (ReadFile(m_hSerialPort, pReadBuf, dwBytesRead, &dwBytesRead, NULL))
  277. {
  278. return (INT)dwBytesRead;
  279. }
  280. return dwBytesRead;
  281. }