说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

自己写了一个异步串口通讯的类,还算好用,现在完善中。要的留下E-mail,一周后发布。适合中级及以下用户!!!。。??

编辑:说三道四文库 发布时间:2018-07-23 04:04
HTML文档下载 WORD文档下载 PDF文档下载
请大家多提意见!!!
是用ApI还是mscomm啊?
给我发一份看看啊,我正需要这个东西那。
huaguomountain@163.com
不胜感激。
mark,
  wwb81@sohu.com

  thank u first.
用API写的,一周后发。
dyh2008@126.com
谢谢
mail@ymroom.com
谢谢。
感谢万分

tns1853@sohu.com
enigmazero@sina.com
呵呵
lb0lblb@126.com
谢谢。
好,给我来个 fcf-128@163.com  谢谢
fym_2001_2001@163.com
谢谢,给我一个
谢谢
 sudianbo@163.com
那位帮我写几个函数:
用VC的控件(参数默认)
按钮1:打开串口
按钮2:发送数据
TEXT1:存放待发送的数据
TEXT2:存放接收到的数据
谢谢
doglu_329@163.net
lixl-2003@163.com

thank u!
我自己也写了个,请专家些指正:
使用API,共3个类:
MTdeque:数据缓冲区,实现多线程数据存取.
CPortSetting:串口参数设置
CRs232Win32:主功能类.

MTdeque.h://无对应CPP,全内联.
//
//  MTDEQUE.H
//

#ifndef MTDEQUE_H
#define MTDEQUE_H
#include <deque>
class MTdeque
{
protected :
    const m_iMaxSize;
std::deque<BYTE> m_Queue;
    CRITICAL_SECTION m_Lock;

public :
    MTdeque( int max_size ) : m_iMaxSize( max_size )
    {
        ::InitializeCriticalSection( &m_Lock );
    }
    ~MTdeque()
    {
        ::DeleteCriticalSection( &m_Lock );
    }
    int SpaceFree()
    {
        ::EnterCriticalSection( &m_Lock );
        int size = m_iMaxSize - m_Queue.size();
        ::LeaveCriticalSection( &m_Lock );
        return ( size < 0 ) ? 0 : size;
    }
    int SpaceUsed()
    {
        ::EnterCriticalSection( &m_Lock );
        int size = m_Queue.size();
        ::LeaveCriticalSection( &m_Lock );
        return size;
    }
    int Insert( char c )
    {
        int return_value;
        ::EnterCriticalSection( &m_Lock );
        if ( m_Queue.size() < m_iMaxSize ) {
            m_Queue.push_back( c );
            return_value = c & 0xff;
        } else
            return_value = -1;
        ::LeaveCriticalSection( &m_Lock );
        return return_value;
    }
    int Insert( char *data, int count )
    {
        ::EnterCriticalSection( &m_Lock );
        int actual = m_iMaxSize - m_Queue.size() ;
        if ( actual < 0 )
            actual = 0;
        if ( count < actual )
            actual = count;
        for ( int i = 0 ; i < actual ; i++ )
            m_Queue.push_back( *data++ );
        ::LeaveCriticalSection( &m_Lock );
        return actual;
    }
    int Extract( char *data, int max )
    {
        int i = 0;
        ::EnterCriticalSection( &m_Lock );
        while ( i < max && m_Queue.size() ) {
            data[ i++ ] = m_Queue.front();
            m_Queue.pop_front();
        }
        ::LeaveCriticalSection( &m_Lock );
        return i;
    }
    int Peek( char *data, int max )
    {
        ::EnterCriticalSection( &m_Lock );
        if ( max > m_Queue.size() )
            max = m_Queue.size();
        for ( int i = 0 ; i < max ; i++ )
            data[ i ] = m_Queue.begin()[ i ];
        ::LeaveCriticalSection( &m_Lock );
        return i;
    }
    int Extract()
    {
        int ret_val = -1;
        ::EnterCriticalSection( &m_Lock );
        if ( m_Queue.size() ) {
            ret_val = m_Queue.front() & 0xff;
            m_Queue.pop_front();
        }
        ::LeaveCriticalSection( &m_Lock );
        return ret_val;
    }
    void Clear()
    {
        ::EnterCriticalSection( &m_Lock );
        m_Queue.clear();
        ::LeaveCriticalSection( &m_Lock );
    }
};

