在VB中用MSComm通过RS232与MCS51通信,速率大于19200时都没有问题,但一降下来就不行了,问题可能出在哪?有时候需要发送两次51才能收到数据,不知这又可能是什么原因?请高手指教,给分好说。MSComm中的Settings里的M,S,N到底区别在什么地方?是不是收到数据后一定会进行校验(除N外)。也请指教

解决方案 »

  1.   

    但二者的波特率设的是一样的呀,它们在57600的时候工作完全正常,只是把它们的波特率都降到9600时就不行了。这时候Button按两下才能发出数据,也不知是什么原因。请指教
      

  2.   

    N—无校验,E—偶校验,O—奇校验,M—符号校验,S—空格校验,确实如此
      

  3.   

    大体程序如下,设计时约定:先发送&HAA再发送所选择的单片机号,然后等待所选的单片机将
    单片机号返回,如一致然后发送&H00请求所要接收的数据长度,接收完数据长度后开始接收数
    据,数据接收完毕后做校验,成功则发送&H02结束一次过程。程序中未对单片机号做判断。
    Private Sub cmdStart_Click()
        Dim byOutput(1 To 1) As Byte
    MSComm1.Settings = "57600,m,8,1"
    byOutput(1) = &HAA
    MSComm1.Output = byOutput    '发送字节&HAA给单片机让片机做好准备
    MSComm1.RThreshold = 1       '设置接收阀值
    iProgramNum = 1              '令iProgramNum=1,执行第一段程序
    'MSComm1.Settings = "57600,m,8,1"
    byOutput(1) = val(txtChipSelect.Text)   '选择单片机
    MSComm1.Output = byOutput    '发送单片机号给单片机让选择单片机做好准备
    MSComm1.Settings = "57600,n,8,1"
    End SubPrivate Sub Form_Load()
    MSComm1.PortOpen = True       '部分参数直接在控件属情列表里改了
    MSComm1.Settings = "57600,m,8,1"
    iProgramNum = 0
    End SubPrivate Sub MSComm1_OnComm()
    Select Case MSComm1.CommEvent
    Case comEvReceive
                Dim byInput() As Byte
                Dim byOutput(1 To 1) As Byte
                Dim byArray(1 To 200) As Byte
                Dim iTemp As Integer
                Dim iPos As Integer
                Dim byTemp As Byte
       
         If iProgramNum = 1 Then   'Case
         '接收芯片型号判断是否正确选片,如正确则发送00请求数据长度并将iProgramNum改为2
                  MSComm1.Settings = "57600,n,8,1"
                  byInput = MSComm1.Input            '则发送00请求数据长度并将iProgramNum改为2
                  For iTemp = LBound(byInput) To UBound(byInput)
                       byTemp = byInput(iTemp)        'byTemp中放的为单片机的编号
                  Next iTemp
                  txtShow.Text = "当前单片机为:" & Val(byTemp) & Space(1)
                  iProgramNum = 2                    '注意这一点,执行这些语句后准备开始接收数据块长度
                  byOutput(1) = &H0
                  MSComm1.Output = byOutput          '发送&H00表示请求数据长度
                          
         ElseIf iProgramNum = 2 Then   'Case
         '接收数据长度并赋给iDataLength,然后发送&H01表示请求发送数据并将iProgramNum改为3
                  MSComm1.Settings = "57600,n,8,1"
                  byInput = MSComm1.Input           '再发01表示准备接收数据,然后转到iProgramNum=03
                  For iTemp = LBound(byInput) To UBound(byInput)
                       byTemp = byInput(iTemp)
                       iDataLength = byInput(iTemp)
                  Next iTemp                      '可试一下上一句是否可以改为byTemp=byInput(iTemp)
                  txtShow.Text = txtShow.Text & "数据长:" & iDataLength & Space(1)
                  iProgramNum = 3
                  byOutput(1) = &H1
                  MSComm1.Output = byOutput       '发送&H01表示准备接收数据
      
         ElseIf iProgramNum = 3 Then    'Case
         '读入数据及校验位,校验并显示,然后发送&H02改变Settings使程序可以进入下一个数据传送过程
                  If MSComm1.InBufferCount >= 23 Then
                     iPos = 1
                     MSComm1.Settings = "57600,n,8,1"
                     byInput = MSComm1.Input       '这句容易forget,此时程序常常会提示"下标越界"
                     For iTemp = LBound(byInput) To UBound(byInput)  'byArray(iDataLength+1)放的为校验码
                          byArray(iPos) = byInput(iTemp)
                          iPos = iPos + 1
                          txtShow.Text = txtShow.Text & Chr(byInput(iTemp))
                     Next iTemp
                     byOutput(1) = &H2
                     MSComm1.Output = byOutput
                                      '做校验
                     byTemp = 0
                     For iTemp = 1 To iDataLength
                         byTemp = (Val(byTemp) + byArray(iTemp)) And &HFF
                     Next iTemp
                     If byTemp = byArray(iDataLength + 1) Then
                         txtShow.Text = txtShow.Text & "校验位正确" & Space(1) & byTemp
                     End If
                     
                  Else:
                      'varTemp = MsgBox("输入数据未完整,等待...", vbInformation, "system info")   'test
                  End If
                  'iTemp = MsgBox("End of iProgramNum=3", vbInformation, "程序测试提示")   'for test only
        
         Else: iTemp = MsgBox("iProgramNum=" & iProgramNum & "未定义", vbInformation, "程序测试提示")
         End If    'Case
    End Select
    End Sub
      

  4.   

    如果将cmdStart_Click中的MSComm1.Settings = "57600,n,8,1"改为MSComm1.Settings = "57600,m,8,1"并且后面不再对Settings改变,则iProgramNum=1部分执行,但iProgramNum=2和3部分都未执行。把57600降为9600以后iProgramNum=2和3部分也不执行,且数据长度也不对。所以想知道Settings中的校验位对数据接收的影响。
      

  5.   

    因为涉及多个单片机,所以开始的时候必须在校验位上放1,后来的几步须为0,所以在最开始的时候用M,后来用S,结果测试的时候数据长度不正确,iProgramNum=2和3的部分也没执行,不知为什么。是不是不论Settings中校验位上放什么MSComm接收数据的时候都会做校验?请指教。
      

  6.   

    应该是先设置Setting属性,再打开端口吧!建议在设置Setting属性前,先用mscomm.Portopen=false 关闭端口,设置完了再用mscomm.portopen=true打开
      

  7.   

    另外,mscomm的校验是奇偶校验,效果不好,建议用CRC还有关于单片机的片选问题,可以在帧结构中进行控制
      

  8.   

    是不是不论settings设为什么mscomm接收数据时都进行奇偶校验?CRC校验怎么做?想请教一下!
    单片机的片选,可以说得更详细一些么?非常感谢。
      

  9.   

    降速问题已解决,想听听CityBird的一些建议。谢谢。
      

  10.   

    在帧结构增加几个字节的数据或选择特殊的位用来标志单片机的ID,然后将整个帧广播给所有的单片机,单片机接收完数据帧后,先取出帧中标志单片机ID的数据与自生的数据比较,判断这个帧是不是给自己的,然后实行相应的操作。CRC检验的资料网上多的是,google一下就有了。