当前位置: 行情首页 >> 技术文章 >> 技术文章 >> 请问:有没有BCB的COM口通讯

  • 请问:有没有BCB的COM口通讯的例程? C++ Builder / 基础类
  • 2007-10-18 15:40:33 杭州电脑数码城 转载来源:csdn.net
  • 社区 - C++ Builder / 基础类

    请问:有没有BCB的COM口通讯的例程?

    () 2000-02-01 12:40:00在 C++ Builder / 基础类 提问

    请给出一个详细的例子,谢谢。
    问题点数:100、回复次数:7

    1楼 radish () 回复于 2000-02-01 13:10:00 得分 10


    在我的网页上有一个DELPHI的,不知道你要不要(radsworld.myrice.com)

    2楼 AutoAsm (风流总被雨打风吹去) 回复于 2000-02-03 22:56:00 得分 0


    例程没有,不过COM 通讯 RING 3 就够了,不是太难。

    3楼 bunny () 回复于 2000-02-04 00:29:00 得分 0


    我记得在程序员大本营里有的说!

    4楼 ysh (大白菜) 回复于 2000-02-05 01:48:00 得分 15


    我正在用BCB串口通信程序,已做出现成的程序,但不知是否符合你的要求。查询请E到yangsh_sky@371.net

    5楼 nil (DiDiDa) 回复于 2000-02-13 17:45:00 得分 5


    我有,请与我联系:bcb4zp@21cn.com

    6楼 Firing_Sky (火的天空) 回复于 2000-02-13 17:51:00 得分 20


    #include <windows.h>
    #pragma hdrstop
    #include "ICCDevice.h"
    static HANDLE ComHandle;
    //static HANDLE hCom[4];
    static COMMTIMEOUTS MyCommTimeouts;
    DCB dcb;
    HINSTANCE hInstance;
    //---------------------------------------------------
    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
    {
    hInstance=hinst;
    return 1;
    }
    //------------------------------------------------------------------------
    HINSTANCE __declspec(dllexport) __stdcall GetDLLInstance()
    {
    return(hInstance);
    }
    //------------------------------------------------------------------------------

    bool ReceiveByteFromComDev(double TimeReceiveDelay, unsigned char* ByteBuf, HANDLE hCom)
    {
    unsigned long dwNumRead ;
    unsigned long dwNumtoRead ;
    unsigned char TempCommRead[3];
    GetCommTimeouts(hCom,&MyCommTimeouts);
    MyCommTimeouts.ReadIntervalTimeout = TimeReceiveDelay;
    MyCommTimeouts.ReadTotalTimeoutMultiplier = 1;
    MyCommTimeouts.ReadTotalTimeoutConstant = TimeReceiveDelay;
    SetCommTimeouts(hCom ,&MyCommTimeouts );
    dwNumtoRead = 1 ;
    BOOL Fcom=ReadFile(hCom,&TempCommRead,dwNumtoRead ,&dwNumRead,NULL);
    if (Fcom && dwNumRead!= 0) {*ByteBuf = TempCommRead[0] ;return true;}
    else return false;
    }
    //-------------------------------------------------
    bool SendByteToComm(unsigned char ByteToSend, HANDLE hCom)
    {
    int TimeSendDelay=1;
    unsigned long dwNumWrite ;
    unsigned long dwNumtoWrite ;
    unsigned char TempCommWrite[3];
    GetCommTimeouts(hCom,&MyCommTimeouts);
    MyCommTimeouts.WriteTotalTimeoutMultiplier = TimeSendDelay;
    MyCommTimeouts.WriteTotalTimeoutConstant = 1;
    SetCommTimeouts(hCom,&MyCommTimeouts);
    dwNumtoWrite = 1 ;
    TempCommWrite[0] = ByteToSend ;
    if(WriteFile(hCom, &TempCommWrite , dwNumtoWrite,&dwNumWrite,NULL)) return true;
    else return false;
    }

    int __declspec(dllexport) __stdcall CloseComm(HANDLE hCom)
    {
    if(CloseHandle( hCom )) return 1;
    else return 0;
    }
    //-------------------------------------------------------------------------------
    int __declspec(dllexport) __stdcall SetComm(int CommID,HANDLE *sendhcom)
    {
    if(CommID<1 and and CommID>4)return 0;
    char ComName[]="COM1";
    switch(CommID)
    {
    case 1:{ComName[3]='1';break;}
    case 2:{ComName[3]='2';break;}
    case 3:{ComName[3]='3';break;}
    case 4:{ComName[3]='4';break;}
    default: return 0;
    }
    ComHandle = CreateFile(ComName,
    GENERIC_READ and GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL
    );
    if (!SetupComm( ComHandle ,1024,1024)){ CloseHandle(ComHandle);return 0;}
    GetCommState(ComHandle, &dcb);//Read com' dcb setting
    dcb.BaudRate = CBR_19200;
    dcb.ByteSize = 8; // number of bits/byte, 4-8
    dcb.Parity = EVENPARITY; // 0-4=no,odd,even,mark,space
    dcb.StopBits = ONESTOPBIT;
    dcb.fDtrControl = DTR_CONTROL_DISABLE;//make DTR disable
    dcb.XonChar = 0x17; // XON ASCII char
    dcb.XoffChar = 0x19; // XOFF ASCII char
    dcb.XonLim = 256 ;
    dcb.XoffLim = 1;
    SetCommMask(ComHandle , EV_TXEMPTY and EV_RXCHAR and EV_ERR );
    PurgeComm(ComHandle , PURGE_TXCLEAR);
    PurgeComm(ComHandle , PURGE_RXCLEAR);
    if (!SetCommState(ComHandle, &dcb))return 0;
    *sendhcom = ComHandle;
    // hCom[CommID-1]=ComHandle;
    return 1;
    }
    //------------------------------------------------------------------------------
    int __declspec(dllexport) __stdcall Reset(HANDLE hCom)
    {
    GetCommState(hCom, &dcb);
    dcb.fDtrControl = DTR_CONTROL_ENABLE;
    if (!SetCommState(hCom, &dcb))return 0;
    GetCommState(hCom, &dcb);
    dcb.fDtrControl = DTR_CONTROL_DISABLE;
    if (!SetCommState(hCom, &dcb))return 0;
    else return 1;
    }

    int __declspec(dllexport) __stdcall ShutDown(HANDLE hCom)
    {
    unsigned char p1=0x00,p2=0x00;
    if(!SendByteToComm(0xfa, hCom))return 0;
    if(!SendByteToComm(0x46, hCom))return 0;
    if(!ReceiveByteFromComDev(2000,&p1, hCom));
    if(!ReceiveByteFromComDev(500,&p2, hCom));
    if(!ReceiveByteFromComDev(500,&p2, hCom));
    if(!ReceiveByteFromComDev(500,&p2, hCom));
    if(!ReceiveByteFromComDev(500,&p2, hCom));
    PurgeComm(hCom, PURGE_TXCLEAR);
    PurgeComm(hCom, PURGE_RXCLEAR);
    return 1;
    }

    7楼 ybchen (我)(是)(菜)(鸟)(我)(怕)(谁) 回复于 2000-02-13 21:28:00 得分 50


    我用的是 C++ Builder 的哥哥 Borland C++ 5 编的串口类,
    使用非常简单,稍加改动就可以在 C++ Builder 里面运行,
    因为 C++ Builder 仍然用的是 Borland C++ 5.x 的编译器,
    这里有完整的代码,如果发现有bug请告诉我,同样我也会
    感谢你的,因为这段代码正在使用中。

    串口通讯用的是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 类的实现就明白了, TCommQueue 是保存数据的队列
    //TComm32 & TCommQueue, Copyright (C) ybchen, EMail: ybchen@email.com.cn
    //======================================================================

    class TCommQueue
    {
    public:
    TCommQueue(long BufSize=8192);
    virtual ~TCommQueue();

    long In(char far *s, long n=1); //RetVal: num of chars pushed in
    long Out(char far *s, long n=1); //RetVal: num of chars poped out
    long Read(char far *s, long n=1, long Offs=0); //RetVal: num of chars read

    void Clear(void) { _First = _Count = 0; }
    long Count(void) { return _Count; }
    long QSize(void) { return _BufSize; }
    bool Valid(void) { return _Buffer != 0; }

    protected:
    long _BufSize, _First, _Count;
    char far *_Buffer;
    };

    //-----------------------------------------------------------------//
    // To use TComm32, The message WM_COMMNOTIFY must be processed //
    // in the user's window as following: //
    //-----------------------------------------------------------------//
    // EV_MESSAGE(WM_COMMNOTIFY, EvCommNotify), //
    // LRESULT TUserWindow::EvCommNotify(WPARAM wParam, LPARAM lParam) //
    // { //
    // ((TComm32 *)lParam)->CommNotify(wParam); //
    // ... ... // add your code here (bytes received or transed) //
    // return true; //
    // } //
    //-----------------------------------------------------------------//

    class 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;
    };

    //============================================================================//
    // TCommQueue //
    //============================================================================//
    TCommQueue::TCommQueue(long BufSize)
    {
    _BufSize = BufSize;
    _First = 0;
    _Count = 0;
    _Buffer = (char far *)malloc(_BufSize);
    }

    TCommQueue::~TCommQueue()
    {
    if(_Buffer)
    {
    free(_Buffer);
    _Buffer=0;
    }
    }

    long TCommQueue::In(char far *c, long n)
    {
    if(_Buffer)
    {
    long i, k, i0;

    i0=(_First+_Count)%_BufSize;
    if((i=_BufSize-_Count)>n)
    i=n;
    if((k=i0+i-_BufSize)<0)
    k=0;
    i-=k;

    if(c)
    {
    memcpy(_Buffer+i0, c, i);
    memcpy(_Buffer, c+i, k);
    }

    _Count+=i+k;
    return i+k;
    }

    return 0;
    }

    long TCommQueue::Out(char far *c, long n)
    {
    if(_Buffer)
    {
    long i, k;

    if((i=_Count)>n)
    i=n;
    if((k=_First+i-_BufSize)<0)
    k=0;
    i-=k;

    if(c)
    {
    memcpy(c , _Buffer+_First, i);
    memcpy(c+i, _Buffer , k);
    }

    _Count-=i+k;
    _First+=i+k;
    _First%=_BufSize;
    return i+k;
    }

    return 0;
    }

    long TCommQueue::Read(char far *c, long n, long Offs)
    {
    if(_Buffer)
    {
    if((Offs>=_Count) and and (Offs<0))
    return 0;

    long i, k, i0;

    i0=(_First+Offs)%_BufSize;
    if((i=_Count-Offs)>n)
    i=n;
    if((k=i0+i-_BufSize)<0)
    k=0;
    i-=k;

    if(c)
    {
    memcpy(c , _Buffer+i0, i);
    memcpy(c+i, _Buffer , k);
    }

    return i+k;
    }

    return 0;
    }

    //============================================================================//
    // TComm32 //
    //============================================================================//
    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<100); 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);
    }
    }


竟价广告:

    业界行情新闻声明事项:

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