#endif

// EOF MTDeque.h





PortSetting.h:
// PortSetting.h: interface for the CPortSetting class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PORTSETTING_H__84846883_2F05_11D6_ACBC_00D0F808BF85__INCLUDED_)
#define AFX_PORTSETTING_H__84846883_2F05_11D6_ACBC_00D0F808BF85__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/*//
DCB:
DWORD DCBlength
DWORD BaudRate
DWORD fBinary //总为TRUE 
DWORD fParity
DWORD fOutxCtsFlow //传入的CTS行是否为输出流提供了流控制。
//DCB允许CTS和RTS流控制独立地打开和关闭
DWORD fOutxDsr //传入的DSR行是否为输出流提供了流控制。
//DCB允许DTR和DSR流控制独立地打开和关闭
DWORD fDtrControl //控制DTR输出行。=DTR_CONTROL_HANDSHAKE
//把DTR作流控制行,能制止传入的数据。
//DTR_CONTROL_ENABLE用于升高线。
//DTR_CONTROL_DISABLE用于降低线。
DWORD fDsrSensitivity //启用DSR作为数据有效信号。DSR低值无效
DWORD fOutX //XON/XOFF是否适用于发送器。
DWORD fInX //XON/XOFF是否用于控制传入的数据。
DWORD fErrorChar
DWORD fNull //丢弃传入的NULL字符
DWORD fRtsControl //=DTR_CONTROL_HANDSHAKE:RTS线在输入缓冲
//区75%容量时截止传入的数据。25%以下时会
//降低RTS线。可使用RTS_CONTROL_ENABLE,
//RTS_CONTROL_DISABLE。RTS_CONTROL_ENABLE
//中RTS_CONTROL_TOGGLE值在发送器出现数据时
//将asserts RTS,且当TX缓冲区为空时降RTS
DWORD fAbortOnError //错误时终止读写至调用ClearCommError()
WORD XonLim
WORD xOFFLim
BYTE ByteSize //=5-8(7)
BYTE Parity //=NO_PARITY, EVEN_PARITY, ODD_PARITY, 
//=MARK_PARITY,SPACE_PARITY
BYTE StopBits //=ONESTOPBIT,TWOSTOPBITS,
//=ONE5TOPBITS(ByteSize==5)
char XonChar //=0x11(^Q)?
char XoffChar //=0x13(^S)?
char ErrorChar
char EofChar
char EvtChar //特殊字符到达时产生一个事件
//*/

/*//
COMMTIMEOUTS:
DWORD ReadIntervalTimeout
DWORD ReadTotalTimeoutMultiplier
DWORD ReadTotalTimeoutConstant
DWORD WriteTotalTimeoutMultiplier
DWORD WriteTotalTimeoutConstant
//*/

