用API实现串口异步读写

VB的MSCOMM控件虽然很好用,但是在没有装VB的机器上用该控件总觉得有些累赘,网上的VB API代码大部分都基于是同步方式,处理复杂的通信模式不是太理想,所以用了一些时间,把VC项目中的异步串口读写代码翻译为VB格式。

在VB新建一个类,把下面的代码复制后即可使用

 

'*************************************************************************
'
**模 块 名:SerialPort
'
**说    明:YFsoft 版权所有2006 - 2007(C)
'
**创 建 人:叶帆
'
**日    期:2006-08-17 14:32:29
'
**修 改 人:
'
**日    期:
'
**描    述:串口异步读写(API)
'
**版    本:V1.0.0
'
*************************************************************************
Option Explicit

Private Type ComStat
    fCtsHold 
As Long
    fDsrHold 
As Long
    fRlsdHold 
As Long
    fXoffHold 
As Long
    fXoffSent 
As Long
    fEof 
As Long
    fTxim 
As Long
    fReserved 
As Long
    cbInQue 
As Long
    cbOutQue 
As Long
End Type

Private Type COMMTIMEOUTS
    ReadIntervalTimeout 
As Long
    ReadTotalTimeoutMultiplier 
As Long
    ReadTotalTimeoutConstant 
As Long
    WriteTotalTimeoutMultiplier 
As Long
    WriteTotalTimeoutConstant 
As Long
End Type

Private Type DCB
    DCBlength 
As Long
    BaudRate 
As Long
    
'DWORD DCBlength;      /* sizeof(DCB)                     */
    'DWORD BaudRate;       /* Baudrate at which running       */
    'DWORD fBinary: 1;     /* Binary Mode (skip EOF check)    */
    'DWORD fParity: 1;     /* Enable parity checking          */
    'DWORD fOutxCtsFlow:1; /* CTS handshaking on output       */
    'DWORD fOutxDsrFlow:1; /* DSR handshaking on output       */
    'DWORD fDtrControl:2;  /* DTR Flow control                */
    'DWORD fDsrSensitivity:1; /* DSR Sensitivity              */
    'DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
    'DWORD fOutX: 1;       /* Enable output X-ON/X-OFF        */
    'DWORD fInX: 1;        /* Enable input X-ON/X-OFF         */
    'DWORD fErrorChar: 1;  /* Enable Err Replacement          */
    'DWORD fNull: 1;       /* Enable Null stripping           */
    'DWORD fRtsControl:2;  /* Rts Flow control                */
    'DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
    'DWORD fDummy2:17;      /* Reserved                        */
    fBitFields As Long 'See Comments in Win32API.Txt
    wReserved As Integer
    XonLim 
As Integer
    XoffLim 
As Integer
    ByteSize 
As Byte
    Parity 
As Byte
    StopBits 
As Byte
    XonChar 
As Byte
    XoffChar 
As Byte
    ErrorChar 
As Byte
    EofChar 
As Byte
    EvtChar 
As Byte
    wReserved1 
As Integer 'Reserved; Do Not Use
End Type

Private Type OVERLAPPED
    Internal 
As Long
    InternalHigh 
As Long
    offset 
As Long
    OffsetHigh 
As Long
    hEvent 
As Long
End Type

Private Type SECURITY_ATTRIBUTES
    nLength 
As Long
    lpSecurityDescriptor 
As Long
    bInheritHandle 
