CE 操作串口
WinCE里面都是通过标准的系统API对串口进行操作的,但是串口不同于其它文件,它是是独占式地操作的。
下面是一个操作的串口类:
#pragma once typedef void (*LPDataArriveProc)(char *data,int length,DWORD userdata); // 定义数据处理回调函数(指针类型) class CPSerialPort { public: CPSerialPort(); virtual ~CPSerialPort(); //打开串口 BOOL OpenPort(LPCTSTR Port,); //关闭串口 BOOL ClosePort(); //激活与关闭持续接收 BOOL Activate(); BOOL Deactivate(); BOOL IsActive(); //接收数据线程函数 static DWORD WINAPI ReadPortThread(LPVOID lpParameter); DWORD ReadPort(char *data,int length); //读取一定长度的数据 DWORD WritePort(unsigned char *data,int length); //发送数据 DWORD WriteFileToPort(LPCTSTR FileName); //发送文件 private: HANDLE m_hComm; //串口设备handle HANDLE m_hReadThread; //读串口线程handle BOOL m_bReceiving; //是否持续接收 int m_nBufferSize; //缓冲大小 char *Buffer; //缓冲区 LPDataArriveProc m_lpDataArriveProc; //回调函数,用于处理数据 DWORD m_dwUserData; //串口设置以及超时参数 DCB dcb; COMMTIMEOUTS CommTimeOuts; protected: void ReceiveChar(CPSerialPort *port,COMSTAT comstat); };
#include "StdAfx.h" #include "PSerialPort.h" CPSerialPort::CPSerialPort() { m_hComm = INVALID_HANDLE_VALUE; m_hReadThread = NULL; m_bReceiving = FALSE; m_nBufferSize = ; //缓冲大小 } CPSerialPort::~CPSerialPort() { ClosePort(); } //串口接收线程,主要是中断处理,调用另外一个专门的接收函数实现 DWORD WINAPI CPSerialPort::ReadPortThread(LPVOID lpParameter) //参数指向串口类 { DWORD evtMask; //事件驱动变量WaitCommEvent()用 DWORD dwReadErrrors; //保存出错状态用 COMSTAT cmState; CPSerialPort* m_pSerial; m_pSerial =(CPSerialPort*)lpParameter; if(m_pSerial->m_hComm!=INVALID_HANDLE_VALUE) { PurgeComm(m_pSerial->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR ); //清空串口驱动的发送和接收区,此函数一般用在第一次打开串口或长时间未用串口时 SetCommMask (m_pSerial->m_hComm, EV_RXCHAR); //设置响应事件//EV_RXCHAR:输入缓冲区中已收到数据 } while((m_pSerial->m_hComm!=INVALID_HANDLE_VALUE)&&(m_pSerial->m_bReceiving)) { if(WaitCommEvent(m_pSerial->m_hComm,&evtMask,NULL)) //等接收信号 { //有数据 ClearCommError(m_pSerial->m_hComm,&dwReadErrrors,&cmState); //清错误并查询,保证下一次的waitcommEvent(); m_pSerial->ReceiveChar(m_pSerial,cmState); //读数据 } } ; } //读并保存串口数据 void CPSerialPort::ReceiveChar(CPSerialPort *port, COMSTAT comstat) { BOOL bResult = TRUE; DWORD dwError = ; DWORD dwWantRead; BOOL fReadState; DWORD dwLength; char* buf=new char[port->m_nBufferSize]; //生成缓存区 if(!buf) //分配内存失败,返回 return; for(;;) //读数 { bResult=ClearCommError(port->m_hComm,&dwError,&comstat); || !port->m_bReceiving) //无数据或按退出则退出程序 { break; //返回 } //确定读数长度 dwWantRead=comstat.cbInQue; if(dwWantRead> (DWORD)(port->m_nBufferSize)) { dwWantRead=port->m_nBufferSize; } fReadState=ReadFile(port->m_hComm,buf,dwWantRead,&dwLength,NULL); if(!fReadState) { //AfxMessageBox(_T("无法从串口读取数据!")); } else { ) { // 回送数据 if(port->m_lpDataArriveProc!=NULL) // 如果处理数据回调函数不为空 { port->m_lpDataArriveProc(buf,dwLength,port->m_dwUserData); // 处理数据 } } } } // 释放内存 if (buf) { delete[] buf; buf = NULL; } } //打开串口 BOOL CPSerialPort::OpenPort(LPCTSTR Port,int BaudRate,int DataBits,int StopBits,int Parity,LPDataArriveProc proc,DWORD userdata) { m_lpDataArriveProc=proc; //接收线程用的回调函数 m_dwUserData=userdata; //用户参数(指向调用OpenPort()的窗口 if(m_hComm==INVALID_HANDLE_VALUE) { m_hComm=CreateFile(Port,GENERIC_READ|GENERIC_WRITE,,,OPEN_EXISTING,,); //打开串口 if(m_hComm==INVALID_HANDLE_VALUE ) { AfxMessageBox(_T("无法打开端口!请检查是否已被占用。")); return FALSE; } GetCommState(m_hComm,&dcb); dcb.BaudRate=BaudRate; dcb.ByteSize=DataBits; dcb.Parity=Parity; dcb.StopBits=StopBits; dcb.fParity=FALSE; dcb.fBinary=TRUE; dcb.fDtrControl=; dcb.fRtsControl=; dcb.fOutX=dcb.fInX=dcb.fTXContinueOnXoff=; // 设置状态参数 SetCommMask(m_hComm,EV_RXCHAR); //设置"接收到一个字符"事件 SetupComm(m_hComm,,); //设置接收,发送缓存大小为16384byte if(!SetCommState(m_hComm,&dcb)) //将设置的参数写入串口 { AfxMessageBox(_T("无法按当前参数配置端口,请检查参数!")); PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收 ClosePort(); //关闭 return FALSE; } //设置超时参数 GetCommTimeouts(m_hComm,&CommTimeOuts); CommTimeOuts.ReadIntervalTimeout=; //查询方式读数时的时间间隔 CommTimeOuts.ReadTotalTimeoutMultiplier=; //读一个字节时的时间超时上限 CommTimeOuts.ReadTotalTimeoutConstant=; //总超时量 CommTimeOuts.WriteTotalTimeoutMultiplier=; CommTimeOuts.WriteTotalTimeoutConstant=; if(!SetCommTimeouts(m_hComm,&CommTimeOuts)) //写入串口 { AfxMessageBox(_T("无法设置超时参数!")); PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收区 ClosePort(); return FALSE; } PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收区 return TRUE; } return FALSE; } BOOL CPSerialPort::ClosePort() { Deactivate(); if(m_hComm!=INVALID_HANDLE_VALUE) { SetCommMask(m_hComm,); //清事件 PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); //清除串口发送接收区 CloseHandle(m_hComm); m_hComm=INVALID_HANDLE_VALUE; return TRUE; } return TRUE; } BOOL CPSerialPort::Activate() { if(m_hComm==INVALID_HANDLE_VALUE) { return FALSE; } if(!m_bReceiving) { //开始接收线程 PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); m_bReceiving=TRUE; m_hReadThread=CreateThread(NULL,,ReadPortThread,,NULL); } if(m_hReadThread!=NULL) { return TRUE; } else { m_bReceiving=FALSE; return FALSE; } //return FALSE; } BOOL CPSerialPort::Deactivate() { if(m_hComm==INVALID_HANDLE_VALUE) { return FALSE; } //停止接收线程 if(m_bReceiving) { m_bReceiving=FALSE; //关串口读数线程 SetCommMask(m_hComm,); //退出等待线程 WaitForSingleObject(m_hReadThread,); CloseHandle(m_hReadThread); m_hReadThread=NULL; return TRUE; } return FALSE; } BOOL CPSerialPort::IsActive() { return m_bReceiving; } DWORD CPSerialPort::WritePort(unsigned char *data,int length) { DWORD fg; COMSTAT cmstat; if(m_hComm==INVALID_HANDLE_VALUE) { ; } ClearCommError(m_hComm,&fg,&cmstat); // 清错并查询状态 BOOL fWriteState; DWORD dwBytesWritten=; fWriteState=WriteFile(m_hComm,data,length*sizeof(char),&dwBytesWritten,NULL); return dwBytesWritten; } DWORD CPSerialPort::ReadPort(char *data,int length) { BOOL fReadState; DWORD dwLength,dwBytesRead; int TimeOutCount; dwBytesRead=; TimeOutCount=; while(m_hComm!=INVALID_HANDLE_VALUE) { char* buf=new char[length]; fReadState=ReadFile(m_hComm,data,length,&dwLength,NULL); if(!fReadState) { break; } else { dwBytesRead+=dwLength; data+=dwLength; } if(dwBytesRead==(DWORD)length) { break; } ) { TimeOutCount=; } else { TimeOutCount++; Sleep(); } ) { break; } } return dwBytesRead; } DWORD CPSerialPort::WriteFileToPort(LPCTSTR FileName) { if(m_hComm==INVALID_HANDLE_VALUE) { ; } CFile cf; BOOL fWriteState; DWORD dwBytesWritten; DWORD dwCharToWrite; dwCharToWrite=; if(!cf.Open(FileName,CFile::modeRead)) { //AfxMessageBox(_T("无法打开Hex文件!")); ; } dwCharToWrite=(DWORD)cf.GetLength(); cf.Seek(,CFile::begin); dwBytesWritten=; ) { char* buf=new char[dwCharToWrite]; cf.Read(buf,dwCharToWrite); fWriteState=WriteFile(m_hComm,buf,dwCharToWrite*sizeof(char),&dwBytesWritten,NULL); if(!fWriteState) { //AfxMessageBox(_T("无法向端口写入数据!")); } if(buf) { delete[] buf; buf = NULL; } } cf.Close(); return dwBytesWritten; }
CE 操作串口的更多相关文章
- C#操作串口总结
Technorati 标签: C#,SerialPort,ReadTo,ReadTimeout 最近几天一直在调一个要长时间连续不断的操作串口,并且是多线程运行,不允许中断的服务.后来服 ...
- MSComm控件与Win32 API操作串口有何区别?
MSComm控件与Win32 API操作串口有何区别? [问题点数:50分,结帖人shell_shell] 收藏帖子 回复 我是一个小兵,在战场上拼命! 结帖率 83.33% 我以前用MSCo ...
- android开发(37) android使用android_serialport_api 操作串口,解决权限问题
最近有个项目,要使用android设备操作串口的 斑马GK888T打印机,使用打印机打印二维码. 硬件设备连接方式: 安卓设备 通过 串口RS232 连接 斑马打印机的串口 那么就要解决:使用安卓设备 ...
- 通过shell操作串口
1. 通过stty工具设置串口参数,例如 stty -F /dev/ttyUSB0 raw speed 9600 -echo min 0 time 10 上例设置了ttyUSB0设备的数据流格式为ra ...
- Pyserial操作串口
pySerial 介绍 封装了串口通讯模块,支持Linux.Windows.BSD(可能支持所有支持POSIX的操作系统),支持Jython(Java)和IconPython(.NET and Mon ...
- python操作串口
import serial test = serial.Serial("COM1",115200)#这里就已经打开了串口 print(test.portstr) test.writ ...
- C# 如何操作串口
1.首先要引用 System.IO.Ports using System; using System.Collections.Generic; using System.ComponentModel ...
- qt 操作串口 QSerialPort
准备工作 *.pro中加入 QT += serialport 初始化 void MainWindow::initPort() { //读取串口信息 foreach (const QSerialPort ...
- qt 操作串口
第三方类下载 https://sourceforge.net/projects/qextserialport/files/ 目录介绍 搭建工程 拷贝qextserialbase.cpp.qextser ...
随机推荐
- spark-sql性能测试
一,测试环境 1) 硬件环境完全相同: 包括:cpu/内存/网络/磁盘Io/机器数量等 2)软件环境: 相同数据 ...
- 使用NSJSONSerialization将数组或字典转为字符串
IOS中将数组或字典转为字符串可以用NSJSONSerialization,代码如下: NSData* data = [NSJSONSerialization dataWithJSONObject:a ...
- WebService 生成类的命令语句
在开发项目中,有时候需要调用webservice接口程序,根据项目规定有的项目是直接引入接口,有的是需要把接口生成代理类的形式在项目中使用,根据项目需要来取舍. 以下列出项目中常用的Webservic ...
- sql server数据库连接问题处理
下面请一字一句地看,一遍就设置成功,比你设置几十遍失败,费时会少得多. 首先,在连接数据库之前必须保证SQL Server 2012是采用SQL Server身份验证方式而不是windows身份验证方 ...
- js④
for循环代码执行顺序 1.执行小括号里面的第一个语句 2.判断小括号里面第二个语句的布尔值,如果为false,就会结束掉整个for循环,如果为true,就会执行大括号里面的语句块; 3.每次执行完大 ...
- Android --AsyncTask异步任务(一)
1.为什么要异步任务 Android单线程模式 耗时操作放在非主线程(UI线程)中执行 我们都知道Android是单线程模式,只有主线程才能对UI操作,简称UI线程.当然这样的好处是:保证UI的稳定性 ...
- 一步一步搭框架(asp.netmvc+easyui+sqlserver)-01
一步一步搭框架(asp.netmvc+easyui+sqlserver)-01 要搭建的框架是企业级开发框架,适用用企业管理信息系统的开发,如:OA.HR等 1.框架名称:sampleFrame. 2 ...
- Spring学习笔记(3)——Bean的注入方式
依赖注入 依赖注入支持属性注入.构造函数注入.工厂注入. 属性注入: 属性注入即通过setXxx()方法注入Bean的属性值或依赖对象 属性注入要求Bean提供一个默认的构造函数(无参构造函数),并为 ...
- 【转】C#多线程
C#中的多线程编程 C#是.Net平台的通用开发工具,它能够建造所有的.Net应用.在.Net中所有线程都运行在应用程序域(AppDomain)中,这也许让你想到Win32进程,实际上它们还是有很大的 ...
- centos6虚拟机复制后修改网卡
方法1: 使用vmware创建centos6.4虚拟机, 创建完成后复制该虚拟机, 打开复制的虚拟机发现网卡名字是eth1,而网卡配置文件为eth0,mac地址变了 这时修改网卡配置文件, 删除uui ...