/*//
Mode:
MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s]
             [to=on|off] [xon=on|off] [odsr=on|off]
             [octs=on|off] [dtr=on|off|hs]
             [rts=on|off|hs|tg] [idsr=on|off]
设置串行通讯端口。
该版本的 mode 命令为串行端口 (COM1、COM2、COM3 等等)设置参数。

参数 

comm
指定异步通讯 (COM) 端口的序号。

baud=b 
指定以比特为单位的每秒传输速度。下表列出 b 的有效缩写及其相对速度:
11   110 baud 
15   150 baud 
30   300 baud 
60   600 baud
12   1200 baud 
24   2400 baud 
48   4800 baud
96   9600 baud 
19   19,200 baud

parity=p 
指定系统如何使用奇偶位检验传输错误。 p 值可以为下列之一:n (无)、
e (偶)、o (奇)、m (标记)或 s (空格)。默认值为 e 。
有些计算机不支持 m 和 s 值。  

data=d 
表示单个字符的位数。d 的有效值范围是 5 到 8 。默认值是 7 。
有些计算机不支持 5 和 6 。

stop=s 
定义字符结束的停止位数:1、1.5 或 2。如果波特率是 110,则默认值为 2 ;
 否则默认值为 1。有些计算机不支持 1.5 。

to=on|off
指定无限超时处理为 on 或 off 。 默认值为 off 。

xon=on|off
指定数据流控制的 xon 或 xoff 协议为 on 或 off 。

odsr=on|off
指定使用数据集准备 (DSR) 线路的输出握手信号为 on 或 off。

octs=on|off
指定使用清除发送 (CTS) 线路的输出握手信号为 on 或 off。

dtr=on|off
指定 DTR 线路为 on 或 off。

rts=on|off|hs|tg
RTS 线路设置为 on、off、handshake 或 toggle。

idsr=on|off
指定 DSR 线路上的信号检测为 on 或 off。
//*/

class CPortSetting  
{
public:
CPortSetting(HANDLE *pPort);
virtual ~CPortSetting();
int ApplySetting() ;
int BuildSetting( LPCTSTR lpMode ) ;
int DefineSetting() ;
    int SetBaudRate( ULONG rate );
    int SetParity( int parity );
    int SetWordLength( int word_length );
    int SetStopBits( int stop_bits );
    int SetDtr( int value );
    int SetRts( int value );
    int SetXonXoff( int value );
    int SetDtrDsr( int value );
    int SetRtsCts( int value );
int SetReadIntervalTimeout( DWORD interval ) ;
int SetReadTotalTimeout( DWORD dwMultiplier, DWORD dwConstant ) ;
int SetWriteTotalTimeout( DWORD dwMultimplier, DWORD dwConstant ) ;
int GetCurrDcb( LPDCB ) ;
int GetCurrTimeouts( LPCOMMTIMEOUTS ) ;
enum PARITY_TYPE{ 
PARITYTYPE_NO = 0,
PARITYTYPE_EVEN, 
PARITYTYPE_ODD, 
PARITYTYPE_MARK, 
PARITYTYPE_SPACE 
}; 
protected:
DCB m_dcb ;
HANDLE* m_phPort ;
CString m_szPortname ;
COMMTIMEOUTS m_timeouts ;
};
#endif // !defined(AFX_PORTSETTING_H__84846883_2F05_11D6_ACBC_00D0F808BF85__INCLUDED_)

PortSetting.cpp

// PortSetting.cpp: implementation of the CPortSetting class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PortSetting.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPortSetting::CPortSetting(HANDLE *pPort) 
: m_phPort( pPort )
{

}

CPortSetting::~CPortSetting()
{

}

int CPortSetting::ApplySetting()

ASSERT( INVALID_HANDLE_VALUE != *m_phPort ) ;
if( SetCommState( *m_phPort, &m_dcb ) ){
if( SetCommTimeouts( *m_phPort, &m_timeouts ) )
return -2 ;
}
else return 0 ;
return -3 ; 
}

int CPortSetting::SetBaudRate( ULONG rate )

m_dcb.BaudRate = rate ;
return 0 ; 
}

int CPortSetting::SetParity( int parity )

switch( parity )
{
    case PARITYTYPE_NO:
m_dcb.fParity = FALSE; 
m_dcb.Parity = NOPARITY;    
break;
case PARITYTYPE_EVEN:
m_dcb.fParity = TRUE;  
m_dcb.Parity = EVENPARITY;  
break;
case PARITYTYPE_ODD:
m_dcb.fParity = TRUE;  
m_dcb.Parity = ODDPARITY;   
break;
case PARITYTYPE_MARK:
m_dcb.fParity = TRUE;  
m_dcb.Parity = MARKPARITY;  
break;
case PARITYTYPE_SPACE :
m_dcb.fParity = TRUE;  
m_dcb.Parity = SPACEPARITY; 
break;
default:
return -1 ;
}
return 0 ; 
}

