CESeries.cpp
上传用户:jhjyl123
上传日期:2016-03-29
资源大小:51k
文件大小:8k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. /*-----------------------------------------
  2. * Copyright (c) 2008 Eric Wong
  3. * 本版紧供读者参考,不得用于任何商业行为
  4. *
  5. * 文件名称: CESeries.cpp
  6. * 文件标识: 
  7. * 摘要:用于封装WINCE 串口通讯
  8. *
  9. * 当前版本: 1.0
  10. * 作者: 汪兵 Eric Wong
  11. * 完成日期: 2008年1月17日
  12. *
  13. * 取代版本:
  14. * 原作者: 
  15. * 完成日期: 
  16. ----------------------------------------*/
  17. #include "StdAfx.h"
  18. #include "CESeries.h"
  19. //构造函数
  20. CCESeries::CCESeries()
  21. {
  22. //初始化内部变量
  23. m_hComm = INVALID_HANDLE_VALUE;
  24. m_OnSeriesRead = NULL;
  25. m_bOpened = 0;
  26. }
  27. //析构函数
  28. CCESeries::~CCESeries()
  29. {
  30. if (m_bOpened)
  31. {
  32. //关闭串口
  33. ClosePort();
  34. }
  35. }
  36. //串口读线程函数
  37. DWORD CCESeries::ReadThreadFunc(LPVOID lparam)
  38. {
  39. CCESeries *ceSeries = (CCESeries*)lparam;
  40. DWORD evtMask;
  41. BYTE * readBuf = NULL;//读取的字节
  42. DWORD actualReadLen=0;//实际读取的字节数
  43. DWORD willReadLen;
  44. DWORD dwReadErrors;
  45. COMSTAT cmState;
  46. // 清空缓冲,并检查串口是否打开。
  47. ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE); 
  48. //清空串口
  49. PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR );
  50. SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
  51. while (TRUE)
  52. {   
  53. if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0))
  54. {
  55. SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
  56. //表示串口收到字符
  57. if (evtMask & EV_RXCHAR) 
  58. {
  59. ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
  60. willReadLen = cmState.cbInQue ;
  61. if (willReadLen <= 0)
  62. {
  63. continue;
  64. }
  65. //分配内存
  66. readBuf = new BYTE[willReadLen];
  67. ZeroMemory(readBuf,willReadLen);
  68. //读取串口数据
  69. ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);
  70. //如果读取的数据大于0,
  71. if (actualReadLen>0)
  72. {
  73. //触发读取回调函数
  74. if (ceSeries->m_OnSeriesRead)
  75. {
  76. ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen);
  77. }
  78. }
  79. //释放内存
  80. delete[] readBuf;
  81. readBuf = NULL;
  82. }
  83. }
  84. //如果收到读线程退出信号,则退出线程
  85. if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
  86. {
  87. break;
  88. }
  89. }
  90. return 0;
  91. }
  92. //关闭读线程
  93. void CCESeries::CloseReadThread()
  94. {
  95. SetEvent(m_hReadCloseEvent);
  96. //设置所有事件无效无效
  97. SetCommMask(m_hComm, 0);
  98. //清空所有将要读的数据
  99.     PurgeComm( m_hComm,  PURGE_RXCLEAR );
  100.     //等待4秒,如果读线程没有退出,则强制退出
  101.     if (WaitForSingleObject(m_hReadThread,4000) == WAIT_TIMEOUT)
  102. {
  103. TerminateThread(m_hReadThread,0);
  104. }
  105. m_hReadThread = NULL;
  106. }
  107. /*
  108. *函数介绍:打开串口
  109. *入口参数:pPortOwner :使用此串口类的窗体句柄
  110.    portNo :串口号
  111.    baud :波特率
  112.    parity :奇偶校验
  113.    databits :数据位
  114.    stopbits :停止位
  115. *出口参数:(无)
  116. *返回值:TRUE:成功打开串口;FALSE:打开串口失败
  117. */
  118. BOOL CCESeries::OpenPort(void * pOwner,
  119.  UINT portNo , /*串口号*/
  120.  UINT baud , /*波特率*/
  121.  UINT parity , /*奇偶校验*/
  122.  UINT databits , /*数据位*/
  123.  UINT stopbits    /*停止位*/
  124.  )
  125. {
  126. DCB commParam;
  127. TCHAR szPort[15];
  128. ASSERT(pOwner!=NULL);
  129. m_pOwner = pOwner;
  130. // 已经打开的话,直接返回
  131. if (m_hComm != INVALID_HANDLE_VALUE)
  132. {
  133. return TRUE;
  134. }
  135. //设置串口名
  136. wsprintf(szPort, L"COM%d:", portNo);
  137. //打开串口
  138. m_hComm = CreateFile(
  139. szPort,
  140. GENERIC_READ | GENERIC_WRITE, //允许读和写
  141. 0, //独占方式(共享模式)
  142. NULL,
  143. OPEN_EXISTING, //打开而不是创建(创建方式)
  144. 0,
  145. NULL 
  146. );
  147. if (m_hComm == INVALID_HANDLE_VALUE)
  148. {
  149. // 无效句柄,返回。
  150. TRACE(_T("CreateFile 返回无效句柄n"));
  151. return FALSE;
  152. }
  153. // 得到打开串口的当前属性参数,修改后再重新设置串口。
  154. if (!GetCommState(m_hComm,&commParam))
  155. {
  156. //关闭串口
  157. CloseHandle (m_hComm);
  158. m_hComm = INVALID_HANDLE_VALUE;
  159. return FALSE;
  160. }
  161. //设置串口参数
  162. commParam.BaudRate = baud; // 设置波特率 
  163. commParam.fBinary = TRUE; // 设置二进制模式,此处必须设置TRUE
  164. commParam.fParity = TRUE; // 支持奇偶校验 
  165. commParam.ByteSize = databits; // 数据位,范围:4-8 
  166. commParam.Parity = parity; // 校验模式
  167. commParam.StopBits = stopbits; // 停止位 
  168. commParam.fOutxCtsFlow = FALSE; // No CTS output flow control 
  169. commParam.fOutxDsrFlow = FALSE; // No DSR output flow control 
  170. commParam.fDtrControl = DTR_CONTROL_ENABLE; 
  171. // DTR flow control type 
  172. commParam.fDsrSensitivity = FALSE; // DSR sensitivity 
  173. commParam.fTXContinueOnXoff = TRUE; // XOFF continues Tx 
  174. commParam.fOutX = FALSE; // No XON/XOFF out flow control 
  175. commParam.fInX = FALSE; // No XON/XOFF in flow control 
  176. commParam.fErrorChar = FALSE; // Disable error replacement 
  177. commParam.fNull = FALSE; // Disable null stripping 
  178. commParam.fRtsControl = RTS_CONTROL_ENABLE; 
  179. // RTS flow control 
  180. commParam.fAbortOnError = FALSE; // 当串口发生错误,并不终止串口读写
  181. //设置串口参数
  182. if (!SetCommState(m_hComm, &commParam))
  183. {
  184. TRACE(_T("SetCommState error"));
  185. //关闭串口
  186. CloseHandle (m_hComm);
  187. m_hComm = INVALID_HANDLE_VALUE;
  188. return FALSE;
  189. }
  190.     //设置串口读写时间
  191. COMMTIMEOUTS CommTimeOuts;
  192. GetCommTimeouts (m_hComm, &CommTimeOuts);
  193. CommTimeOuts.ReadIntervalTimeout = MAXDWORD;  
  194. CommTimeOuts.ReadTotalTimeoutMultiplier = 0;  
  195. CommTimeOuts.ReadTotalTimeoutConstant = 0;    
  196. CommTimeOuts.WriteTotalTimeoutMultiplier = 10;  
  197. CommTimeOuts.WriteTotalTimeoutConstant = 1000;  
  198. if(!SetCommTimeouts( m_hComm, &CommTimeOuts ))
  199. {
  200. TRACE( _T("SetCommTimeouts 返回错误") );
  201. //关闭串口
  202. CloseHandle (m_hComm);
  203. m_hComm = INVALID_HANDLE_VALUE;
  204. return FALSE;
  205. }
  206. //指定端口监测的事件集
  207. SetCommMask (m_hComm, EV_RXCHAR);
  208. //分配串口设备缓冲区
  209. SetupComm(m_hComm,512,512);
  210. //初始化缓冲区中的信息
  211. PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
  212. CString strEvent;
  213. strEvent.Format(L"Com_ReadCloseEvent%d",portNo);
  214. m_hReadCloseEvent = CreateEvent(NULL,TRUE,FALSE,strEvent);
  215. //创建串口读数据监听线程
  216. m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);
  217. TRACE(_T("串口打开成功"));
  218. m_bOpened = TRUE;
  219. return TRUE;
  220. }
  221. /*
  222. *函数介绍:关闭串口
  223. *入口参数:(无)
  224. *出口参数:(无)
  225. *返回值:  (无)
  226. */
  227. void CCESeries::ClosePort()
  228. {
  229. //表示串口还没有打开
  230. if (m_hComm == INVALID_HANDLE_VALUE)
  231. {
  232. return ;
  233. }
  234. //关闭读线程
  235. CloseReadThread();
  236. //关闭串口
  237. CloseHandle (m_hComm);
  238. //关闭事件
  239. CloseHandle(m_hReadCloseEvent);
  240. m_hComm = INVALID_HANDLE_VALUE;
  241. m_bOpened = FALSE;
  242. }
  243. /*
  244. *函数介绍:往串口写入数据
  245. *入口参数:buf :待写入数据缓冲区
  246.        bufLen : 待写入缓冲区长度
  247. *出口参数:(无)
  248. *返回值:TRUE:设置成功;FALSE:设置失败
  249. */
  250. BOOL CCESeries::WriteSyncPort(const BYTE*buf , DWORD bufLen)
  251. {
  252. DWORD dwNumBytesWritten;
  253. DWORD dwHaveNumWritten =0 ; //已经写入多少
  254. int iInc = 0; //如果3次写入不成功,返回FALSE
  255. ASSERT(m_hComm != INVALID_HANDLE_VALUE);
  256. do
  257. {
  258. if (WriteFile (m_hComm, //串口句柄 
  259. buf+dwHaveNumWritten, //被写数据缓冲区 
  260. bufLen - dwHaveNumWritten,          //被写数据缓冲区大小
  261. &dwNumBytesWritten, //函数执行成功后,返回实际向串口写的个数
  262. NULL)) //此处必须设置NULL
  263. {
  264. dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten;
  265. //写入完成
  266. if (dwHaveNumWritten == bufLen)
  267. {
  268. break;
  269. }
  270. iInc++;
  271. if (iInc >= 3)
  272. {
  273. return FALSE;
  274. }
  275. Sleep(10);
  276. }
  277. else
  278. {
  279. return FALSE;
  280. }
  281. }while (TRUE);
  282. return TRUE;
  283. }
  284. /*
  285. *函数介绍:设置串口读取、写入超时
  286. *入口参数:CommTimeOuts : 指向COMMTIMEOUTS结构
  287. *出口参数:(无)
  288. *返回值:TRUE:设置成功;FALSE:设置失败
  289. */
  290. BOOL CCESeries::SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts)
  291. {
  292. ASSERT(m_hComm != INVALID_HANDLE_VALUE);
  293. return SetCommTimeouts(m_hComm,&CommTimeOuts);
  294. }
  295. //得到串口是否打开
  296. BOOL CCESeries::GetComOpened()
  297. {
  298. return m_bOpened;
  299. }