gongxd 发表于 2009-4-24 10:19:57

vc 用mscomm奇怪问题

问题是用vc的程序给下位机发送读数据命令,但每次都返回两组数据,我由用vb做了一个是正常的,发送一个指令,就返回一组数据
如果先运行vc的程序,再运行vb的程序第一次会获得两组数据,以后就正常了,那位能帮忙看看

vc的接收代码:
//打开串口
BOOL CMscommDlg::CommOpen(CMSComm &MSCOMIN,int COMPortNOIN)
{
        // TODO: Add your control notification handler code here
        //如果串口打开则关闭
        if(MSCOMIN.GetPortOpen())
        {
                MSCOMIN.SetPortOpen(FALSE);
        }
        short i;
        i=(short)COMPortNOIN;
        try
        {
                MSCOMIN.SetCommPort(i); //选择com
                m_mscomm.SetInputMode(1);//1:表示以二进制方式检取数据
                m_mscomm.SetInBufferSize(1024); //接收缓冲区
                m_mscomm.SetOutBufferSize(1024);//发送缓冲区
                m_mscomm.SetSettings(m_CommSettingStr);
                m_mscomm.SetRThreshold(1);         //参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的OnComm事件
                if(!m_mscomm.GetPortOpen())
                {
                        m_mscomm.SetPortOpen(TRUE);//打开串口
                }
                m_mscomm.SetInputLen(0); //// 每次读取缓冲区中 所有数据
                m_mscomm.GetInput();//先预读缓冲区以清除残留数据


        }
        catch(CException *e)
        {

                TCHAR errormsg;
                e->GetErrorMessage (errormsg,255,NULL);
                CString msg;
                msg.Format("端口COM%i无效,请检查串口是否被其它程序占用或硬件连线错误\r\n\r\n错误描述:",i);
                msg+=errormsg;
                MessageBox(msg,"无法打开串口",MB_ICONSTOP);
                return FALSE;
        }

        //保存INI       
        CMyInI myini;
        myini.Put("COM",(int)i);
        myini.Put("COMSetting",m_CommSettingStr);

        //CString title;
        //title.Format("智能充电架数据服务器v1.0COM%i",(int)i);
        //this->SetWindowText(title);
        return TRUE;
       
}


//串口接收事件
void CMscommDlg::OnOnCommMscomm1()
{
    if(        m_mscomm.GetCommEvent()==2) //事件值为2表示接收缓冲区内有字符
    {      
                COleVariant myVar;
                COleSafeArray safearray_inp;
                LONG len,k;
                     sleep(10);
                myVar.Attach(m_mscomm.GetInput()); //读缓冲区
                safearray_inp=myVar;
                len=safearray_inp.GetOneDimSize(); //得到有效数据长度
      if (len>0)
      {
                        for(k=0;k<len;k++)
                        {
                                safearray_inp.GetElement(&k,FrameProcesser.rxdata+k);//转换为BYTE型数组
                        }
                        FrameProcesser.StreamInput(FrameProcesser.rxdata,len);
                        //串口收到数据处理函数
                        CommRev();
      }
               
    }       
}


下面是抓的包
//=======================================================用vc的===============================================================

1       IRP_MJ_CLOSE                  Port Closed
2       IRP_MJ_CREATE                   Port Opened - mscomm.exe
3       IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 9600
4       IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
//发送读数据指令
5       IRP_MJ_WRITE                  Length: 0007, Data: 55 AA 03 F2 01 01 F7
//返回数据 这里有问题 返回了两组 55 AA开头的
6       IRP_MJ_READ                     Length: 0004, Data: 55 AA 11 F3
7       IRP_MJ_READ                     Length: 0015, Data: 01 01 58 00 00 00 00 00 00 00 34 00 00 00 00
8       IRP_MJ_READ                     Length: 0002, Data: 00 92
//不应该有这一组
9       IRP_MJ_READ                     Length: 0009, Data: 55 AA 11 F3 01 01 58 00 00
10      IRP_MJ_READ                     Length: 0012, Data: 00 00 00 00 00 34 00 00 00 00 00 92
//发送另一个读数据指令
11      IRP_MJ_WRITE                  Length: 0007, Data: 55 AA 03 F2 01 02 F8