int CPortSetting::SetWordLength( int word_length )

if( word_length >8 || word_length < 5 )
return -1 ;
m_dcb.ByteSize = word_length  ;
  return 0 ; 
}

int CPortSetting::SetStopBits( int stop_bits )

    switch ( stop_bits ) {
    case 1: m_dcb.StopBits = ONESTOPBIT;  break;
    case 2: m_dcb.StopBits = TWOSTOPBITS; break;
default:
return -1 ;
}
  return 0 ; 
}

int CPortSetting::SetDtr( int value )

if ( value )
        m_dcb.fDtrControl = DTR_CONTROL_ENABLE;
    else
        m_dcb.fDtrControl = DTR_CONTROL_DISABLE;
return 0 ; 
}

int CPortSetting::SetRts( int value )

if ( value )
        m_dcb.fRtsControl = RTS_CONTROL_ENABLE;
    else
        m_dcb.fRtsControl = RTS_CONTROL_DISABLE;
return 0 ; 
}

int CPortSetting::SetXonXoff( int value )

if ( value ) {
m_dcb.fOutX = TRUE;
m_dcb.fInX = TRUE;
} else {
m_dcb.fOutX = FALSE;
m_dcb.fInX = FALSE;
}
return 0 ; 
}
int CPortSetting::SetDtrDsr( int value )

if ( value ) {
m_dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
            m_dcb.fOutxDsrFlow = TRUE;
    } else
        m_dcb.fOutxDsrFlow = FALSE;
return 0 ; 
}

int CPortSetting::SetRtsCts( int value )

if ( value ) {
m_dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
m_dcb.fOutxCtsFlow = TRUE;
} else
m_dcb.fOutxCtsFlow = FALSE;
return 0 ; 
}

int CPortSetting::GetCurrDcb( LPDCB lpdcb )
{
ASSERT( INVALID_HANDLE_VALUE != *m_phPort ) ;
ASSERT( NULL != lpdcb ) ; 
GetCommState( *m_phPort, lpdcb ) ;
return 0 ;
}

int CPortSetting::GetCurrTimeouts( LPCOMMTIMEOUTS lptimeouts )
{
ASSERT( INVALID_HANDLE_VALUE != *m_phPort ) ;
ASSERT( NULL != lptimeouts ) ;
GetCommTimeouts( *m_phPort, lptimeouts ) ;
return 0 ;
}
int CPortSetting::SetReadIntervalTimeout( DWORD interval )
{
m_timeouts.ReadIntervalTimeout = interval ;
return 0 ;
}
int CPortSetting::SetReadTotalTimeout( 
DWORD dwMultiplier, DWORD dwConstant )
{
m_timeouts.ReadTotalTimeoutConstant = dwConstant ;
m_timeouts.ReadTotalTimeoutMultiplier = dwMultiplier ;
return 0 ;
}
int CPortSetting::SetWriteTotalTimeout(
DWORD dwMultimplier, DWORD dwConstant )
{
m_timeouts.WriteTotalTimeoutMultiplier = dwMultimplier ;
m_timeouts.WriteTotalTimeoutConstant = dwConstant ;
return 0 ;
}
int CPortSetting::BuildSetting( LPCTSTR lpMode )
{
return 0 ;
}
int CPortSetting::DefineSetting()
{
GetCurrDcb( &m_dcb ) ;
GetCurrTimeouts( &m_timeouts ) ;
return 0 ;
}
sutra:怎么用的?注释几乎没有~~~内容好像也没贴完
// Rs232Win32.h: interface for the CRs232Win32 class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_RS232WIN32_H__F3A42FF9_29B8_11D6_ACA7_00D0F808BF85__INCLUDED_)
#define AFX_RS232WIN32_H__F3A42FF9_29B8_11D6_ACA7_00D0F808BF85__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afxtempl.h>
#include "mtdeque.h"
#include "PortSetting.h"
long GetCurrTime() ;

