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 操作串口的更多相关文章

  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. 利用HttpURLConnection发送请求

    HttpURLConnection: 每个 HttpURLConnection实例都可用于生成单个请求,但是其他实例可以透明地共享连接到 HTTP 服务器的基础网络.请求后在 HttpURLConne ...

  2. js⑧

    window对象表示浏览器中打开的窗口, 它是JavaScript浏览器对象模型中的顶层对象.其中还包括了 - Document: 使我们可以从脚本中对 HTML 页面中的所有元素进行访问. - Hi ...

  3. Unity3D 一个较常见的错误信息“rect[2] == rt->GetGLWidth() && rect[3] == rt->GetGLHeight()”

    rect[2] == rt->GetGLWidth() && rect[3] == rt->GetGLHeight() 这个错误信息的具体含义我还不太清楚.它出现以后会不停 ...

  4. IELTS - Word List 28

    1, The lawsuit is very much o the lawyer's mind. 2, The canteen was absolutely packed. 3, Doctors di ...

  5. maven的使用体验

    由于之前是从C++代码阵营中转到java阵营的(这里可能还会转到scala阵营中).在写工程代码的时候,如果是只是简单的创建java project的话,当然也是可以的.但是,随着项目慢慢扩大,组件越 ...

  6. DOM扩展之 HTML5

    11.3.1 与类相关的扩充 2. classList属性 在操作类名时,需要通过className属性添加,删除和替换类名.因为className是一个字符串,所以即使只修改一部分内容也要设置整个字 ...

  7. APK签名是如何生成的

    零.前言本文以支付宝手机客户端为例,进行剖析到支付宝官网下载当前最新版本:8.0.1 (2014-01-28)文件名为 alipay_wap_main.apkMD5 摘要为 69820edb3cd13 ...

  8. 关于css的新思考

    因为被派去协助别的组,有机会写了一下react,发现ICE做的那一个套件用来搭建后台系统真的太给力了(插一句必入table组件其实是可以把删除添加座位基础方法加进去的).因为看了demo的代码以及对于 ...

  9. Java 和 C+

    文不对题,啦啦啦~~~ 第一次感到在windows平台java应用发布的无力,平时自己自写自用都是在自己电脑上,没什么感觉.如今要发布个给人用,打包应用.附加jre,这过程还得多加几行字说明,另人特么 ...

  10. 2014 项目中用到batik

    现在手头上的项目用到batik编程,用的maven管理jar包,要在pom.xml中dependencies标签下添加一下配置(batik编程使用的顶层jar包) <dependency> ...