WinCE里面都是通过标准的系统API对串口进行操作的,但是串口不同于其它文件,它是是独占式地操作的。

下面是一个操作的串口类:

  1. #pragma once
  2. typedef void (*LPDataArriveProc)(char *data,int length,DWORD userdata); // 定义数据处理回调函数(指针类型)
  3.  
  4. class CPSerialPort
  5. {
  6. public:
  7. CPSerialPort();
  8. virtual ~CPSerialPort();
  9.  
  10. //打开串口
  11. BOOL OpenPort(LPCTSTR Port,);
  12. //关闭串口
  13. BOOL ClosePort();
  14.  
  15. //激活与关闭持续接收
  16. BOOL Activate();
  17. BOOL Deactivate();
  18. BOOL IsActive();
  19.  
  20. //接收数据线程函数
  21. static DWORD WINAPI ReadPortThread(LPVOID lpParameter);
  22.  
  23. DWORD ReadPort(char *data,int length);        //读取一定长度的数据
  24. DWORD WritePort(unsigned char *data,int length);  //发送数据
  25. DWORD WriteFileToPort(LPCTSTR FileName);         //发送文件
  26.  
  27. private:
  28. HANDLE m_hComm; //串口设备handle
  29. HANDLE m_hReadThread; //读串口线程handle
  30. BOOL m_bReceiving; //是否持续接收
  31. int m_nBufferSize; //缓冲大小
  32. char *Buffer; //缓冲区
  33.  
  34. LPDataArriveProc m_lpDataArriveProc; //回调函数,用于处理数据
  35. DWORD m_dwUserData;
  36.  
  37. //串口设置以及超时参数
  38. DCB dcb;
  39. COMMTIMEOUTS CommTimeOuts;
  40.  
  41. protected:
  42. void ReceiveChar(CPSerialPort *port,COMSTAT comstat);
  43.  
  44. };
  1. #include "StdAfx.h"
  2. #include "PSerialPort.h"
  3.  
  4. CPSerialPort::CPSerialPort()
  5. {
  6. m_hComm = INVALID_HANDLE_VALUE;
  7. m_hReadThread = NULL;
  8. m_bReceiving = FALSE;
  9. m_nBufferSize = ; //缓冲大小
  10. }
  11.  
  12. CPSerialPort::~CPSerialPort()
  13. {
  14. ClosePort();
  15. }
  16. //串口接收线程,主要是中断处理,调用另外一个专门的接收函数实现
  17. DWORD WINAPI CPSerialPort::ReadPortThread(LPVOID lpParameter) //参数指向串口类
  18. {
  19. DWORD   evtMask; //事件驱动变量WaitCommEvent()用
  20. DWORD   dwReadErrrors; //保存出错状态用
  21. COMSTAT   cmState;
  22. CPSerialPort*  m_pSerial;
  23. m_pSerial   =(CPSerialPort*)lpParameter;
  24.  
  25. if(m_pSerial->m_hComm!=INVALID_HANDLE_VALUE)
  26. {
  27. PurgeComm(m_pSerial->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR ); //清空串口驱动的发送和接收区,此函数一般用在第一次打开串口或长时间未用串口时
  28. SetCommMask (m_pSerial->m_hComm, EV_RXCHAR); //设置响应事件//EV_RXCHAR:输入缓冲区中已收到数据
  29. }
  30.  
  31. while((m_pSerial->m_hComm!=INVALID_HANDLE_VALUE)&&(m_pSerial->m_bReceiving))
  32. { if(WaitCommEvent(m_pSerial->m_hComm,&evtMask,NULL)) //等接收信号
  33. { //有数据
  34. ClearCommError(m_pSerial->m_hComm,&dwReadErrrors,&cmState); //清错误并查询,保证下一次的waitcommEvent();
  35. m_pSerial->ReceiveChar(m_pSerial,cmState); //读数据
  36. }
  37. }
  38.  
  39. ;
  40. }
  41.  
  42. //读并保存串口数据
  43. void CPSerialPort::ReceiveChar(CPSerialPort *port, COMSTAT comstat)
  44. {
  45. BOOL bResult = TRUE;
  46. DWORD dwError = ;
  47. DWORD dwWantRead;
  48. BOOL fReadState;
  49. DWORD dwLength;
  50.  
  51. char* buf=new char[port->m_nBufferSize]; //生成缓存区
  52. if(!buf)                   //分配内存失败,返回
  53.   return;
  54.  
  55. for(;;)  //读数
  56. {
  57. bResult=ClearCommError(port->m_hComm,&dwError,&comstat);
  58. || !port->m_bReceiving) //无数据或按退出则退出程序
  59. {
  60. break; //返回
  61. }
  62. //确定读数长度
  63. dwWantRead=comstat.cbInQue;
  64.  
  65. if(dwWantRead> (DWORD)(port->m_nBufferSize))
  66. {
  67. dwWantRead=port->m_nBufferSize;
  68. }
  69.  
  70. fReadState=ReadFile(port->m_hComm,buf,dwWantRead,&dwLength,NULL);
  71.  
  72. if(!fReadState)
  73. {
  74. //AfxMessageBox(_T("无法从串口读取数据!"));
  75. }
  76. else
  77. {
  78. )
  79. {
  80. // 回送数据
  81. if(port->m_lpDataArriveProc!=NULL) // 如果处理数据回调函数不为空
  82. {
  83. port->m_lpDataArriveProc(buf,dwLength,port->m_dwUserData); // 处理数据
  84. }
  85. }
  86. }
  87. }
  88.  
  89. // 释放内存
  90. if (buf)
  91. {
  92. delete[] buf;
  93. buf = NULL;
  94. }
  95. }
  96.  
  97. //打开串口
  98. BOOL CPSerialPort::OpenPort(LPCTSTR Port,int BaudRate,int DataBits,int StopBits,int Parity,LPDataArriveProc proc,DWORD userdata)
  99. {
  100. m_lpDataArriveProc=proc;   //接收线程用的回调函数
  101. m_dwUserData=userdata; //用户参数(指向调用OpenPort()的窗口
  102.  
  103. if(m_hComm==INVALID_HANDLE_VALUE)
  104. {
  105. m_hComm=CreateFile(Port,GENERIC_READ|GENERIC_WRITE,,,OPEN_EXISTING,,); //打开串口
  106. if(m_hComm==INVALID_HANDLE_VALUE )
  107. {
  108. AfxMessageBox(_T("无法打开端口!请检查是否已被占用。"));
  109. return FALSE;
  110. }
  111. GetCommState(m_hComm,&dcb);
  112. dcb.BaudRate=BaudRate;
  113. dcb.ByteSize=DataBits;
  114. dcb.Parity=Parity;
  115. dcb.StopBits=StopBits;
  116. dcb.fParity=FALSE;
  117. dcb.fBinary=TRUE;
  118. dcb.fDtrControl=;
  119. dcb.fRtsControl=;
  120. dcb.fOutX=dcb.fInX=dcb.fTXContinueOnXoff=;
  121.  
  122. // 设置状态参数
  123. SetCommMask(m_hComm,EV_RXCHAR); //设置"接收到一个字符"事件
  124. SetupComm(m_hComm,,); //设置接收,发送缓存大小为16384byte
  125. if(!SetCommState(m_hComm,&dcb)) //将设置的参数写入串口
  126. {
  127. AfxMessageBox(_T("无法按当前参数配置端口,请检查参数!"));
  128. PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收
  129. ClosePort();   //关闭
  130. return FALSE;
  131. }
  132.  
  133. //设置超时参数
  134. GetCommTimeouts(m_hComm,&CommTimeOuts);
  135. CommTimeOuts.ReadIntervalTimeout=; //查询方式读数时的时间间隔
  136. CommTimeOuts.ReadTotalTimeoutMultiplier=; //读一个字节时的时间超时上限
  137. CommTimeOuts.ReadTotalTimeoutConstant=; //总超时量
  138. CommTimeOuts.WriteTotalTimeoutMultiplier=;
  139. CommTimeOuts.WriteTotalTimeoutConstant=;
  140.  
  141. if(!SetCommTimeouts(m_hComm,&CommTimeOuts)) //写入串口
  142. { AfxMessageBox(_T("无法设置超时参数!"));
  143. PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收区
  144. ClosePort();
  145. return FALSE;
  146. }
  147.  
  148. PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收区
  149. return TRUE;
  150. }
  151.  
  152. return FALSE;
  153. }
  154.  
  155. BOOL CPSerialPort::ClosePort()
  156. {
  157. Deactivate();
  158. if(m_hComm!=INVALID_HANDLE_VALUE)
  159. { SetCommMask(m_hComm,); //清事件
  160. PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收区
  161. CloseHandle(m_hComm);
  162. m_hComm=INVALID_HANDLE_VALUE;
  163. return TRUE;
  164. }
  165.  
  166. return TRUE;
  167. }
  168.  
  169. BOOL CPSerialPort::Activate()
  170. {
  171. if(m_hComm==INVALID_HANDLE_VALUE)
  172. {  return FALSE;
  173. }
  174.  
  175. if(!m_bReceiving)
  176. { //开始接收线程
  177. PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
  178. m_bReceiving=TRUE;
  179. m_hReadThread=CreateThread(NULL,,ReadPortThread,,NULL);
  180. }
  181.  
  182. if(m_hReadThread!=NULL)
  183. {
  184. return TRUE;
  185. }
  186. else
  187. {
  188. m_bReceiving=FALSE;
  189. return FALSE;
  190. }
  191. //return FALSE;
  192. }
  193.  
  194. BOOL CPSerialPort::Deactivate()
  195. {
  196. if(m_hComm==INVALID_HANDLE_VALUE)
  197. { return FALSE;
  198. }
  199.  
  200. //停止接收线程
  201. if(m_bReceiving)
  202. {
  203. m_bReceiving=FALSE; //关串口读数线程
  204. SetCommMask(m_hComm,); //退出等待线程
  205.  
  206. WaitForSingleObject(m_hReadThread,);
  207. CloseHandle(m_hReadThread);
  208. m_hReadThread=NULL;
  209. return TRUE;
  210. }
  211.  
  212. return FALSE;
  213. }
  214.  
  215. BOOL CPSerialPort::IsActive()
  216. {
  217. return m_bReceiving;
  218. }
  219.  
  220. DWORD CPSerialPort::WritePort(unsigned char *data,int length)
  221. {
  222. DWORD fg;
  223. COMSTAT cmstat;
  224. if(m_hComm==INVALID_HANDLE_VALUE)
  225. {
  226. ;
  227. }
  228. ClearCommError(m_hComm,&fg,&cmstat); // 清错并查询状态
  229. BOOL fWriteState;
  230. DWORD dwBytesWritten=;
  231.  
  232. fWriteState=WriteFile(m_hComm,data,length*sizeof(char),&dwBytesWritten,NULL);
  233.  
  234. return dwBytesWritten;
  235. }
  236.  
  237. DWORD CPSerialPort::ReadPort(char *data,int length)
  238. {
  239. BOOL fReadState;
  240. DWORD dwLength,dwBytesRead;
  241. int TimeOutCount;
  242.  
  243. dwBytesRead=;
  244. TimeOutCount=;
  245.  
  246. while(m_hComm!=INVALID_HANDLE_VALUE)
  247. {
  248. char* buf=new char[length];
  249. fReadState=ReadFile(m_hComm,data,length,&dwLength,NULL);
  250. if(!fReadState)
  251. {
  252. break;
  253. }
  254. else
  255. {
  256. dwBytesRead+=dwLength;
  257. data+=dwLength;
  258. }
  259. if(dwBytesRead==(DWORD)length)
  260. {
  261. break;
  262. }
  263. )
  264. {
  265. TimeOutCount=;
  266. }
  267. else
  268. {
  269. TimeOutCount++;
  270. Sleep();
  271. }
  272. )
  273. {
  274. break;
  275. }
  276. }
  277. return dwBytesRead;
  278. }
  279.  
  280. DWORD CPSerialPort::WriteFileToPort(LPCTSTR FileName)
  281. {
  282. if(m_hComm==INVALID_HANDLE_VALUE)
  283. { ;
  284. }
  285.  
  286. CFile cf;
  287.  
  288. BOOL fWriteState;
  289. DWORD dwBytesWritten;
  290. DWORD dwCharToWrite;
  291.  
  292. dwCharToWrite=;
  293.  
  294. if(!cf.Open(FileName,CFile::modeRead))
  295. {
  296. //AfxMessageBox(_T("无法打开Hex文件!"));
  297. ;
  298. }
  299. dwCharToWrite=(DWORD)cf.GetLength();
  300. cf.Seek(,CFile::begin);
  301. dwBytesWritten=;
  302.  
  303. )
  304. {
  305. char* buf=new char[dwCharToWrite];
  306. cf.Read(buf,dwCharToWrite);
  307.  
  308. fWriteState=WriteFile(m_hComm,buf,dwCharToWrite*sizeof(char),&dwBytesWritten,NULL);
  309. if(!fWriteState)
  310. {
  311. //AfxMessageBox(_T("无法向端口写入数据!"));
  312. }
  313. if(buf)
  314. {
  315. delete[] buf;
  316. buf = NULL;
  317. }
  318. }
  319. cf.Close();
  320. return dwBytesWritten;
  321. }

