SynSerial.cpp 7.0 KB

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