//本想做成DLL的,留下了太多的数据导出宏.后面改用源码,所以:~~
#ifdef AFX_API_EXPORT
#undef AFX_API_EXPORT
#define AFX_API_EXPORT
#endif

#define WM_RS232_RX (WM_USER+0x200)
#define WM_RS232_TX (WM_USER+0x201)

class CRs232Win32   
{
public:
AFX_API_EXPORT CRs232Win32();
virtual AFX_API_EXPORT ~CRs232Win32();
//hardware stream control
// hsc_TRS_CTS() ;
// hsc_DTR_DSR() ;
//software stream control
// ssc_XON_XOFF() ;

int AFX_API_EXPORT Open( LPCTSTR portname ) ;
int AFX_API_EXPORT Close( void ) ;
int AFX_API_EXPORT Reset( void ) ;

//write
int AFX_API_EXPORT Write( void* buf, int bitcount,
long millsec = -1 , void* term = NULL , int termcount = 0 ) ; 
//send
int AFX_API_EXPORT Read( void* buf, int bitcount, 
long millsec = -1 , void* term = NULL , int termcount = 0 ) ;

int AFX_API_EXPORT PurgeRead() ;
int AFX_API_EXPORT PurgeWrite() ;
int AFX_API_EXPORT TxNotify( ) ;
int AFX_API_EXPORT RxNotify( DWORD dwCount ) ;

void AFX_API_EXPORT SetNotifyWnd( HWND hWnd ) { m_hNotifyWnd = hWnd ; } 
public:
CPortSetting m_setting ;
TCHAR m_portname[MAX_PATH] ;
protected:
MTdeque m_TxBuf ;
MTdeque m_RxBuf ;
enum PortError{
PORTERROR_SUCCESS = 0 ,
PORTERROR_TIMEOUT = -100,
PORTERROR_PORTERROR = -200,
PORTERROR_PORTNOTOPEN = -300,
PORTERROR_UNKNOWN
} m_errPort ;
int Check_Status( void ) ;
int Clear_Errors( void ) ;
private:
static unsigned int __stdcall output_thread( void* portptr) ;
static unsigned int __stdcall input_thread(void* portptr) ;
    bool output_worker();


unsigned long m_nByteCount ;
    int m_iBreakDuration;        
bool m_bInputThreadReading;
HANDLE m_hPort ;
HWND m_hNotifyWnd ;
    HANDLE m_hKillWriteThreadEvent;
    HANDLE m_hKillReadThreadEvent;
    HANDLE m_hWriteRequestEvent;
    HANDLE m_hReadRequestEvent;
    HANDLE m_hBreakRequestEvent;
HANDLE m_hReadThreadSafeExitEvent ;
HANDLE m_hWriteThreadSafeExitEvent ;
};

extern CRs232Win32 g_rs232 ;
#endif // !defined(AFX_RS232WIN32_H__F3A42FF9_29B8_11D6_ACA7_00D0F808BF85__INCLUDED_)
// Rs232Win32.cpp: implementation of the CRs232Win32 class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Rs232Win32.h"
#include <process.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define MAX_RX_SIZE 1024
#define MAX_TX_SIZE 1024

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CRs232Win32 g_rs232 ;

CRs232Win32::CRs232Win32()
:m_RxBuf( MAX_RX_SIZE ),
 m_TxBuf( MAX_TX_SIZE ),
 m_setting(&m_hPort),
 m_errPort( PORTERROR_SUCCESS ),
 m_hPort(INVALID_HANDLE_VALUE)
{
m_hReadRequestEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ;
m_hWriteRequestEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ;
m_hBreakRequestEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ;

m_hKillReadThreadEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; 
m_hKillWriteThreadEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; 

m_hReadThreadSafeExitEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; 
m_hWriteThreadSafeExitEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; 

m_hNotifyWnd = NULL ;
}

CRs232Win32::~CRs232Win32()
{

}
int CRs232Win32::Read( void * buf, int bitcount, long millsec/* =-1 */ ,
  void* term/*= NULL */, int termcount/* =0 */ )
{
if( m_errPort )
return m_errPort ;
SetEvent(m_hReadRequestEvent) ;
return m_RxBuf.Extract( (char*)buf, bitcount ) ;
}

