CESeries.cpp
上传用户:zhqmouse
上传日期:2022-05-26
资源大小:47k
文件大小:7k
源码类别:

GPS编程

开发平台:

Visual C++

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