//==========================================================用vb的============================================================
1       IRP_MJ_CLOSE                  Port Closed
2       IRP_MJ_CREATE                   Port Opened - HD_vbserial1.exe
3       IOCTL_SERIAL_SET_BAUD_RATE      Baud Rate: 9600
4       IOCTL_SERIAL_SET_LINE_CONTROL   StopBits: 1, Parity: No, DataBits: 8
//发送读数据指令
5       IRP_MJ_WRITE                  Length: 0009, Data: 55 AA 05 F2 01 01 01 01 FB
//返回数据 第一次返回了两组 55 AA开头的
6       IRP_MJ_READ                     Length: 0001, Data: 55
7       IRP_MJ_READ                     Length: 0001, Data: AA
8       IRP_MJ_READ                     Length: 0002, Data: 11 F3
9       IRP_MJ_READ                     Length: 0002, Data: 01 01
10      IRP_MJ_READ                     Length: 0002, Data: 0C 00
11      IRP_MJ_READ                     Length: 0001, Data: 00
12      IRP_MJ_READ                     Length: 0001, Data: 00
13      IRP_MJ_READ                     Length: 0001, Data: 00
14      IRP_MJ_READ                     Length: 0001, Data: 00
15      IRP_MJ_READ                     Length: 0001, Data: 00
16      IRP_MJ_READ                     Length: 0001, Data: 00
17      IRP_MJ_READ                     Length: 0001, Data: 34
18      IRP_MJ_READ                     Length: 0001, Data: 00
19      IRP_MJ_READ                     Length: 0001, Data: 00
20      IRP_MJ_READ                     Length: 0001, Data: 00
21      IRP_MJ_READ                     Length: 0003, Data: 00 00 46

22      IRP_MJ_READ                     Length: 0001, Data: 55
23      IRP_MJ_READ                     Length: 0002, Data: AA 11
24      IRP_MJ_READ                     Length: 0002, Data: F3 01
25      IRP_MJ_READ                     Length: 0001, Data: 01
26      IRP_MJ_READ                     Length: 0002, Data: 0C 00
27      IRP_MJ_READ                     Length: 0002, Data: 00 00
28      IRP_MJ_READ                     Length: 0002, Data: 00 00
29      IRP_MJ_READ                     Length: 0002, Data: 00 00
30      IRP_MJ_READ                     Length: 0002, Data: 34 00
31      IRP_MJ_READ                     Length: 0002, Data: 00 00
32      IRP_MJ_READ                     Length: 0002, Data: 00 00
33      IRP_MJ_READ                     Length: 0001, Data: 46
//发送读数据指令 以后就正确了
34      IRP_MJ_WRITE                  Length: 0009, Data: 55 AA 05 F2 01 01 01 01 FB
//返回正确数据
35      IRP_MJ_READ                     Length: 0001, Data: 55
36      IRP_MJ_READ                     Length: 0003, Data: AA 11 F3
37      IRP_MJ_READ                     Length: 0003, Data: 01 01 20
38      IRP_MJ_READ                     Length: 0004, Data: 00 00 00 00
39      IRP_MJ_READ                     Length: 0004, Data: 00 00 00 34
40      IRP_MJ_READ                     Length: 0004, Data: 00 00 00 00
41      IRP_MJ_READ                     Length: 0002, Data: 00 5A
//发送读数据指令
42      IRP_MJ_WRITE                  Length: 0009, Data: 55 AA 05 F2 01 01 01 01 FB
//返回正确数据
43      IRP_MJ_READ                     Length: 0001, Data: 55
44      IRP_MJ_READ                     Length: 0003, Data: AA 11 F3
45      IRP_MJ_READ                     Length: 0002, Data: 01 01
46      IRP_MJ_READ                     Length: 0004, Data: 20 00 00 00
47      IRP_MJ_READ                     Length: 0005, Data: 00 00 00 00 34
48      IRP_MJ_READ                     Length: 0006, Data: 00 00 00 00 00 5A
//发送读数据指令
49      IRP_MJ_WRITE                  Length: 0009, Data: 55 AA 05 F2 01 01 01 01 FB
//返回正确数据
50      IRP_MJ_READ                     Length: 0001, Data: 55
51      IRP_MJ_READ                     Length: 0003, Data: AA 11 F3
52      IRP_MJ_READ                     Length: 0004, Data: 01 01 20 00
53      IRP_MJ_READ                     Length: 0009, Data: 00 00 00 00 00 00 34 00 00
54      IRP_MJ_READ                     Length: 0004, Data: 00 00 00 5A

