我在VC中,用CSerial Port 类,写一个串口通信小程序,想用WM_COMM_RXFLAG_DETECTED这个事件告知我一次接收信息完成。我的主程序文件是:CVerDlg.cpp,在该文件中:ON_MESSAGE(WM_COMM_RXFLAG_DETECTED, OnCommEnd)LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)在CVerDlg.h中:
  afx_msg LONG OnCommEnd(WPARAM ch, LPARAM port);现在,当接收到串口发送来的消息后,我可以进入
LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)
这个函数但是,问题在于:
如果串口到来的消息只有一个字节,我每接收完这条消息后,进入LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)这个函数一次, 如果串口发送的消息大于一个字节(2~N)则每次接收完消息后,会进入这个函数两次,为啥会这样?还盼牛人指点!!!!  或者是,我对WM_COMM_RXFLAG_DETECTED这个事件的理解有问题??

解决方案 »

  1.   

    我以前用这个串口类读取大量的数据用的是在timer里定时读取(轮询)的方式,事件没试过,也许需要设置阈值什么的?其实进入OnCommEnd多次也没关系的,你自己要把数据重新打包然后在接收端解包就可以了
      

  2.   

    如果是单纯地接受数据的话,确实这样是没什么影响的。 但是,我现在要根据收到的数据自动应答,如果接收到一次,但是却两次进入LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)函数的话,我就自动应答两次,就悲剧了
      

  3.   

    你到底想说什么,进入几次不重要,重要的是你怎么处理接收的。如果是end了,你也得接收下一个啊,你的协议是什么,能贴点源码吗
      

  4.   


    我的协议是:没接收到一条信息,不验证信息的内容,立即回复一条信息(回复的信息是预先存储的,且每一条按次序均不相同)。在这种情况下,如果其实只收到一条信息,但却进入了两次LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)函数,这是,我的程序就会发出两条不同的应答信息,但事实上,这时候应该只发送一条应答信息,这就是现在的问题代码的话,其实就是我在1楼所贴的:
    我的程序中使用了CSerialPort 类,我使用了该类中定义的WM_COMM_RXFLAG_DETECTED事件(Serial Port.h文件中)
    #define WM_COMM_RXFLAG_DETECTED WM_USER+8 // The event character was received and placed in the input buffer. 而后,在我的主程序文件(CVer1Dlg.cpp)中,定义了LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)这个函数对该事件的响应
    ON_MESSAGE(WM_COMM_RXFLAG_DETECTED, OnCommEnd)LONG CVer1Dlg::OnCommEnd(WPARAM ch, LPARAM port)当然,在CVer1Dlg.h中,也有声明
    afx_msg LONG OnCommEnd(WPARAM ch, LPARAM port);就是这样的了现在的情况是,接收到一次串口数据后,可以进入上述函数,如果接收的数据只有一个字节,则只进入上述函数一次;如果一次接收的数据超过一个字节,就会进入上述函数两次。。  我想要的结果是,一次不管接收多少个字节,只进入这个函数一次。 这个,是不是也是WM_COMM_RXFLAG_DETECTED这个事件的本来意义?或者说,我对WM_COMM_RXFLAG_DETECTED这个事件的理解有问题?
      

  5.   

    把CSerialPort类的代码贴出来 虽然貌似这个类在网上很多的样子。。
    SerialPort.h#ifndef __SERIALPORT_H__
    #define __SERIALPORT_H__#define WM_COMM_BREAK_DETECTED WM_USER+1 // A break was detected on input.
    #define WM_COMM_CTS_DETECTED WM_USER+2 // The CTS (clear-to-send) signal changed state. 
    #define WM_COMM_DSR_DETECTED WM_USER+3 // The DSR (data-set-ready) signal changed state. 
    #define WM_COMM_ERR_DETECTED WM_USER+4 // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. 
    #define WM_COMM_RING_DETECTED WM_USER+5 // A ring indicator was detected. 
    #define WM_COMM_RLSD_DETECTED WM_USER+6 // The RLSD (receive-line-signal-detect) signal changed state. 
    #define WM_COMM_RXCHAR WM_USER+7 // A character was received and placed in the input buffer. 
    #define WM_COMM_RXFLAG_DETECTED WM_USER+8 // The event character was received and placed in the input buffer.  
    #define WM_COMM_TXEMPTY_DETECTED WM_USER+9 // The last character in the output buffer was sent.  class CSerialPort
    {  
    public:
    int m_nWriteSize; 
    void ClosePort();
    // contruction and destruction
    CSerialPort();
    virtual ~CSerialPort(); // port initialisation
    BOOL InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, char parity = 'N', UINT databits = 8, UINT stopbits = 1, DWORD dwCommEvents = EV_RXCHAR, UINT writebuffersize = 1024);
    HANDLE m_hComm; // start/stop comm watching
    BOOL StartMonitoring();
    BOOL RestartMonitoring();
    BOOL StopMonitoring(); DWORD GetWriteBufferSize();
    DWORD GetCommEvents();
    DCB GetDCB(); void WriteToPort(char* string);
    void WriteToPort(char* string,int n);
    void WriteToPort(LPCTSTR string);
    void WriteToPort(LPCTSTR string,int n);protected:
    // protected memberfunctions
    void ProcessErrorMessage(char* ErrorText);
    static UINT CommThread(LPVOID pParam);
    static void ReceiveChar(CSerialPort* port, COMSTAT comstat);
    static void WriteChar(CSerialPort* port); // thread
    CWinThread* m_Thread; // synchronisation objects
    CRITICAL_SECTION m_csCommunicationSync;
    BOOL m_bThreadAlive; // handles
    HANDLE m_hWriteEvent;
    HANDLE m_hShutdownEvent; // Event array. 
    // One element is used for each event. There are two event handles for each port.
    // A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent).
    // There is a general shutdown when the port is closed. 
    HANDLE m_hEventArray[3]; // structures
    OVERLAPPED m_ov;
    COMMTIMEOUTS m_CommTimeouts;
    DCB m_dcb; // owner window
    CWnd* m_pOwner; // misc
    UINT m_nPortNr;
    char* m_szWriteBuffer;
    DWORD m_dwCommEvents;
    DWORD m_nWriteBufferSize;
    };#endif __SERIALPORT_H__
      

  6.   

    这个是因为 你使用的OnComm()这个函数 他响应的条件是:每当接收缓冲区有一个字符到来时 他就会触发这个OnComm()函数 所以当你发一个字节的时候就触发一次 多个字节的时候就是触发多次了!!已也可以Debug下 在OnComm()设置断点 发多字节 观察变量值就很明白了 !!
      

  7.   

    我用的是 Serialport这个多线程类来编的一个类似与串口调试助手程序,但有个那个在接收框中 如何实现自动换行啊 就是说没接收完一次数据 就会自动换行!!我用的是OnComm(WPARAM ch,LPARAM port)这个函数来接收数据的,这个函数是每当接收缓冲区有一个字符到来时 他就响应了 那我如何判断何时数据接收完了啊