int CRs232Win32::Write( void * buf, int bitcount, long millsec/*=-1*/,
   void* term/* =NULL */, int termcount/* =0 */ )
{
if( m_errPort )
return m_errPort ;
m_TxBuf.Insert( (TCHAR*)buf, bitcount ) ;
m_TxBuf.Insert( (TCHAR*)buf, termcount ) ;
SetEvent(m_hWriteRequestEvent) ;
return 0 ;
}
int CRs232Win32::Open( LPCTSTR portname )
{
if( m_errPort )
return m_errPort ;
if( m_hPort != INVALID_HANDLE_VALUE && m_hPort != 0 )
Close() ;
m_hPort = CreateFile( portname,
                          GENERIC_READ | GENERIC_WRITE,
                          0,
                          0,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                          0 );
if( INVALID_HANDLE_VALUE == m_hPort )
{
DWORD lasterror = GetLastError() ;
// ::FormatMessage( 0, NULL, lasterror, 0, lpbuf, bufsize, NULL ) ; 
return PORTERROR_PORTNOTOPEN ;
}
m_setting.DefineSetting() ;
_tcscpy( m_portname, portname ) ;
_beginthreadex( NULL, 0, input_thread, this, 0, NULL ) ;
_beginthreadex( NULL, 0, output_thread, this, 0, NULL ) ;
return 0 ;
}
int CRs232Win32::Close()
{
if( INVALID_HANDLE_VALUE != m_hPort )
{
SetEvent( m_hKillReadThreadEvent ) ;
SetEvent( m_hKillWriteThreadEvent ) ;
_sleep(0);
::WaitForSingleObject( m_hReadThreadSafeExitEvent, 5000 ) ;
::WaitForSingleObject( m_hWriteThreadSafeExitEvent, 5000 ) ;
CloseHandle( m_hPort );
m_hPort = INVALID_HANDLE_VALUE ;
}
return 0 ;
}
int CRs232Win32::Reset()
{
return 0 ;
}
int CRs232Win32::PurgeRead()
{
    if ( m_errPort < PORTERROR_SUCCESS )
        return m_errPort ;
    m_RxBuf.Clear();
    PurgeComm( m_hPort, PURGE_RXCLEAR ); 
    if ( !m_bInputThreadReading )
        SetEvent( m_hReadRequestEvent );
    return PORTERROR_SUCCESS;
}

int CRs232Win32::PurgeWrite()
{
    if ( m_errPort < PORTERROR_SUCCESS )
        return m_errPort;
    m_TxBuf.Clear();
    PurgeComm( m_hPort, PURGE_TXCLEAR ); 
    return PORTERROR_SUCCESS;
}

int CRs232Win32::Check_Status()
{
return 0 ;
}
int CRs232Win32::Clear_Errors()
{
return 0 ;
}
CRs232Win32::RxNotify( DWORD dwCount )
{
if( ::IsWindow( m_hNotifyWnd ) )
::PostMessage( m_hNotifyWnd, WM_RS232_RX, m_RxBuf.SpaceUsed(), 0 ) ;
return 0 ;
}

CRs232Win32::TxNotify(  )
{
if( ::IsWindow( m_hNotifyWnd ) )
::PostMessage( m_hNotifyWnd, WM_RS232_TX, m_RxBuf.SpaceUsed() , 0 ) ;
return 0 ;
}













long GetCurrTime()
{
    return GetTickCount();
}

