Option ExplicitPrivate Sub Command1_Click()
    On Error GoTo ErrHandle:
    If MSComm1.PortOpen = False Then
        Me.MSComm1.CommPort = CInt(Text2.Text)
        MSComm1.Settings = Text3.Text & "," & Text4.Text & "," & Text5.Text & "," & Text6.Text
        MSComm1.RThreshold = 1
        MSComm1.PortOpen = True
        Command1.Caption = "关闭端口"
    ElseIf MSComm1.PortOpen = True Then
        MSComm1.PortOpen = False
        Command1.Caption = "打开端口"
    End If
    Exit Sub
ErrHandle:
    MsgBox Err.Number & ":" & Err.Description
End SubPrivate Sub MSComm1_OnComm()
    MSComm1.InputMode = comInputModeBinary
    Select Case MSComm1.CommEvent
        Case comEvReceive
            Dim intLength As Integer
            intLength = 0
            Dim myArray() As Byte
            intLength = MSComm1.InBufferCount
            ReDim myArray(intLength)
            myArray = MSComm1.Input
            Text1.Text = ConvertToString(myArray)
            
    End Select
        
End SubPrivate Function ConvertToString(inputArray() As Byte) As String
    Dim strHex As String
    Dim strString As String
    Dim i As Integer
    For i = 0 To UBound(inputArray)
        strHex = strHex & CStr(Hex(inputArray(i))) & " "
        If inputArray(i) < 32 Or inputArray(i) > 128 Then
            strString = strString & Chr(63)
        Else
            strString = strString & Chr(inputArray(i))
        End If
    Next
    ConvertToString = strHex & vbCr & strString & vbCr
End Function这是我的测试代码,我发现单步调试时结果正常,直接运行就只接给我显示了strHex和strString最后两个字符,我读出来的数据是D ?,D是strHex的最后一位,?是strString的最后一位,但我单步调试是一样的.还有,我发现,如果我把断点放在ConvertoString这过程中会是这个结果,如果把断点放在OnComm事件里,结果是正常的,这是为什么啊?
我参考了串口调试工具的源码,它的确不会出问题,难道是它的单码长,我的代码短?

