HwCOM.cpp
上传用户:shmeyee
上传日期:2015-06-28
资源大小:108k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

  1. // COM.cpp: implementation of the CHwCOM class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "HwCOM.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14. CHwCOM::CHwCOM ()
  15. : m_bDeviceGotway ( FALSE )
  16. , m_pCSFor_OpenCOM ( NULL )
  17. {
  18. m_nComNo = INVALID_COM_NO;
  19. ZeroMemory(&m_CommProp,sizeof(COMMPROP));
  20. m_handleCOM = NULL;
  21. }
  22. CHwCOM::~CHwCOM()
  23. {
  24. CloseCOM();
  25. }
  26. /********************************************************************************
  27. * Function Type : Public
  28. * Parameter : buf - 读数据缓冲
  29. * dwSize - 要读的字节数
  30. * Return Value : >=0 - 读到的字节数
  31. * -1 - 串口丢失
  32. * Description : 从串口中读数据, 该类无法判断接在串口上的设备被移走的情况,必须
  33. * 由调用者根据不同的通信协议来判断设备被移走的情况
  34. *********************************************************************************/
  35. int CHwCOM::Read(char *data, int size)
  36. {
  37. if ( GetCommInputBuffLen () <= 0 ) return 0;
  38. int nRet = Transmit ( data, size, TRUE );
  39. return nRet;
  40. }
  41. /********************************************************************************
  42. * Function Type : Public
  43. * Parameter : buf - 写数据缓冲
  44. * dwSize - 要写的字节数
  45. * Return Value : >=0 - 写出去的字节数
  46. * -1 - 串口丢失
  47. * Description : 往串口中写数据, 该类无法判断接在串口上的设备被移走的情况,必须
  48. * 由调用者根据不同的通信协议来判断设备被移走的情况
  49. *********************************************************************************/
  50. int CHwCOM::Write(char *data, int size)
  51. {
  52. if ( size < 1 ) return 0;
  53. return Transmit ( data, size, FALSE );
  54. }
  55. /********************************************************************************
  56. * Function Type : Public
  57. * Parameter : buf - 写数据缓冲
  58. * dwSize - 要写的字节数
  59. * Return Value : >=0 - 传输成功的字节数
  60. * -1 - 串口丢失
  61. * Description : 与串口数据通信, 该类无法判断接在串口上的设备被移走的情况,必须
  62. * 由调用者根据不同的通信协议来判断设备被移走的情况
  63. *********************************************************************************/
  64. int CHwCOM::Transmit(char *data, int size, BOOL bRead)
  65. {
  66. if ( m_bDeviceGotway ) return 0;
  67. DWORD dwTransmitBytes = 0;
  68. m_CSFor_TransmitCOM.Lock();
  69. BOOL bRet = FALSE;
  70. for ( int i=0; i< COM_REMOVE_MAX_ERROR; i++ )
  71. {
  72. if ( bRead )
  73. bRet = ::ReadFile ( m_handleCOM, data, size, &dwTransmitBytes, NULL );
  74. else
  75. bRet = ::WriteFile ( m_handleCOM, data, size, &dwTransmitBytes, NULL );
  76. if ( bRet ) break;
  77. Sleep ( 1 );
  78. }
  79. m_CSFor_TransmitCOM.Unlock();
  80. // 串口通信成功
  81. if ( bRet )
  82. {
  83. return (int)dwTransmitBytes;
  84. }
  85. // 串口丢失
  86. m_bDeviceGotway = TRUE;
  87. return -1;
  88. }
  89. /********************************************************************************
  90. * Function Type : Private
  91. * Parameter : bClearRead - TRUE  : 终止读操作并清除读缓冲
  92. * FALSE : 终止写操作并清除写缓冲
  93. * Return Value : None
  94. * Description : 清空串口所有缓冲和字符
  95. *********************************************************************************/
  96. void CHwCOM::ClearComm(BOOL bClearRead)
  97. {
  98. m_CSFor_TransmitCOM.Lock();
  99. if(bClearRead)
  100. PurgeComm(m_handleCOM, PURGE_RXABORT | PURGE_RXCLEAR);
  101. else
  102. PurgeComm(m_handleCOM, PURGE_TXABORT | PURGE_TXCLEAR);
  103. m_CSFor_TransmitCOM.Unlock();
  104. }
  105. /********************************************************************************
  106. * Function Type : Public
  107. * Parameter : None
  108. * Return Value : 长度
  109. * Description : 获得串口输入缓冲区的长度
  110. *********************************************************************************/
  111. DWORD CHwCOM::GetCommInputBuffLen ()
  112. {
  113. DWORD Errors;
  114. COMSTAT Stat;
  115. m_CSFor_TransmitCOM.Lock();
  116. BOOL bRet = ClearCommError(m_handleCOM,&Errors,&Stat);
  117. m_CSFor_TransmitCOM.Unlock();
  118. return Stat.cbInQue;
  119. }
  120. /********************************************************************************
  121. * Function Type : Public
  122. * Parameter : None
  123. * Return Value : 长度
  124. * Description : 获得串口输出缓冲区中还有多少字节数据未发送
  125. *********************************************************************************/
  126. DWORD CHwCOM::GetCommOutBufRemainBytes()
  127. {
  128. DWORD Errors;
  129. COMSTAT Stat;
  130. m_CSFor_TransmitCOM.Lock();
  131. ClearCommError(m_handleCOM,&Errors,&Stat);
  132. m_CSFor_TransmitCOM.Unlock();
  133. return Stat.cbOutQue;
  134. }
  135. /********************************************************************************
  136. * Function Type : Public
  137. * Parameter : nComNO - 串口号(如:2,表示COM2)
  138. * nBaudRate - 波特率
  139. * Return Value : None
  140. * Description : 初始化串口
  141. *********************************************************************************/
  142. BOOL CHwCOM::OpenCOM(int nComNO, int nBaudRate/*=576000*/, BOOL bQuiet/*=FALSE*/)
  143. {
  144. if ( m_handleCOM && m_handleCOM != INVALID_HANDLE_VALUE )
  145. return TRUE;
  146. ASSERT ( nComNO > 0 && nComNO < 255 );
  147. m_nComNo = nComNO;
  148. TCHAR ucFileName[20];
  149. //打开串口
  150. _snwprintf_s(ucFileName,sizeof(ucFileName), _T("\\.\COM%d"),m_nComNo);
  151. if ( m_pCSFor_OpenCOM )
  152. m_pCSFor_OpenCOM->Lock();
  153. m_handleCOM = CreateFile((LPCTSTR)ucFileName,
  154. GENERIC_READ | GENERIC_WRITE, //打开类型为可读写
  155. 0, //以独占模式打开串口
  156. NULL, //不设置安全属性
  157. OPEN_EXISTING, //设备不存在时打开失败
  158. 0, //不需设置文件属性
  159. NULL); // 不需参照模板文件
  160. if ( m_pCSFor_OpenCOM )
  161. m_pCSFor_OpenCOM->Unlock();
  162. if ( !m_handleCOM || m_handleCOM == INVALID_HANDLE_VALUE )
  163. {
  164. if ( !bQuiet )
  165. {
  166. TRACE ( L"Open(#2) [COM%d] failedn",m_nComNo );
  167. }
  168. m_handleCOM = NULL;
  169. return FALSE;
  170. }
  171. // 设置DCB
  172. DCB MyDcb;
  173. if(GetCommState(m_handleCOM,&MyDcb))
  174. {
  175. MyDcb.BaudRate = nBaudRate;
  176. MyDcb.ByteSize = 8;
  177. MyDcb.Parity = NOPARITY;
  178. MyDcb.StopBits = ONESTOPBIT;
  179. MyDcb.fBinary=1;
  180. SetCommState(m_handleCOM,&MyDcb);
  181. }
  182. SetupComm(m_handleCOM,MAX_COM_BUFSIZE,MAX_COM_BUFSIZE/4);
  183. // 进行超时设置
  184. COMMTIMEOUTS CommTimeouts =
  185. {
  186. 100, // 读字符间隔超时时间: 100 ms
  187. 2, // 读操作时每字符的时间: 2 ms (n个字符总共为2*n ms)
  188. 1000, // 基本的(额外的)读超时时间: 1000 ms
  189. 2, // 写操作时每字符的时间: 2 ms (n个字符总共为2*n ms)
  190. 500, // 基本的(额外的)写超时时间: 500 ms
  191. };
  192. if ( !SetCommTimeouts(m_handleCOM, &CommTimeouts) )
  193. {
  194. TRACE ( L"Set [COM%d] timeout parameter failedn", nComNO );
  195. CloseCOM ();
  196. return FALSE;
  197. }
  198. if ( !EscapeCommFunction ( m_handleCOM,SETDTR ) )
  199. {
  200. TRACE ( L"[COM%d] EscapeCommFunction failedn", nComNO );
  201. }
  202. BOOL bRet = GetCommProperties ( m_handleCOM, &m_CommProp );
  203. if( !bRet || !(m_CommProp.dwProvCapabilities&PCF_INTTIMEOUTS) )
  204. {
  205. TRACE ( L"[COM%d] not supported capabilitiesn", nComNO );
  206. }
  207. ClearCommBufByRead();
  208. m_bDeviceGotway = FALSE;
  209. if ( !bQuiet )
  210. {
  211. TRACE ( L"Open(#2) [COM%d] successfullyn", nComNO );
  212. }
  213. return TRUE;
  214. }
  215. void CHwCOM::CloseCOM()
  216. {
  217. if ( m_handleCOM && m_handleCOM != INVALID_HANDLE_VALUE )
  218. {
  219. CloseHandle ( m_handleCOM );
  220. m_handleCOM = NULL;
  221. }
  222. }
  223. /********************************************************************************
  224. * Function Type : Private
  225. * Parameter : None
  226. * Return Value : None
  227. * Description : 通过读操作来清空串口所有缓冲和字符
  228. *********************************************************************************/
  229. void CHwCOM::ClearCommBufByRead()
  230. {
  231. ClearComm ( TRUE ); ClearComm ( FALSE );
  232. char buf[1024] = {0};
  233. int nReadyBytes = 0;
  234. while ( ( nReadyBytes = (int)GetCommInputBuffLen() ) > 0 )
  235. {
  236. Read ( buf, nReadyBytes );
  237. }
  238. }
  239. /********************************************************************************
  240. * Function Type : Private
  241. * Parameter : iBytes - [in] 等待数据字节数
  242. * timeout - [in] 等待数据的最大时间(毫秒)
  243. * Return Value : TRUE - 等到数据
  244. * FALSE - 没等到
  245. * Description : 等到指定字节数据可读
  246. *********************************************************************************/
  247. BOOL CHwCOM::WaitForDataToRead(int iBytes,int timeout/* = WAIT_DATA_TIMEOUT*/)
  248. {
  249. DWORD start_time = GetTickCount();
  250. while ( (DWORD)( GetTickCount() - start_time ) < (DWORD)timeout)
  251. {
  252. if( GetCommInputBuffLen() < (DWORD)iBytes) //没有接收到iBytes个数据
  253. Sleep ( 100 );
  254. else
  255. {
  256. return TRUE;
  257. }
  258. }
  259. return FALSE;
  260. }
  261. BOOL CHwCOM::SetCommMask(DWORD dwEvtMask)
  262. {
  263. if ( m_handleCOM && m_handleCOM != INVALID_HANDLE_VALUE )
  264. {
  265. return ::SetCommMask ( m_handleCOM, dwEvtMask );
  266. }
  267. return FALSE;
  268. }
  269. BOOL CHwCOM::WaitCommEvent(LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
  270. {
  271. if ( m_handleCOM && m_handleCOM != INVALID_HANDLE_VALUE )
  272. {
  273. return ::WaitCommEvent ( m_handleCOM, lpEvtMask, lpOverlapped );
  274. }
  275. return FALSE;
  276. }