unsigned int CRs232Win32::input_thread( void* portptr )
{
    CRs232Win32 *port = (CRs232Win32 *) portptr;
    OVERLAPPED AsyncReadInfo = { 0 };
    OVERLAPPED AsyncStatusInfo = { 0 };
    AsyncReadInfo.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    AsyncStatusInfo.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    ASSERT( AsyncReadInfo.hEvent );
    ASSERT( AsyncStatusInfo.hEvent );
    DWORD dwCommEvent, dwBytesRead;
    bool waiting_on_status = false;
    port->m_bInputThreadReading = false;
    HANDLE handles[ 4 ] = { port->m_hKillReadThreadEvent,
                            AsyncReadInfo.hEvent,
                            AsyncStatusInfo.hEvent,
                            port->m_hReadRequestEvent };

    SetCommMask( port->m_hPort, 
                 EV_BREAK | EV_CTS  | EV_DSR   | EV_RXCHAR |
                 EV_ERR   | EV_RING | EV_RLSD   );
    for ( bool done = false ; !done ; ) {
        int bytes_to_read = 0;
        char read_buffer[ 256 ];
        dwBytesRead = 0 ;
//终止.
if( ::WaitForSingleObject(port->m_hKillReadThreadEvent, 0 ) == WAIT_OBJECT_0 ) 
break ;
        if ( !port->m_bInputThreadReading ) {
            bytes_to_read = port->m_RxBuf.SpaceFree();
            if ( bytes_to_read > 256 )
                bytes_to_read = 256;
            if ( bytes_to_read > 0 ) {
                if ( ReadFile( port->m_hPort, read_buffer, bytes_to_read, 
&dwBytesRead, &AsyncReadInfo ) ) {
                    if ( dwBytesRead ) {
                        port->m_RxBuf.Insert( read_buffer, dwBytesRead );
                        port->RxNotify( dwBytesRead );
                    }
else 
_sleep(0);
}
else {
//重叠操作正在进行ing...
port->m_bInputThreadReading = true ;
_sleep(0);
}
            }
else 
ResetEvent( AsyncReadInfo.hEvent ) ;//缓冲区满
        } 
        if ( !waiting_on_status  ) {
            if ( !WaitCommEvent( port->m_hPort, 
                                 &dwCommEvent, 
                                 &AsyncStatusInfo ) ) {
                waiting_on_status = true;
            } else { 
                port->Check_Status();
                port->Clear_Errors();
            }
        }
        if ( waiting_on_status && 
           ( port->m_bInputThreadReading || bytes_to_read == 0 ) ) {
            DWORD result = WaitForMultipleObjects( 4,
                                                   handles,
                                                   FALSE,
                                                   INFINITE );
            switch ( result ) {
            case WAIT_OBJECT_0 + 0 : // kill thread event
                done = true; 
                break;  
            case WAIT_OBJECT_0 + 1 : 
dwBytesRead = 0 ;
               if ( GetOverlappedResult( port->m_hPort, 
                                          &AsyncReadInfo, 
                                          &dwBytesRead, 
                                          FALSE ) ) 
                {      // read completed successfully
                    if ( dwBytesRead ) {
                        port->m_RxBuf.Insert( read_buffer, dwBytesRead );
                        port->RxNotify( dwBytesRead );
                    }
else {
_sleep(0) ;
}
                }
port->m_bInputThreadReading = false;
                break;
            case WAIT_OBJECT_0 + 2 : { /* Status event */ 
                DWORD dwOverlappedResult;
                if ( GetOverlappedResult( port->m_hPort, 
                                          &AsyncStatusInfo, 
                                          &dwOverlappedResult, 
                                          FALSE ) ) 
                {
                    port->Check_Status();
                    port->Clear_Errors();
                }
                waiting_on_status = false;
                break;
            }
            case WAIT_OBJECT_0 + 3 :
                break;
            default :
                ASSERT( false );
            }
        }
    }
    CloseHandle( AsyncReadInfo.hEvent );
    CloseHandle( AsyncStatusInfo.hEvent );
    port->m_bInputThreadReading = false;
SetEvent( port->m_hReadThreadSafeExitEvent ) ;
return 0 ;
}

