在哪里下载的也忘掉了,在2000下用起来没有问题,但98下面,发送的len与written不一样,发送len为8字节,但WriteFile调用后,实际写过去的字节数变量written为0,但接收方也明明看到有8个字节送过来的。请高手看一眼代码,以前没有在98下面试过,这一试傻眼了,查了MSDN好像也没有什么不对的地方啊:(comaccess.h////////////////////////////////////////////////////////////////////////////////////////
// 
// Project:    Class ComAccess
//              Overlapped serial IO communication class
//  System:     Win9x WinNT
// File:       comaccess.h
// Start date: 17.11.1997
// Update:     31.07.1998
// Version:    1.2
// Author:     Patrick Feuser [email protected] Germany
// Copyright © 1997. Alle Rechte vorbehalten
//
////////////////////////////////////////////////////////////////////////////////////////#ifndef _COMACCESS_H_
#define _COMACCESS_H_
#include <windows.h>
class ComAccess 
{
private: HANDLE      m_hCom; // Device handle  OVERLAPPED  m_ov;   // A structure that contains informations which are
                    // used for asynchronous input and output operations TCHAR       m_lpszErrorMessage[256];public: ComAccess(VOID);
ComAccess(LPCSTR lpszPortNum); ~ComAccess() { Close(); }
    // For more definitions see <winbase.h>
BOOL Open(LPCSTR lpszPortNum = "com1", 
     DWORD  dwBaudRate  = CBR_9600, 
     BYTE   byParity    = NOPARITY,
     BYTE   byStopBits  = TWOSTOPBITS,
     BYTE   byByteSize  = 8); VOID Close(VOID);

DWORD WriteData(LPCVOID pdata, DWORD len);
DWORD ReadData(LPVOID  pdest, DWORD len, DWORD dwMaxWait = 500); LPSTR GetErrorMessage(VOID) { return m_lpszErrorMessage; }private: VOID ErrorToString(LPCSTR lpszMessage); BOOL IsNT(VOID);
};
#endif // _COMACCESS_H_

解决方案 »

  1.   

    comaccess.cpp////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Project:    Class ComAccess
    //              Overlapped serial IO communication class
    //  System:     Win9x WinNT
    //  File:       comaccess.cpp
    //  Start date: 17.11.1997
    //  Update:     31.07.1998
    //  Version:    1.2
    //  Author:     Patrick Feuser [email protected] Germany
    //  Copyright &copy; 1997. Alle Rechte vorbehalten
    //
    ////////////////////////////////////////////////////////////////////////////////////////#include "StdAfx.h"
    #include "comaccess.h"////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Constructors
    //ComAccess::ComAccess(VOID)
    {
    m_hCom = 0;
    m_lpszErrorMessage[0] = '\0';
    ZeroMemory(&m_ov, sizeof(m_ov));
    }
    ComAccess::ComAccess(LPCSTR lpszPortNum)

    ComAccess::ComAccess();
    ComAccess::Open(lpszPortNum); 
    }////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Function:      Open(LPCSTR lpszPortNum,
    //                      DWORD  dwBaudRate, 
    //                      BYTE   byParity,
    //                      BYTE   byStopBits,
    //                      BYTE   byByteSize)
    //
    //  Return value:  BOOL TRUE or FALSE
    //BOOL ComAccess::Open(LPCSTR lpszPortNum, 
                         DWORD  dwBaudRate, 
                         BYTE   byParity,
                         BYTE   byStopBits,
     BYTE   byByteSize)
    {
    DCB  dcb; // structure that defines the control setting for a serial communications device
    BOOL bSuccess;

    m_hCom = CreateFile(lpszPortNum,           // pointer to name of the file
                        GENERIC_READ|GENERIC_WRITE, // access mode
                        0,                     // comm devices must be opened w/exclusive-access 
                        NULL,                  // no security attributs 
                        OPEN_EXISTING,         // comm devices must use OPEN_EXISTING 
                        FILE_FLAG_OVERLAPPED,  // overlapped I/O
                        NULL);                 // hTemplate must be NULL for comm devices  if ( m_hCom == INVALID_HANDLE_VALUE ) 
    {
    // handle the error
    ComAccess::ErrorToString("Open(): CreateFile() failed, invalid handle value");

    return FALSE;
    } //
    // Omit the call to SetupComm to use the default queue sizes.
    // Get the current configuration.
    //
     
    bSuccess = GetCommState(m_hCom, &dcb); if ( ! bSuccess ) 
    {
    // Handle the error.
    ComAccess::ErrorToString("Open(): GetCommState() failed");
    ComAccess::Close(); return FALSE;
    } //
    // Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit are default parameters
    // dcb.BaudRate = dwBaudRate;
    dcb.ByteSize = byByteSize;
    dcb.Parity   = byParity;
    dcb.StopBits = byStopBits;

    bSuccess = SetCommState(m_hCom, &dcb); if ( ! bSuccess ) 
    {
    // Handle the error. 
    ComAccess::ErrorToString("Open(): SetCommState() failed");
    ComAccess::Close(); return FALSE;
    } return TRUE;
    }////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Function:      Close(VOID)
    //
    //  Return value:  VOID
    //VOID ComAccess::Close(VOID)
    {
    if ( m_hCom > 0 )
    {
    CloseHandle(m_hCom);
    } m_hCom = 0; 
    }////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Function:     WriteData(LPCVOID pdata, 
    //                          DWORD   len)
    //
    //  Return value:  DWORD -1 failed, above, num written bytes
    //DWORD ComAccess::WriteData(LPCVOID pdata, 
                               DWORD   len)
    {
    BOOL  bSuccess;
    DWORD written = 0; if ( len < 1 )
    return(0); // create event for overlapped I/O
    m_ov.hEvent = CreateEvent(NULL,   // pointer to security attributes 
                              FALSE,   // flag for manual-reset event 
                              FALSE,  // flag for initial state 
                              "");    // pointer to event-object name  if ( m_ov.hEvent == INVALID_HANDLE_VALUE )
    {
    // Handle the error.
    ComAccess::ErrorToString("WriteData(): CreateEvent() failed");
      
    return(-1);
    } bSuccess = WriteFile(m_hCom,   // handle to file to write to  
                         pdata,    // pointer to data to write to file 
                         len,      // number of bytes to write 
                         &written, // pointer to number of bytes written 
                         &m_ov);   // pointer to structure needed for overlapped I/O
    if ( ComAccess::IsNT() )
    {
    bSuccess = GetOverlappedResult(m_hCom, &m_ov, &written, TRUE); if (  bSuccess )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    ComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed");            CString msg_1;
            msg_1.Format ("len is %d, written is %d",len,written);
    ComAccess::ErrorToString(msg_1); 
    return(-1);
    }
    }
    else
    if ( len != written )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
            CString msg_1;
            msg_1.Format ("len is %d, written is %d",len,written);
    ComAccess::ErrorToString(msg_1);  return(-1);
    } CloseHandle(m_ov.hEvent);    written = 8;
    return written;
    }////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Function:      ReadData(LPVOID pdest, 
    //                         DWORD  len, 
    //                          DWORD  dwMaxWait)
    //
    //  Return value:  DWORD -1 failed, above, num read bytes
    //
      

  2.   

    DWORD ComAccess::ReadData(LPVOID pdest, 
                              DWORD  len, 
                              DWORD  dwMaxWait)
    {
    BOOL  bSuccess;
    DWORD result = 0,
          read   = 0, // num read bytes
          mask   = 0; // a 32-bit variable that receives a mask 
                      // indicating the type of event that occurred if ( len < 1 ) return(0); // create event for overlapped I/O m_ov.hEvent = CreateEvent(NULL,   // pointer to security attributes 
                              FALSE,   // flag for manual-reset event 
                              FALSE,  // flag for initial state 
                              "");    // pointer to event-object name  if ( m_ov.hEvent == INVALID_HANDLE_VALUE )
    {
    // Handle the error.
    ComAccess::ErrorToString("ReadData(): CreateEvent() failed");
      
    return(-1);
    } // Specify here the event to be enabled bSuccess = SetCommMask(m_hCom, EV_RXCHAR); if ( ! bSuccess )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    ComAccess::ErrorToString("ReadData(): SetCommMask() failed");
      
    return(-1);
    }
    // WaitForSingleObject bSuccess = WaitCommEvent(m_hCom, &mask, &m_ov); if ( ! bSuccess )
    {
    int err = GetLastError(); if ( err == ERROR_IO_PENDING)
    {
    result = WaitForSingleObject(m_ov.hEvent, dwMaxWait);  //wait dwMaxWait
                                            // milli seconds before returning
    if ( result == WAIT_FAILED )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    ComAccess::ErrorToString("ReadData(): WaitForSingleObject() failed");
      
    return(-1);
    }
    }
    }

    // The specified event occured?

    if ( mask & EV_RXCHAR) 
    {
    bSuccess = ReadFile(m_hCom, // handle of file to read 
                    pdest,  // address of buffer that receives data 
                len,    // number of bytes to read 
            &read,  // address of number of bytes read 
        &m_ov); // address of structure for data  if ( ComAccess::IsNT() )
    {
    bSuccess = GetOverlappedResult(m_hCom, &m_ov, &read, TRUE); if ( ! bSuccess )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    ComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed"); return(-1);
    }
    }
    else
    if ( ! bSuccess )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    ComAccess::ErrorToString("ReadData(): ReadFile() failed"); return(-1);
    }
    }
    else
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    wsprintf(m_lpszErrorMessage, "Error ReadData(): No EV_RXCHAR occured\n"); return(-1);
    }

    CloseHandle(m_ov.hEvent);

    return read;
    }////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Function:      ErrorToString(LPCSTR lpszMessage)
    //
    //  Return value:  VOID
    //VOID ComAccess::ErrorToString(LPCSTR lpszMessage)
    {
    LPVOID lpMessageBuffer;
    DWORD  error = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM,      // source and processing options
                  NULL,                            // pointer to message source
                  error,                           // requested message identifie
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // the user default language.
                  (LPTSTR) &lpMessageBuffer,       // pointer to message buffer
                  0,                               // maximum size of message buffer
                  NULL);                           // address of array of message inserts  // and copy it in our error string
    wsprintf(m_lpszErrorMessage,"%s: (%d) %s\n", lpszMessage, error, lpMessageBuffer); LocalFree(lpMessageBuffer);
    }////////////////////////////////////////////////////////////////////////////////////////
    // 
    //  Function:     IsNT(VOID)
    //
    //  Return value: BOOL True or False
    //BOOL ComAccess::IsNT(VOID)
    {
        OSVERSIONINFO osvi;
        
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        
        GetVersionEx(&osvi);    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) 
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
      

  3.   

    你的WriteData(LPCVOID pdata, DWORD   len)
    跟我的程序差不多啊。
    我的也能在2000下用,
    98我也没特意去试过。
    我看程序是没什么问题,
      

  4.   

    我用VC。NET+2000 server做的,
    发现设置 DCB结构的时候,最后一个参数要去调,
      

  5.   

    我也看了很多资料上的方法,大家基本上都是这样做的,为什么我在98下面不行呢?在98下面执行的时候会跳到如下语句:
    else
    if ( len != written )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    CString msg_1;
    msg_1.Format ("len is %d, written is %d",len,written);
    ComAccess::ErrorToString(msg_1); 
    return(-1);
    }
    如果发送8个字节,则len为8,而written实际写入串口的数据为0,但对方已经接收到数据的。我强制将written默认为8,但读的时候还是有问题。
      

  6.   

    我的发送与接收函数如下:
    void CMotorCtrlPanelView::SendUsart(BYTE oprcode, UINT addr, UINT data)
    {
        ComAccess * com;
        CString msg;
        unsigned char TxUsartData[10];
        unsigned char RxUsartData[20];
        int send_result;
        int read_result;
        WORD textlen;
        INT16 temp;
        
        *TxUsartData = 0xFF;
        *(TxUsartData + 1) = oprcode;
        temp.intall = addr;
        *(TxUsartData + 2) = temp.intbyte .HighByte;
        *(TxUsartData + 3) = temp.intbyte .LowByte;
        temp.intall = data;
        *(TxUsartData + 4) = temp.intbyte .HighByte ;
        *(TxUsartData + 5) = temp.intbyte .LowByte ;
        
        reg_crc=0xffff;
    for(int i=0; i<6; i++)
    {
    crc_chk(*(TxUsartData + i));
    }
        temp.intall = reg_crc;
    *(TxUsartData + 6) = temp.intbyte .LowByte ;
    *(TxUsartData + 7) = temp.intbyte .HighByte ;
            if ( ! (com = new ComAccess()) )
    {
            msg.Format("*** Error: Not enough memory to create ComAccess object!\n");
            textlen = m_out_msg.GetWindowTextLength ();
            m_out_msg.SetSel (textlen,textlen);
            m_out_msg.ReplaceSel (msg);
    return;
    }
    if(!com->Open ("com1", CBR_9600, NOPARITY, TWOSTOPBITS, 8))
    {
            msg.Format ("*** Error: Can't open communication device!\n", "%s", com->GetErrorMessage());
            textlen = m_out_msg.GetWindowTextLength ();
            m_out_msg.SetSel (textlen,textlen);
            m_out_msg.ReplaceSel (msg);
    delete com;
    return;
    }
        send_result = com->WriteData(TxUsartData, 8);
        if ( send_result < 0 )
        {
            msg.Format ("*** Error: %s\n", com->GetErrorMessage ());
            textlen = m_out_msg.GetWindowTextLength ();
    //        m_out_msg.SetFocus ();
            m_out_msg.SetSel (textlen,textlen);
            m_out_msg.ReplaceSel (msg);
        }
        else
        {
            msg.Format ("Waiting...");
            textlen = m_out_msg.GetWindowTextLength ();
            m_out_msg.SetSel (textlen,textlen);
            m_out_msg.ReplaceSel (msg);
            TxMsgCount ++;
        }
        read_result = com->ReadData(RxUsartData, 20);
        if ( (read_result < 0)  )
        {
            msg.Format ("*** Error:%s\n", com->GetErrorMessage());
            textlen = m_out_msg.GetWindowTextLength ();
            m_out_msg.SetSel (textlen,textlen);
            m_out_msg.ReplaceSel (msg);        msg.Format ("*** Error: Operation is failed!\n");
            textlen = m_out_msg.GetWindowTextLength ();
            m_out_msg.SetSel (textlen,textlen);
            m_out_msg.ReplaceSel (msg);
             
        }
        else
        {
            msg.Format ("Operation is successed!");
            textlen = m_out_msg.GetWindowTextLength ();
            m_out_msg.SetSel (textlen,textlen);
            m_out_msg.ReplaceSel (msg);        // process the status        
        }
        // close communication device
    com->Close();
        // destruct the communication device object and free memory 
    delete com;
    }
      

  7.   

    2000下真的能用吗??
    这个真搞不懂?你说的 written为8,为什么 len 还是不等于written
    是不是len 有问题??
      

  8.   

    不知道为什么,在2000下面,writefile的参数中,需要发送的字节数与实际发送的字节数都为8(我发8字节),但在98下面,发送的字节数(len)为8,接收的字节数(written)就是为0,但实际上数据已经发送出去了,我另外的设备已经接收到,所以我准备去掉
    else
    if ( len != written )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    CString msg_1;
    msg_1.Format ("len is %d, written is %d",len,written);
    ComAccess::ErrorToString(msg_1); 
    return(-1);
    }
    这段代码,而且很多代码例程里面都没有这段代码的。
    但是在98下面依然读不到数据,代码会进入这里:
    else
    if ( ! bSuccess )
    {
    // Handle the error.
    CloseHandle(m_ov.hEvent);
    ComAccess::ErrorToString("ReadData(): ReadFile() failed"); return(-1);
    }
    我依然屏蔽掉这段代码,但数据没有读到。
    WIN2000下面是没有问题的。
      

  9.   

    我屏障掉如下的语句后,writefile()函数调用后,实际发送的字节数与请求发送的字节数就相同了。
    但读数据还是有问题!
    m_ov.hEvent = CreateEvent(NULL,   // pointer to security attributes 
                     FALSE,   // flag for manual-reset event 
                     FALSE,  // flag for initial state 
                     "");    // pointer to event-object name
      

  10.   

    我也遇到这样的问题。有人告诉我说98缺少文件,从2000下拷贝就行了。可不知道缺少哪个文件。别人还说MSDN里有,可我死活找不到。郁闷。