As Long
End Type

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As LongAs Long
Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long 'OVERLAPPED
Private Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
Private Declare Function GetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long
Private Declare Function BuildCommDCB Lib "kernel32" Alias "BuildCommDCBA" (ByVal lpDef As String, lpDCB As DCB) As Long
Private Declare Function SetCommState Lib "kernel32" (ByVal hCommDev As Long, lpDCB As DCB) As Long
Private Declare Function GetCommState Lib "kernel32" (ByVal nCid As Long, lpDCB As DCB) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As StringByVal dwDesiredAccess As LongByVal dwShareMode As LongByVal lpSecurityAttributes As LongByVal dwCreationDisposition As LongByVal dwFlagsAndAttributes As LongByVal hTemplateFile As LongAs Long
Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As LongAs Long
Private Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA" (lpEventAttributes As SECURITY_ATTRIBUTES, ByVal bManualReset As LongByVal bInitialState As LongByVal lpName As StringAs Long
Private Declare Function SetCommMask Lib "kernel32" (ByVal hFile As LongByVal dwEvtMask As LongAs Long
Private Declare Function SetEvent Lib "kernel32" (ByVal hEvent As LongAs Long
Private Declare Function PurgeComm Lib "kernel32" (ByVal hFile As LongByVal dwFlags As LongAs Long
Private Declare Function ClearCommError Lib "kernel32" (ByVal hFile As Long, lpErrors As Long, lpStat As ComStat) As Long
Private Declare Function GetOverlappedResult Lib "kernel32" (ByVal hFile As Long, lpOverlapped As OVERLAPPED, lpNumberOfBytesTransferred As LongByVal bWait As LongAs Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As LongByVal dwMilliseconds As LongAs Long
Private Declare Function SetupComm Lib "kernel32" (ByVal hFile As LongByVal dwInQueue As LongByVal dwOutQueue As LongAs Long

Private Const GENERIC_WRITE = &H40000000
Private Const GENERIC_READ = &H80000000
Private Const OPEN_EXISTING = 3
Private Const FILE_ATTRIBUTE_NORMAL = &H80
Private Const FILE_FLAG_OVERLAPPED = &H40000000
Private Const DTR_CONTROL_DISABLE = &H0
Private Const RTS_CONTROL_ENABLE = &H1
Private Const PURGE_RXABORT = &H2
Private Const PURGE_RXCLEAR = &H8
Private Const PURGE_TXABORT = &H1
Private Const PURGE_TXCLEAR = &H4
Private Const ERROR_IO_PENDING = 997
Private Const STATUS_WAIT_0 = &H0
Private Const WAIT_OBJECT_0 = (STATUS_WAIT_0 + 0)
Private Const WAIT_TIMEOUT = 258&

Private m_Handle As Long
Private m_OverlappedRead As OVERLAPPED
Private m_OverlappedWrite As OVERLAPPED

'*************************************************************************
'
**函 数 名:OpenPort
'
**输    入:ComNumber(Long)     - 串口号
'
**        :Comsettings(String) - 配置信息
'
**输    出:(Long) - 0 成功 非 0 失败
'
**功能描述:打开串口
'
**全局变量:
'
**调用模块:
'
**作    者:叶帆
'
**日    期:2006-08-17 14:40:14
'
**修 改 人:
'
**日    期:
'
**版    本:V1.0.0
'
*************************************************************************
Public Function OpenPort(ComNumber As Long, Comsettings As StringOptional lngInSize As Long = 1024Optional lngOutSize As Long = 512As Long
    
On Error GoTo handelinitcom
    
Dim retval As Long
    
Dim CtimeOut As COMMTIMEOUTS, dcbs As DCB
    
Dim strCOM As String, strConfig As String

    strCOM 
= "/.COM" & Format(ComNumber, "0")
    m_Handle 
= CreateFile(strCOM, GENERIC_READ Or GENERIC_WRITE, 00&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL Or FILE_FLAG_OVERLAPPED, 0)
    
If m_Handle = -1 Then
        OpenPort 
= -1
        
Exit Function
    
End If

    
'设置dcb块
    dcbs.DCBlength = Len(dcbs)                           '长度
    Call GetCommState(m_Handle, dcbs)

    
'波特率,奇偶校验,数据位,停止位  如:9600,n,8,1
    strConfig = "COM" & Format(ComNumber, "0"& ":" & Comsettings
    
Call BuildCommDCB(strConfig, dcbs)

    
'------------------------------
    '    dcbs.fBinary = 1                          '二进制方式
    '    dcbs.fOutxCtsFlow = 0                     '不用CTS检测发送流控制
    '    dcbs.fOutxDsrFlow = 0                     '不用DSR检测发送流控制
    '    dcbs.fDtrControl = DTR_CONTROL_DISABLE    '禁止DTR流量控制
    '    dcbs.fDsrSensitivity = 0                  '对DTR信号线不敏感
    '    dcbs.fTXContinueOnXoff = 1                '检测接收缓冲区
    '    dcbs.fOutX = 0                            '不做发送字符控制
    '    dcbs.fInX = 0                             '不做接收控制
    '    dcbs.fErrorChar = 0                       '是否用指定字符替换校验错的字符
    '    dcbs.fNull = 0                            '保留NULL字符
    '    dcbs.fRtsControl = RTS_CONTROL_ENABLE     '允许RTS流量控制
    '    dcbs.fAbortOnError = 0                    '发送错误后,继续进行下面的读写操作
    '    dcbs.fDummy2 = 0                          '保留
    dcbs.fBitFields = 1 * 2 ^ 0 Or DTR_CONTROL_DISABLE * 2 ^ 4 Or 1 * 2 ^ 7 Or RTS_CONTROL_ENABLE * 2 ^ 12

    dcbs.wReserved 
= 0                        '没有使用,必须为0
    dcbs.XonLim = 0                           '指定在XOFF字符发送之前接收到缓冲区中可允许的最小字节数
    dcbs.XoffLim = 0                          '指定在XOFF字符发送之前缓冲区中可允许的最小可用字节数
    dcbs.XonChar = 0                          '发送和接收的XON字符
    dcbs.XoffChar = 0                         '发送和接收的XOFF字符
    dcbs.ErrorChar = 0                        '代替接收到奇偶校验错误的字符
    dcbs.EofChar = 0                          '用来表示数据的结束
    dcbs.EvtChar = 0                          '事件字符,接收到此字符时,会产生一个事件
    'dcbs.wReserved1 = 0                      '没有使用
    'dcbs.BaudRate =9600                      '波特率
    'dcbs.Parity=0                            '奇偶校验
    'dcbs.ByteSize=8                          '数据位
    'dcbs.StopBits=0                          '停止位
    '------------------------------

    
If dcbs.Parity = 0 Then                   ' 0-4=None,Odd,Even,Mark,Space
        dcbs.fBitFields = dcbs.fBitFields And &HFFFD     'dcbs.fParity = 0                      '奇偶校验无效
    Else
        dcbs.fBitFields 
= dcbs.fBitFields Or &H2         'dcbs.fParity = 1                      '奇偶校验有效
    End If

    
'超时设置
    CtimeOut.ReadIntervalTimeout = 20                  '0
    CtimeOut.ReadTotalTimeoutConstant = 1              '2500
    CtimeOut.ReadTotalTimeoutMultiplier = 1            '0
    CtimeOut.WriteTotalTimeoutConstant = 10            '2500
    CtimeOut.WriteTotalTimeoutMultiplier = 1           '0
    
    retval 
= SetCommTimeouts(m_Handle, CtimeOut)

    
If retval = -1 Then
        retval 
= GetLastError()
        OpenPort 
= retval
        retval 
= CloseHandle(m_Handle)
        
Exit Function
    
End If

    
'获取信号句柄
    Dim lpEventAttributes1 As SECURITY_ATTRIBUTES
    
Dim lpEventAttributes2 As SECURITY_ATTRIBUTES

    m_OverlappedRead.hEvent 
= CreateEvent(lpEventAttributes1, 100)
    m_OverlappedWrite.hEvent 
= CreateEvent(lpEventAttributes2, 100)

    
'判断设置参数是否成功   设置输入和输出缓冲区是否成功
    If SetCommState(m_Handle, dcbs) = -1 Or SetupComm(m_Handle, lngInSize, lngOutSize) = -1 Or m_OverlappedRead.hEvent = 0 Or m_OverlappedWrite.hEvent = 0 Then
        retval 
= GetLastError()
        OpenPort 
= retval
        
If (m_OverlappedRead.hEvent <> 0Then CloseHandle (m_OverlappedRead.hEvent)
        
If (m_OverlappedWrite.hEvent <> 0Then CloseHandle (m_OverlappedWrite.hEvent)
        
Call CloseHandle(m_Handle)
        m_Handle 
= 0
        
Exit Function
    
End If

    OpenPort 
= 0
    
Exit Function
handelinitcom:
    
Call CloseHandle(m_Handle)
    m_Handle 
= 0
    OpenPort 
= -2
    
Exit Function
End Function

'*************************************************************************
'
**函 数 名:ClosePort
'
**输    入:无
'
**输    出:(Long) - 0 成功 -1 失败
'
**功能描述:关闭串口
'
**全局变量:
'
**调用模块:
'
**作    者:叶帆
'
**日    期:2006-08-17 14:56:13
'
**修 改 人:
'
**日    期:
'
**版    本:V1.0.0
'
*************************************************************************
Public Function ClosePort() As Long
    
If (m_Handle = 0Then
        ClosePort 
= 1
        
Exit Function
    
End If

    
Call SetCommMask(m_Handle, 0)
    
Call SetEvent(m_OverlappedRead.hEvent)
    
Call SetEvent(m_OverlappedWrite.hEvent)

    
If (m_OverlappedRead.hEvent <> 0Then CloseHandle (m_OverlappedRead.hEvent)
    
If (m_OverlappedWrite.hEvent <> 0Then CloseHandle (m_OverlappedWrite.hEvent)

    
If CloseHandle(m_Handle) <> 0 Then
        ClosePort 
= 0
    
Else
        ClosePort 
= -1
    
End If

    m_Handle 
= 0
End Function

'*************************************************************************
'
**函 数 名:ClearInBuf
'
**输    入:无
'
**输    出:无
'
**功能描述:清空输入缓冲区
'
**全局变量:
'
**调用模块:
'
**作    者:叶帆
'
**日    期:2006-08-17 14:57:26
'
**修 改 人:
'
**日    期:
'
**版    本:V1.0.0
'
*************************************************************************
Public Function ClearInBuf() As Long
    
If (m_Handle = 0Then
        ClearInBuf 
= 1
        
Exit Function
    
End If
    
Call PurgeComm(m_Handle, PURGE_RXABORT Or PURGE_RXCLEAR)
    ClearInBuf 
= 0
End Function

'*************************************************************************
'
**函 数 名:ClearOutBuf
'
**输    入:无
'
**输    出:(Long) -
'
**功能描述:清空输出缓冲区
'
**全局变量:
'
**调用模块:
'
**作    者:叶帆
'
**日    期:2006-08-17 15:40:38
'
**修 改 人:
'
**日    期:
'
**版    本:V1.0.0
'
*************************************************************************
Public Function ClearOutBuf() As Long
    
If (m_Handle = 0Then
        ClearOutBuf 
= 1
        
Exit Function
    
End If
    
Call PurgeComm(m_Handle, PURGE_TXABORT Or PURGE_TXCLEAR)
    ClearOutBuf 
= 0
End Function

'*************************************************************************
'
**函 数 名:SendData
'
**输    入:bytBuffer()(Byte) - 数据
'
**        :lngSize(Long)     - 数据长度
'
**输    出:(Long) -
'
**功能描述:发送数据
'
**全局变量:
'
**调用模块:
'
**作    者:叶帆
'
**日    期:2006-08-17 15:43:42
'
**修 改 人:
'
**日    期:
'
**版    本:V1.0.0
'
*************************************************************************
Public Function SendData(bytBuffer() As Byte, lngSize As LongAs Long
    
On Error GoTo ToExit '打开错误陷阱
    '------------------------------------------------
    If (m_Handle = 0Then
        SendData 
= 1
        
Exit Function
    
End If

    
Dim dwBytesWritten As Long
    
Dim bWriteStat As Long
    
Dim ComStats As ComStat
    
Dim dwErrorFlags As Long

    dwBytesWritten 
= lngSize

    
Call ClearCommError(m_Handle, dwErrorFlags, ComStats)
    bWriteStat 
= WriteFile(m_Handle, bytBuffer(0), lngSize, dwBytesWritten, m_OverlappedWrite)

    
If bWriteStat = 0 Then
        
If GetLastError() = ERROR_IO_PENDING Then
            
Call GetOverlappedResult(m_Handle, m_OverlappedWrite, dwBytesWritten, 1)                   '等待直到发送完毕
        End If
    
Else
        dwBytesWritten 
= 0
    
End If

    SendData 
= dwBytesWritten
    
'------------------------------------------------
    Exit Function
    
'----------------
ToExit:
    SendData 
= -1
End Function

'*************************************************************************
'
**函 数 名:ReadData
'
**输    入:bytBuffer()(Byte) - 数据
'
**        :lngSize(Long)     - 数据长度
'
**输    出:(Long) -
'
**功能描述:读取数据
'
**全局变量:
'
**调用模块:
'
**作    者:叶帆
'
**日    期:2006-08-17 16:04:38
'
**修 改 人:
'
**日    期:
'
**版    本:V1.0.0
'
*************************************************************************
Public Function ReadData(bytBuffer() As Byte, lngSize As LongOptional Overtime As Long = 3000As Long
    
On Error GoTo ToExit '打开错误陷阱
    '------------------------------------------------
    If (m_Handle = 0Then
        ReadData 
= 1
        
Exit Function
    
End If

    
Dim lngBytesRead As Long
    
Dim fReadStat As Long
    
Dim dwRes  As Long

    lngBytesRead 
= lngSize

    
'读数据
    fReadStat = ReadFile(m_Handle, bytBuffer(0), lngSize, lngBytesRead, m_OverlappedRead)
    
If fReadStat = 0 Then
        
If GetLastError() = ERROR_IO_PENDING Then                           '重叠 I/O 操作在进行中
            dwRes = WaitForSingleObject(m_OverlappedRead.hEvent, Overtime)  '等待,直到超时
            Select Case dwRes
            
Case WAIT_OBJECT_0:   '读完成
                If GetOverlappedResult(m_Handle, m_OverlappedRead, lngBytesRead, 0= 0 Then
                    
'错误
                    ReadData = -2
                    
Exit Function
                
End If
            
Case WAIT_TIMEOUT:    '超时
                ReadData = -1
                
Exit Function
            
Case Else:                  'WaitForSingleObject 错误
            End Select
        
End If
    
End If
    ReadData 
= lngBytesRead
    
'------------------------------------------------
    Exit Function
    
'----------------
ToExit:
    ReadData 
= -1
End Function

'*************************************************************************
'
**函 数 名:Class_Terminate
'
**输    入:无
'
**输    出:无
'
**功能描述:
'
**全局变量:
'
**调用模块:
'
**作    者:叶帆
'
**日    期:2006-08-17 16:36:21
'
**修 改 人:
'
**日    期:
'
**版    本:V1.0.0
'
*************************************************************************
Private Sub Class_Terminate()
    
Call ClosePort
End Sub
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值