unsigned int CRs232Win32::output_thread( void* portptr )
{
    CRs232Win32 *port = (CRs232Win32 *) portptr;
    HANDLE handles[ 3 ] = { port->m_hKillWriteThreadEvent,
                            port->m_hWriteRequestEvent,
                            port->m_hBreakRequestEvent };
    for ( bool done = false ; !done ; ) {
        switch ( WaitForMultipleObjects( 3, handles, FALSE, INFINITE ) ) {
        case 0 : //m_hKillOutputThreadEvent
            done = true; 
            break;
        case 1 : //m_hWriteRequestEvent
            done = port->output_worker();
            break;
        case 2 : //m_hBreakRequestEvent
            SetCommBreak( port->m_hPort );
            SleepEx( port->m_iBreakDuration, FALSE );
            ClearCommBreak( port->m_hPort );
            break;
        default :
            ASSERT( false );
            break;
        }
    }
SetEvent( port->m_hWriteThreadSafeExitEvent ) ;
return 0 ;
}
bool CRs232Win32::output_worker()
{
    OVERLAPPED AsyncWriteInfo = { 0 };
    AsyncWriteInfo.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    ASSERT( AsyncWriteInfo.hEvent );
    HANDLE handles[ 2 ] = { m_hKillWriteThreadEvent,
                            AsyncWriteInfo.hEvent };
    bool killed = false;
    for ( bool done = false ; ;  ) {
        char data[ 500 ];
        int count = m_TxBuf.Extract( data, 500 );
        if ( count == 0 ) {
            TxNotify();
            break;
        }
        
DWORD result_count;
        if ( !WriteFile( m_hPort, 
                         data, 
                         count, 
                         &result_count, 
                         &AsyncWriteInfo ) ) {
            if ( GetLastError() == ERROR_IO_PENDING ) {
                switch ( WaitForMultipleObjects( 2, handles, FALSE, INFINITE ) ) {
                case 0 : //m_hKillOutputThreadEvent
                    done = true; 
                    killed = true;
                    PurgeComm( m_hPort, PURGE_TXABORT ); 
                    break;
                case 1 : //AsyncWriteInfo.hEvent
                    if ( !GetOverlappedResult( m_hPort, 
                                               &AsyncWriteInfo, 
                                               &result_count, 
                                               FALSE ) ||
                          result_count != count ) {
                        if ( GetLastError() == ERROR_IO_PENDING )
                            Clear_Errors();
                        else
                        done = true;                        
                    } 
                    break;
                default :
                    ASSERT( false );
                }
            } else {
              done = true; 
            }
        } else {
            if ( result_count != count ) {
                done = true;
            }
        }
                         
    }
    CloseHandle( AsyncWriteInfo.hEvent );
    return killed;
}
我想要
zhanglf@hsit.com.cn 谢谢
auly403@163.com 谢谢
yszmax@163.com
3ks
173int@21cn.com

谢谢
lch22@21cn.com
谢谢
我也想要 zgj8128@163.com
我也要,谢谢楼主!
zym@cqhg.com.cn
搬个凳子坐下听讲!

顺便帮顶混分!

我正在急找这方面的东东,真的是急死了,能否借鉴大侠的,给我传一分啊,
谢主龍恩啊::::
lmy040308@163.com
我也看看,跟我的比较一下,好弥补自己的不足,谢谢!!

mashenka@263.net
看看
yinlsea@hotmail.com
thank
tjandy911@eyou.com
zjzhou@zhhz.org
学习先
那个程序好像是MS的例子吧?
我也写了一个,到时候你留下邮箱我发给你~ jiwawao@eyou.com
也发一个给我 谢谢
lyzbd@sina.com
mark
mm_wf@tom.com
 谢谢
jian_zhang03@163.com

Thank u 
发我一个。谢谢!ludexing@ieslab.com.cn
yyjmsht@yahoo.com.cn
谢谢哦!!
dixiatie@yahoo.com.cn
谢谢
jyl@runquan.com

谢谢
mei_bao2000@yahoo.com.cn

hckobe@yahoo.com.cn
收藏
我也要,谢谢楼主!
liudaqing9120@163.com
小弟来晚了,不知楼主能否给我一份:
agudunba@sohu.com
多谢!
mark

frpnet@gmail.com
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