CE 操作串口的更多相关文章

  1. C#操作串口总结

    Technorati 标签: C#,SerialPort,ReadTo,ReadTimeout        最近几天一直在调一个要长时间连续不断的操作串口,并且是多线程运行,不允许中断的服务.后来服 ...

  2. MSComm控件与Win32 API操作串口有何区别?

    MSComm控件与Win32 API操作串口有何区别? [问题点数:50分,结帖人shell_shell]   收藏帖子 回复 我是一个小兵,在战场上拼命!   结帖率 83.33% 我以前用MSCo ...

  3. android开发(37) android使用android_serialport_api 操作串口,解决权限问题

    最近有个项目,要使用android设备操作串口的 斑马GK888T打印机,使用打印机打印二维码. 硬件设备连接方式: 安卓设备 通过 串口RS232 连接 斑马打印机的串口 那么就要解决:使用安卓设备 ...

  4. 通过shell操作串口

    1. 通过stty工具设置串口参数,例如 stty -F /dev/ttyUSB0 raw speed 9600 -echo min 0 time 10 上例设置了ttyUSB0设备的数据流格式为ra ...

  5. Pyserial操作串口

    pySerial 介绍 封装了串口通讯模块,支持Linux.Windows.BSD(可能支持所有支持POSIX的操作系统),支持Jython(Java)和IconPython(.NET and Mon ...

  6. python操作串口

    import serial test = serial.Serial("COM1",115200)#这里就已经打开了串口 print(test.portstr) test.writ ...

  7. C# 如何操作串口

    1.首先要引用  System.IO.Ports using System; using System.Collections.Generic; using System.ComponentModel ...

  8. qt 操作串口 QSerialPort

    准备工作 *.pro中加入 QT += serialport 初始化 void MainWindow::initPort() { //读取串口信息 foreach (const QSerialPort ...

  9. qt 操作串口

    第三方类下载 https://sourceforge.net/projects/qextserialport/files/ 目录介绍 搭建工程 拷贝qextserialbase.cpp.qextser ...

随机推荐

  1. WIN7-64位安装PLSQL-Developer步骤

    可参与网址http://tech.ddvip.com/2012-07/1343104017178927.html 以下操作是从网上搜索在64位WIN7测试通过,64位无法使用PL/SQL Develo ...

  2. Servlet入门

    1.在tomcat中新建一个day01web应用,然后在web应用中新建一个web-inf/classes目录:2.在classes目录中新建一个FirstServlet.java文件:package ...

  3. Python的平凡之路(20)

    (提问复习为主) 一.Django请求的生命周期      武彦涛:           路由系统 -> 视图函数(获取模板+数据=>渲染) -> 字符串返回给用户     二.路由 ...

  4. 【zz】matlab 求差集

    matlab判断2个数组中不同元素--setdiff c = setdiff(A, B) 返回在A中有,而B中没有的值,结果向量将以升序排序返回.在集合论中,c = A - B.A和B也可以是字符串细 ...

  5. javascript实现当前页面截屏

    javascript实现当前页面截屏 一.前言 有客户要求能对用户当前页面进行指定区域截屏,类似qq截屏的实现效果.比如用户在处理工作的时候,将当前页面录入后的一些信息进行截图下载保存.但又不能安装任 ...

  6. [转]python问题:IndentationError:expected an indented block错误解决

    分类: python学习笔记2012-07-07 17:59 28433人阅读 评论(4) 收藏 举报 python语言 原文地址:http://hi.baidu.com/delinx/item/17 ...

  7. Android WebView 保存cache至External Storage

    源博客: http://www.devahead.com/blog/2012/01/saving-the-android-webview-cache-on-the-sd-card/ 其中心思想是,通过 ...

  8. PHP中FOREACH()用法

    PHP 4 引入了 foreach 结构,和 Perl 以及其他语言很像.这只是一种遍历数组简便方法.foreach 仅能用于数组,当试图将其用于其它数据类型或者一个未初始化的变量时会产生错误. 1. ...

  9. js 自运行函数作用

    var obj = new Object(); function test2() { for (var i=1;i<5;i++) { obj['f'+i] = function() { retu ...

  10. 对字符串进行简单的字符数字统计 探索java中的List功能

    题目: 统计一个字符串中数字和字符串的个数,并分别进行排列,要求 1.数字,字符串可以从键盘获取. 2.储存在list 3.统计数字个数,字符串个数 4.把数字和字符串按从小到大的顺序输出 5.不能使 ...