解决方案 »

  1.   

    现在看到问题,读一次卡,居然引发了四次的OnComm事件.
    测试数据:
     48 
    OK
     48 
     49 
     48 
     51 
     51 
    OK
     54 
     52 
     48 
    OK
     55 
     10 
     13 
    OK
      

  2.   

    这也是很明显的发送-接收”不同步的现象:
    因为发送与接收不同步,变成了你是“分段”接收到信息的,但你在程序中采用了:
    Text1.Text = ConvertToString(myArray),每次新接收到的数据把旧的数据都抹掉了。
    当你单步跟踪,或把断点设在OnComm事件里,结果是正常的,是因为程序的停顿能让PC把数据全部接收后再去处理。
    建议:Text1.Text = Text1.Text & ConvertToString(myArray)
      

  3.   

    好的,我试试.
    不过我现在做了这样的修改:
    Dim DataInput() As Byte
    Private Sub Command1_Click()
        On Error GoTo ErrHandle:
        If MSComm1.PortOpen = False Then
            Me.MSComm1.CommPort = CInt(Text2.Text)
            MSComm1.Settings = Text3.Text & "," & Text4.Text & "," & Text5.Text & "," & Text6.Text
            MSComm1.RThreshold = 1
            MSComm1.PortOpen = True
            Command1.Caption = "关闭端口"
        ElseIf MSComm1.PortOpen = True Then
            MSComm1.PortOpen = False
            Command1.Caption = "打开端口"
        End If
        Exit Sub
    ErrHandle:
        MsgBox Err.Number & ":" & Err.Description
    End SubPrivate Sub Command2_Click()
        ReDim DataInput(0)
    End SubPrivate Sub Form_Load()
        ReDim DataInput(0)
        MSComm1.InputLen = 0
    End SubPrivate Sub MSComm1_OnComm()
        'Delay 2
        MSComm1.InputMode = comInputModeBinary
        Select Case MSComm1.CommEvent
            Case comEvReceive
                Dim intLength As Integer
                intLength = 0
                Dim myArray() As Byte
                intLength = MSComm1.InBufferCount
                ReDim myArray(intLength)
                myArray = MSComm1.Input
                Call BufferInput(myArray, intLength)
                Text1.Text = ConvertToString()
        End Select
            
    End Sub
    Private Sub BufferInput(allArray() As Byte, DataLength As Integer)
        Dim i As Integer
        i = UBound(DataInput)
        ReDim Preserve DataInput(i + DataLength)
        Dim j As Integer
        For j = 0 To DataLength - 1
            DataInput(i + j) = allArray(j)
            Debug.Print Chr(allArray(j))
        Next
    End Sub
    Private Function ConvertToString() As String
        Dim strHex As String
        Dim strString As String
        Dim i As Integer
        For i = 0 To UBound(DataInput) - 1
            strHex = strHex & CStr(Hex(DataInput(i))) & " "
            If DataInput(i) < 32 Or DataInput(i) > 128 Then
                strString = strString & Chr(63)
            Else
                strString = strString & Chr(DataInput(i))
            End If
        Next
        ConvertToString = strHex & vbCr & strString & vbCr
    End Function我现在又用一个窗体级变量,保存接收的值,不过现在还有问题,我如何确定在正确接收完一次数据后,清掉窗体级变量DataInput呢?现在的是它永远都在不断的增长,我上边中放了一个按钮来清它的内容~因为无法确定什么时候才接收完一次刷卡的内容!
      

  4.   

    Wenking003(文君)
    你的方法可以了,呵呵,谢谢你.忙烦你再帮我看看用变量保存的方法.还有,就是用Text的话,我也是一样不知道什么时候应该清掉文本框内的值,你说对吗?如何确定输卡结束呢!我在想,我这个卡里,一共是12个字节,前10位是数字,可以正常的转化为ASCII码,进而转化为字符,后两位具体我还没有看,会是什么?有一位是停止位吗?
    我想应该是的,那请问,其它的一类,比如考勤机一类的,都会有像这张卡似的结束位吗?
      

  5.   


    Dim str As StringPrivate Sub Command1_Click()
        On Error GoTo ErrHandle:
        If MSComm1.PortOpen = False Then
            Me.MSComm1.CommPort = CInt(Text2.Text)
            MSComm1.Settings = Text3.Text & "," & Text4.Text & "," & Text5.Text & "," & Text6.Text
            MSComm1.RThreshold = 1
            MSComm1.PortOpen = True
            Command1.Caption = "关闭端口"
        ElseIf MSComm1.PortOpen = True Then
            MSComm1.PortOpen = False
            Command1.Caption = "打开端口"
        End If
        Exit Sub
    ErrHandle:
        MsgBox Err.Number & ":" & Err.Description
    End SubPrivate Sub MSComm1_OnComm()
        MSComm1.InputMode = comInputModeBinary
        Select Case MSComm1.CommEvent
            Case comEvReceive
                Dim intLength As Integer
                intLength = 0
                Dim myArray() As Byte
                intLength = MSComm1.InBufferCount
                ReDim myArray(intLength)
                myArray = MSComm1.Input
                
                str = str & ConvertToString(myArray)
                Debug.Print str
                If Right(str, 1) = "D" Then
                    Text1.Text = Left(str, 10)
                    str = ""
                End If
        End Select
            
    End SubPrivate Function ConvertToString(inputArray() As Byte) As String
        Dim strHex As String
        Dim strString As String
        Dim i As Integer
        For i = 0 To UBound(inputArray)
            'strHex = strHex & CStr(Hex(inputArray(i))) & " "
            If inputArray(i) < 32 Or inputArray(i) > 128 Then
                strString = strString & CStr(Hex(inputArray(i)))
            Else
                strString = strString & Chr(inputArray(i))
            End If
        Next
        ConvertToString = strString
    End Function哈哈.终于实现了.大侠帮我看看最后的这些代码,在实际应用中是否是正确的方法~我没有这方面的精验,比如说做考勤啊一类的东西的时候,大家都是如何用MSComm的?
      

  6.   

    留言收到
    关键是看你连接的外设定的通讯协议是怎么样的一般来说你买读卡器、考勤机的时候都可以通过代理商得到厂家的通讯协议资料如果没有,就只能自己慢慢摸索猜一下了
    还有,就是用Text的话,我也是一样不知道什么时候应该清掉文本框内的值,你说对吗?如何确定输卡结束呢!
    ===================
    要看你的读卡器每次刷卡的时候传过来的是否定长数据和有没有始、停位,如果都有则比较简单,设置好mscomm一般就可以了。
    但如果是不定长或没有始、停位则很麻烦,只能自己写代码进行判断(根据接收到的数据和卡的属性(例如卡号)进行分析说白了就是搞清楚它的通讯协议)不定长数据的接收参考:
    http://www.gjwtech.com/scomm/scvbprogramseveralques.htm
      

  7.   

    对于你的情况,由于两次读卡之间会有明显的时间段,因此你可以在MSComm1_OnComm()中进行一个时间的控制,如0.5秒内接收到的信息是属于最近一次刷卡的信息,超过这个时间段就属于其它的信息,这样你就可以清楚地知道你什么时候处理完一张卡,什么时候该清掉文本框内的值。
    至于是否有停止位什么的,各读写器都不同,这要靠你自己去摸索了。
      

  8.   

    请参考:
    http://community.csdn.net/Expert/topic/3387/3387736.xml?temp=.8557855我一般不喜欢用OnComm触发事件,除非万不得已!
      

  9.   

    现在已经得到数据了.而且因为它有结束位,我猜是结束位吧.我没有这个读卡器的任何资料.
    数据后面有两位,一个A,一个D,我就判断那个D吧.反正现在测试是正常的!大概知道是怎么回事了.现在也没有工作,更涉及不到这方面的项目,只是学习测试,现在收数据可以了,发数据没有这样的设备,暂时告一段落!:(谢谢各位!