kingofkings 发表于 2009-4-24 14:01:32

以下蓝色文字由版主:kingofkings 于:2009-04-24,14:01:32 加入。<font color=black>请发贴人注意:本贴放在这分区不合适,即将移走
原来分区:AVR32技术论坛
即将移去的分区:上位机软件开发(Delphi,C++等)
移动执行时间:自本贴发表0小时后
任何的疑问或咨询,请可随时联系站长。谢谢你的支持!</font>

gongxd 发表于 2009-4-27 19:11:43

不用MSCOMM了很垃圾,改用CserialPort了,自己又改了一下,原来CserialPort只可以接收一个字符,改为接收缓冲区了,最多一次接收1024个,自我感觉良好
点击此处下载VC工程文件ourdev_440279.rar(文件大小:164K) (原文件名:My_serialport.rar)


#ifndef __SERIALPORT_H__
#define __SERIALPORT_H__

//修改BY 中国传惠 Transmart gongxd@126.com,模拟Mscomm
//2009-4-24 修改为读取缓冲区了
//unsigned char RXBuff; //为读缓冲区
//DWORD   RXBuffCount; //读得数据大小
//2009-4-25 setsetings()

#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.
#include <afxtempl.h>
class CSerialPort
{
//自定义属性
public:       

        unsigned char RXBuff;
        DWORD   RXBuffCount;
//自定义函数
public:       
        BOOL Create(CWnd* pParentWnd);
        void SetCommPort(short nNewValue);
        short GetCommPort();

        void SetSettings(LPCTSTR lpszNewValue);
        CString GetSettings();
       
       
        long GetInBufferCount();
        unsigned char * GetInput();
        void SetOutput(unsigned char *sbuff,int sbufflen);

        BOOLSetPortOpen(BOOL bNewValue);
        BOOL SetPortOpen(CWnd* pw,BOOL bNewValue);
        BOOL GetPortOpen();
        CStringGetLastError();
//自定义
protected:
        //串口打开
        BOOL m_PortOpened;
        CString m_COMSettings;
        void CString_Split(CString &string,   LPCTSTR separator,CArray<CString,CString&>   &   outArr);
        CString errmsg;
        UINT Comportno;
        UINT ComBaud;
        char Comparity;
        UINT Comdatabits;
        UINT Comstopbits;
public:
        int m_nWriteSize;
        void ClosePort();
        // contruction and destruction
        CSerialPort();
        virtual                ~CSerialPort();

        // port initialisation                                                                                       
        BOOL                InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 9600, 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(unsigned 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;

        // 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__

zf8848 发表于 2009-4-27 21:42:05

都已经用VC了,最直接的是从 CreateFile 自己打开 COM 做,自己全面控制 RS232,要想简单用 CSerial 类,这个在 CodeProject 有源码下载的.
页: [1]
查看完整版本: vc 用mscomm奇怪问题