当前位置: 行情首页 >> 技术文章 >> 技术文章 >> 求教关于visual C++ V

  • 求教关于visual C++ V6.0 中串行口的编程方法 VC/MFC / 基础类
  • 2007-10-23 10:35:27 杭州电脑数码城 转载来源:csdn.net
  • 社区 - VC/MFC / 基础类

    求教关于visual C++ V6.0 中串行口的编程方法

    () 2000-02-03 15:15:00在 VC/MFC / 基础类 提问


    问题点数:50、回复次数:5

    1楼 vividy () 回复于 2000-02-03 19:30:00 得分 0


    use createfile("\\\\.\\COM1",.....);
    then use readfile and writefile.
    at last closehandle

    2楼 ybchen (我)(是)(菜)(鸟)(我)(怕)(谁) 回复于 2000-02-03 21:12:00 得分 50


    最近我用Borland C++编了一个串口通讯的程序,
    Visual C++ 与此类似,我把我编的串口类贴到此处,
    如果有错误或不完善的地方还请大家一起研究 :-)

    其中 TCommQueue 是我编的一个队列,我不详细说了 --
    不要告诉我不知道什么是队列 :-)

    串口通讯用的是32位API函数,(16位的Win3.x API函数早已
    不复存在): CreateFile、ReadFile、WriteFile、
    CloseHandle等。

    因为这些函数如果用查询方法,他们的超时工作(用
    SetCommTimeouts 设置)会引起系统访问消息的延时,十分
    影响程序运行的效率,因此采用了重叠操作,在另一个线程
    里面监视串口通讯情况,如果有数据收到或发送缓存空就向
    主线程发一个串口通讯消息,并暂停监视,主线程相应完
    消息(读/写)后监视线程继续工作。

    这个类使用非常简单,比如要打开两个串口同时通讯,可以
    如下定义:

    TComm32 *CommA, *CommB;

    初始化:

    CommA = new TComm32(this); //必须指明在哪个窗口消息里处
    CommB = new TComm32(this); //理串口数据,这里用的是this

    CommA -> SetPort(1); //用COM1,在使用中可以随时更改
    CommB -> SetPort(2); //用COM2,在使用中可以随时更改

    CommA -> SetParams(CBR_4800, NOPARITY, 8, ONESTOPBIT);
    CommB -> SetParams(CBR_9600, NOPARITY, 8, ONESTOPBIT);

    打开串口:

    if((Error = CommA -> Open()) != 0)
    {
    //错误处理
    }

    if((Error = CommB -> Open()) != 0)
    {
    //错误处理
    }

    响应串口消息:
    可以在此处读串口,也可以在定时器或其他任何函数里面
    本消息的参数 wParam 表示串口进行了读还是写操作
    本消息的参数 lParam 是响应操作的串口对象的地址

    DEFINE_RESPONSE_TABLE1(TMyWindow, TParentWindow)
    EV_MESSAGE(WM_COMMNOTIFY, EvCommNotify),
    ... //其他消息
    END_RESPONSE_TABLE;

    LRESULT TMyWindow::EvCommNotify(WPARAM wParam, LPARAM lParam)
    {
    ((TComm32 *)lParam)->CommNotify(wParam); //必须调用这个函数

    //可以在此处读串口,也可以在定时器或其他函数里面
    //如果在此处读串口数据,可以按如下方法:
    while((BytesRead = CommA->Read(Buffer, BufferSize)) != 0)
    {
    //处理从CommA里面读出的数据
    }

    while((BytesRead = CommB->Read(Buffer, BufferSize)) != 0)
    {
    //处理从CommB里面读出的数据
    }

    return true; //必须返回非零值
    }

    写串口:可以在任何位置调用:
    BytesWrite = CommA->Write(Buffer, BufferSize);
    BytesWrite = CommB->Write(Buffer, BufferSize);

    关闭串口:
    CommA->Close();
    CommB->Close();

    在程序结束前需要删除CommA、CommB对象,但关闭串口不是必须的,
    因为在他们的析构函数里面已经关闭了串口
    delete CommA;
    delete CommB;

    //=========================================================
    //我不多说了,看看 TComm32 类的实现就明白了
    //TComm32, Copyright (C) ybchen, EMail: ybchen@email.com.cn
    //=========================================================
    class _OWLCLASS TComm32
    {
    public:
    TComm32(TWindow *Win);
    virtual ~TComm32();

    virtual int SetPort(int COMn);
    virtual int SetParams(DWORD Baud, BYTE Parity, BYTE ByteSize, BYTE StopBits);
    virtual int SetBufSize(long InBufSize, long OutBufSize, long HwInSize, long HwOutSize);

    virtual int Open(void);
    virtual int Close(void);
    virtual int Opened(void) { return Handle!=INVALID_HANDLE_VALUE; }

    virtual long Read(char far *s, long n=1);
    virtual long Write(char far *s, long n=1);

    virtual void CommNotify(int NotifyType); //EV_RXCHAR or EV_TXEMPTY

    TCommQueue *InBuf;
    TCommQueue *OutBuf;

    TWindow *ComWin;
    HANDLE Handle; //INVALID_HANDLE_VALUE

    HANDLE hRecvEvent; //NULL
    HANDLE hSendEvent; //NULL

    OVERLAPPED read_os;
    OVERLAPPED write_os;

    volatile long CommThreadId; //-1
    volatile bool RunComThread; // 0
    volatile bool CommThreadRunning; // 0

    int _PortNo;
    long _InBufSize, _OutBufSize, _HwInSize, _HwOutSize;
    DWORD _Baud;
    BYTE _Parity, _ByteSize, _StopBits;
    };

    void _Comm32_CommWatchThread(void *Param) //监视线程
    {
    OVERLAPPED os;
    DWORD dwTransfer, dwEvtMask;
    TComm32 *Comm = (TComm32 *) Param;
    Comm->CommThreadRunning = 1;

    os.hEvent = CreateEvent(NULL, true, false, NULL);
    if(os.hEvent)
    {
    if(SetCommMask(Comm->Handle, EV_RXCHAR and EV_TXEMPTY))
    {
    while(Comm->RunComThread)
    {
    dwEvtMask = 0;
    if(!WaitCommEvent(Comm->Handle, &dwEvtMask, &os))
    {
    if(GetLastError() == ERROR_IO_PENDING)
    GetOverlappedResult(Comm->Handle, &os, &dwTransfer, true);
    }

    if(dwEvtMask & EV_RXCHAR)
    {
    WaitForSingleObject(Comm->hRecvEvent, 0xffffffff);
    ResetEvent(Comm->hRecvEvent);
    Comm->ComWin->PostMessage(WM_COMMNOTIFY, EV_RXCHAR, (LPARAM)Param);
    }

    if(dwEvtMask & EV_TXEMPTY)
    {
    WaitForSingleObject(Comm->hSendEvent, 0xffffffff);
    ResetEvent(Comm->hSendEvent);
    Comm->ComWin->PostMessage(WM_COMMNOTIFY, EV_TXEMPTY, (LPARAM)Param);
    }
    }
    }

    CloseHandle(os.hEvent);
    }

    Comm->CommThreadRunning = 0;
    _endthread();
    }

    TComm32::TComm32(TWindow *Win)
    {
    InBuf = NULL;
    OutBuf = NULL;

    ComWin = Win;
    Handle = INVALID_HANDLE_VALUE;

    hRecvEvent = NULL;
    hSendEvent = NULL;

    memset(&read_os, 0, sizeof(OVERLAPPED));
    memset(&write_os, 0, sizeof(OVERLAPPED));

    CommThreadId = -1;
    RunComThread = 0;
    CommThreadRunning = 0;

    _PortNo = 2; //"COM2"

    _InBufSize = 8192;
    _OutBufSize = 8192;
    _HwInSize = 1200;
    _HwOutSize = 1200;

    _Baud = CBR_9600;
    _Parity = NOPARITY;
    _ByteSize = 8;
    _StopBits = ONESTOPBIT;
    }

    TComm32::~TComm32()
    {
    Close();
    }

    int TComm32::SetPort(int COMn)
    {
    bool NeedReopen = Opened();
    int Err = 0;

    if(NeedReopen)
    if((Err=Close())!=0)
    return -Err;

    _PortNo = COMn;

    if(NeedReopen)
    if((Err=Open())!=0)
    return Err;

    return Err;
    }

    int TComm32::SetParams(DWORD Baud, BYTE Parity, BYTE ByteSize, BYTE StopBits)
    {
    bool NeedReopen = Opened();
    int Err = 0;

    if(NeedReopen)
    if((Err=Close())!=0)
    return -Err;

    _Baud = Baud ;
    _Parity = Parity ;
    _ByteSize = ByteSize;
    _StopBits = StopBits;

    if(NeedReopen)
    if((Err=Open())!=0)
    return Err;

    return Err;
    }

    int TComm32::SetBufSize(long InBufSize, long OutBufSize, long HwInSize, long HwOutSize)
    {
    bool NeedReopen = Opened();
    int Err = 0;

    if(NeedReopen)
    if((Err=Close())!=0)
    return -Err;

    _InBufSize = InBufSize ;
    _OutBufSize = OutBufSize;
    _HwInSize = HwInSize ;
    _HwOutSize = HwOutSize ;

    if(NeedReopen)
    if((Err=Open())!=0)
    return Err;

    return Err;
    }

    int TComm32::Open(void)
    {
    int Err = 0;

    if(!Opened())
    {
    DCB dcb;
    char Fmt_COMn[] = "COM%d";
    char Str[64];

    if(!Err)
    {
    InBuf = new TCommQueue(_InBufSize);
    if(!InBuf->Valid())
    Err=-1;
    }

    if(!Err)
    {
    OutBuf = new TCommQueue(_OutBufSize);
    if(!OutBuf->Valid())
    Err=-2;
    }

    if(!Err)
    {
    sprintf(Str, Fmt_COMn, _PortNo);
    Handle=CreateFile(Str, GENERIC_READ and GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL and FILE_FLAG_OVERLAPPED, NULL);
    if(Handle==INVALID_HANDLE_VALUE)
    Err=-3;
    }

    if(!Err)
    {
    if(!SetCommMask(Handle, EV_RXFLAG))
    Err=-4;
    }

    if(!Err)
    {
    if(!SetupComm(Handle, _HwInSize, _HwOutSize))
    Err=-5;
    }

    if(!Err)
    {
    if(GetCommState(Handle, &dcb))
    {
    dcb.BaudRate = _Baud;
    dcb.ByteSize = _ByteSize;
    dcb.Parity = _Parity;
    dcb.StopBits = _StopBits;
    if(!SetCommState(Handle, &dcb))
    Err = -7;
    }
    else
    {
    Err = -6;
    }
    }

    if(!Err)
    {
    memset(&read_os, 0, sizeof(OVERLAPPED));
    hRecvEvent=CreateEvent(NULL,true,true,NULL);
    read_os.hEvent=CreateEvent(NULL,true,false,NULL);

    if((!hRecvEvent) and and (!read_os.hEvent))
    Err=-8;
    }

    if(!Err)
    {
    memset(&write_os, 0, sizeof(OVERLAPPED));
    hSendEvent=CreateEvent(NULL,true,true,NULL);
    write_os.hEvent=CreateEvent(NULL,true,false,NULL);

    if((!hSendEvent) and and (!write_os.hEvent))
    Err=-9;
    }

    if(!Err)
    {
    RunComThread = 1;
    CommThreadId = _beginthread(_Comm32_CommWatchThread, 4096, this);
    if(CommThreadId == -1)
    {
    RunComThread = 0;
    Err = -10;
    }
    }

    if(Err)
    Close();
    }

    return Err;
    }

    int TComm32::Close(void)
    {
    int i, Err = 0;

    if(Opened())
    for(i=0; (CommThreadRunning) && (i<500); i++)
    {
    RunComThread = 0;
    SetCommMask(Handle, EV_RXFLAG);
    Sleep(10);
    }
    if(CommThreadRunning)
    Err=-1;
    else
    CommThreadId=-1;

    if(hRecvEvent)
    {
    CloseHandle(hRecvEvent);
    hRecvEvent = NULL;
    }

    if(read_os.hEvent)
    {
    CloseHandle(read_os.hEvent);
    memset(&read_os, 0, sizeof(OVERLAPPED));
    }

    if(hSendEvent)
    {
    CloseHandle(hSendEvent);
    hSendEvent = NULL;
    }

    if(write_os.hEvent)
    {
    CloseHandle(write_os.hEvent);
    memset(&write_os, 0, sizeof(OVERLAPPED));
    }

    if(Handle!=INVALID_HANDLE_VALUE)
    {
    CloseHandle(Handle);
    Handle=INVALID_HANDLE_VALUE;
    }

    if(OutBuf)
    {
    delete OutBuf;
    OutBuf = NULL;
    }

    if(InBuf)
    {
    delete InBuf;
    InBuf = NULL;
    }

    return Err;
    }

    long TComm32::Read(char far *s, long n)
    {
    return InBuf->Out(s,n);
    }

    long TComm32::Write(char far *s, long n)
    {
    long Retv = OutBuf->In(s,n);
    ComWin->PostMessage(WM_COMMNOTIFY, EV_TXEMPTY, (LPARAM)this);
    return Retv;
    }

    void TComm32::CommNotify(int NotifyType)
    {
    if(NotifyType & EV_RXCHAR)
    {
    DWORD dwErrorFlag, dwLen, dwBytesRd;
    COMSTAT ComStat;
    char RecvBuf[4096];

    ClearCommError(Handle, &dwErrorFlag, &ComStat);
    dwLen=ComStat.cbInQue;
    if(dwLen>0)
    {
    if(!ReadFile(Handle, RecvBuf, dwLen, &dwBytesRd, &read_os))
    {
    if(GetLastError()==ERROR_IO_PENDING)
    if(WaitForSingleObject(read_os.hEvent, 1000))
    {
    }
    }
    else if(dwBytesRd>0)
    {
    InBuf->In(RecvBuf, dwBytesRd);
    }
    }

    SetEvent(hRecvEvent);
    }

    if(NotifyType & EV_TXEMPTY)
    {
    DWORD dwErrorFlag, dwLen, dwBytesWr;
    COMSTAT ComStat;
    char SendBuf[4096];

    ClearCommError(Handle, &dwErrorFlag, &ComStat);
    dwLen=ComStat.cbOutQue;
    if(dwLen==0)
    {
    if(OutBuf->Count())
    {
    dwLen=OutBuf->Out(SendBuf, 4096);
    WriteFile(Handle, SendBuf, dwLen, &dwBytesWr, &write_os);
    }
    }

    SetEvent(hSendEvent);
    }
    }

    3楼 Firing_Sky (火的天空) 回复于 2000-02-03 21:15:00 得分 0


    串行口是作为文件方式打开的,用CreateFile打开串口,并得到串口句柄
    然后设定一个DCB结构指定端口的特性
    读写串口文件
    关闭串口文件

    4楼 lov () 回复于 2000-02-03 21:58:00 得分 0


    我曾经开发过交换机计费的项目,当时的串口通信我是用winapi函数做的,太复杂.我发
    现用微软的Microsoft Communications Control控件很简单,详细的函数说明MSDN有,我相信它能解决你问题!

    5楼 yb () 回复于 2000-02-07 10:38:00 得分 0


    同意lov的意见。

竟价广告:

    业界行情新闻声明事项:

    • ☉本网转载出于传递更多信息之目的,并不意味着赞同其观点或证实其内容的真实性!
    • ☉如其他媒体、网站或个人从本网下载使用,必须保留本网注明的“稿件来源”,并自负版权等法律责任。如对稿件内容有疑议,请及时与我们联系.
    • ☉如本网转载稿涉及版权等问题,请作者在速来电或来函与杭州电脑数码城网联系.
    • ☉本站网址:http://www.ititt.com/投诉邮箱:6371222@qq.com