我单片机的程序没问题,用串口调试工具通过的。我做的是单片机与VB界面的通讯,功能简单,双方握手后,VB发开始命令,单片机从串口发数据上来,一帧数据5字节。程序如下:
Private Sub Form_Load()MSComm1.CommPort = 1          '初始化串口通信
MSComm1.Settings = "9600,n,8,1"
MSComm1.InputMode = 1
MSComm1.PortOpen = True
MSComm1.InputLen = 5
MSComm1.OutBufferCount = 0
MSComm1.Output = Hex(21) + Chr$(13)
Do
      DoEvents
Loop Until MSComm1.OutBufferCount = 0
'MsgBox "ok"
MSComm1.Output = Hex(85)+ Chr$(13)
Do
      DoEvents
Loop Until MSComm1.OutBufferCount = 0
MSComm1.RThreshold = 5
MSComm1.InBufferCount = 0
End SubPrivate Sub MSComm1_OnComm()
Dim buffer() As Byte
ReDim buffer(5)Select Case MSComm1.CommEvent
    Case comEvReceive
    buffer = MSComm1.Input
    Text1.Text = Hex(buffer(0))
    Text2.Text = Hex(buffer(1))
    Text3.Text = Hex(buffer(2))
    Text4.Text = Hex(buffer(3))
    Text5.Text = Hex(buffer(4))
End Select
End Sub
结果显示的buffer都是单片机发上来的握手信号,那就是单片机没受到我得握手信号Hex(21) 和开始信号Hex(85),我分析是不是因为MSComm发送命令有固定格式,我编程基础不好,像程序中的Chr$(13),我看到大多程序都有,具体意思我不知道。这个问题卡了一周,请各位前辈指点一二,分数不成问题。(拱手)!

解决方案 »

  1.   

    MSComm发送命令是否有固定格式那,比如你说得换行符一定要加吗?单片机为何没响应VB的握手信号和开始信号那。还是我程序其他地方有问题。请各位帮我看看。
      

  2.   

    mscomm的工作机制是这样的:首先设置好参数 COM口1,”9600,N,8,1“和工作模式(是否有握手信号等),清空INPUT队列,打开串口,发握手信号,若INPUT队列不空,则接收,接收后MSCOMM自动清空INPUT队列,不需要用户参与清空,当两边都接收到握手信号后,开始发送或接收。我想你的问题在循环结束语句上,应在检测到INPUTLEN<>0时接收。
    INPUT队列是指对方输入到你的计算机的字串临时存放在MSCOMM中的队列中等待你接收
    OUTPUT队列是你向对方发送字串时你发送的字串在MSCOMM中存放的临时地点等待对方接收。
    或许我说得还不是十分明白,请看MSDN中关于MSCOMM控件的说明。
      

  3.   

    to: QLRC2XU(小菜鸟) 
    我在开始初始化时MSComm1.InputLen = 5,而且MSComm1.RThreshold = 5,表示input中接受5字节就进comEvReceive事件处理程序了。我现在的情况是可以收到单片机传上来的数据,不过是单片机的握手信号0x55,而不是我设定它传的帧格式(有帧头尾,数据,校验位)。所以我觉得问题还是处在我得发送命令上,
    MSComm1.Output = Hex(21) + Chr$(13)
    Do
          DoEvents
    Loop Until MSComm1.OutBufferCount = 0
    但我保证有发送出去的do loop语句,应该能发送出命令,但单片机怎么不接受那。
      

  4.   

    我没装MSDN,但看过网友提供的例子,关于什么term的。如果有关于MSComm的接受发送细节的资料麻烦各位发给我,分数没问题!
      

  5.   

    各位前辈路过请指点一二。昨天我又分析了一个问题,可能是handshaking我用默认的0,我既然有握手信号,就应该选1(xon/xoff),但试过后还是老问题。是不是我其它属性有没考虑到的,还请路过的前辈提些意见,本人编程经验不足,只做过单片机的c编程,难免犯低级错误,还请各位不吝赐教!!!
      

  6.   

    你的连接协议是什么?
    就是byte型的数组吗?hex()返回16进制,chr$()返回string,可能不行。
      

  7.   

    我把chr$()去掉还是同样结果,请问发送时有什么固定格式吗.我觉得需要的属性参数我都设置了呀,是不是还有漏掉的那?
      

  8.   

    你的参数设置应该够了,我的意思是:
    dim a(3) as byte
    a(0)=hex(21)
    a(1)=hex(13)
    a(2)=hex(85)
    a(3)=hex(13)
    mscomm1.output=a
    但数组a里面的设置是不是这样,我不清除,需要你单片机接收数据的协议。
      

  9.   

    to: wildleon(释尊空相) 
    是这样,我单片机程序一直向上位机发送循测信号0x55,如果从上位机接受0x15(既是hex(21))则单片机停止发送循测信号,当再从上位机接受开始命令0x51(既是hex(85))则开始向上位机传送数据.
    hex(13)是没用的,一开始没搞懂,呵呵.我用do loop循环保证上位机的命令发送呀,但结果显示竟然上位机接受的一帧数据都为0x55,就是说单片机没响应上位机命令.我就搞不懂拉,不知道如何下手,请大侠给些建议!
      

  10.   

    我感觉有以下几种可能,
    1、你的参数可能某个地方设置不对,比如校验位是8还是7,握手协议需要特殊设置吗?最好一一检查一下
    2、如果设置是正确的,那加入一下代码:
    dim stopdata as byte
    stopdata=&H15
    dim begindata as byte
    begindata=&H51
    if 需要单片机停止 then
    mscomm1.output=stopdata
    endif
    if 需要单片机工作 then
    mscomm1.output=begindata
    endif
    你先试试看,只要单片机有反应就行了,即使是错误的反映。
      

  11.   

    Private Sub Form_Load()
      MSComm1.CommPort = 1          '初始化串口通信
      MSComm1.Settings = "9600,n,8,1"
      MSComm1.InputMode = 1
      MSComm1.PortOpen = True
      MSComm1.InputLen = 5
      MSComm1.OutBufferCount = 0
      MSComm1.Output = 21
      MSComm1.Output = 85
      MSComm1.RThreshold = 5
      MSComm1.InBufferCount = 0
    End Sub
      

  12.   

    to: wildleon(释尊空相) 
    我设置应该都对的,我又检查一遍.你说得那段代码不会有作用吧,总之都是发命令,和我原来的代码没什么区别吧.我想请教一下有什么办法能知道单片机到底接受到我的上位机命令没有,比如用仿真器可以吗.还是我没理解你代码的意思,请给个详细思路.分数最后一定给,请大家帮帮忙!
      

  13.   

    我觉得是有区别的,你原来那一段代码发送的数据是不对的,你只要而且只能发送一个byte型的数据,所以你必须把发送程序换为:
    mscomm1.output=&H15
    gcj123(佛的光辉)也是这个意思。你最好试试看,因为单片机接收的数据多一个或是少一个都不行,如果他接收的数据不能解析,他会把接收到的数据全部舍弃,即使你数据前面都正确,而最后多了一个chr(13).
      

  14.   

    mscomm1.output=&H15,是传输16进制的格式吗,怎么运行的错误提示无效属性值.2位朋友能说清楚些吗.我后来把发送改为,MSComm1.Output = Hex(21) 还有MSComm1.Output = "21"结果如前没变.抱歉本人新手,这几天也一直在查资料,还请各位朋友帮到底,很感激!
      

  15.   

    MSComm1.Output = chrb(21)
    MSComm1.Output = chrb(85)
      

  16.   

    to: subzero(赘姆烂壳) 
    朋友,能解释清楚些吗.chrb什么意思.我明天到公司才能调试.希望明天能得到你的帮助.
      

  17.   

    Private Sub Form_Load()
      Dim bytData(0 To 1) As Byte
      MSComm1.CommPort = 1          '初始化串口通信
      MSComm1.Settings = "9600,n,8,1"
      MSComm1.InputMode = 1
      MSComm1.PortOpen = True
      MSComm1.InputLen = 5
      MSComm1.OutBufferCount = 0
      bytData(0) = 21
      bytData(1) = 85
      MSComm1.Output = bytData
      MSComm1.RThreshold = 5
      MSComm1.InBufferCount = 0
    End Sub
      

  18.   

    to:gcj123(佛的光辉) 以及各位朋友
    先谢谢各位朋友,我白天又查了些资料,没及时回复各位.我发现有几个地方没弄情,请各位帮我会诊.
    1.书上说output属性必须用byte数组变体型发送二进制数据所以我改动了一下,(和gcj123(佛的光辉) )朋友的思路一样.
    2.就是handshaking属性,关于握手我不熟悉.书上说握手是一种内部通信协议,保证不会由于缓冲区溢出而导致丢失数据.它通过将数据从硬件端口传输到接受缓冲区,使程序读到它.我的问题是我单片机发0x55循测命令,及VB的0x15和0x51命令,它们之间算是握手协议吗.如果算是,我得handshaking应该选xon/xoff拉.这个问题我一直很疑惑,看了很多书讲的内容大同小异,但我还是理解不了,不知道那位前辈能解答我.
    如下是我新改的程序:
    Private Sub Form_Load()
    Dim i As Integer
    Dim av(2) As Byteav(0) = 21
    av(1) = 85
    MSComm1.CommPort = 1          '初始化串口通信
    MSComm1.Settings = "9600,n,8,1"
    MSComm1.InputMode = 1
    MSComm1.PortOpen = True
    MSComm1.OutBufferCount = 0
    MSComm1.Output = av
    Text9.Text = MSComm1.OutBufferCount
    MSComm1.RThreshold = 5
    MSComm1.InputLen = 5
    MSComm1.InBufferCount = 0
    MSComm1.InBufferCount = 0
    End SubPrivate Sub MSComm1_OnComm()
    Dim buffer() As Byte
    ReDim buffer(5)
    Dim data As String
    Dim i As IntegerSelect Case MSComm1.CommEvent
        Case comEvReceive
        Text7.Text = Hex(InBufferCount)
        buffer = MSComm1.Input
        Text8.Text = Hex(InBufferCount)
        Text1.Text = Hex(buffer(0))
        Text2.Text = Hex(buffer(1))
        Text3.Text = Hex(buffer(2))
        Text4.Text = Hex(buffer(3))
        Text5.Text = Hex(buffer(4))
        Text6.Text = i
    End Select
    End Sub
    我加了10个文本框,以便测试.现在text1-5还是显示单片机的循测信号55,text6-9都是0.我发现不对呀.text6是0且不变说明只进了一次comEvReceive事件,应该是不停的接受数据i应该不断增加呀.text7是0也不对呀,那时InBufferCount应该是5才对呀.text9是0也不对呀,刚给output赋值完应该是2呀.
    我有这么多问题,希望各位能解答我其中某个问题也行,我真的挺感激帮我的这些朋友,分数我最后会自觉给的,倾家荡产在所不惜,呵呵.(拱手)
      

  19.   

    To 2034657(四火):
    你以前是学C的吧, 你需要把Dim av(2) As Byte改成Dim av(1) As Byte。在VB中,av(2)表示你定义的数组有av(0)、av(1)、av(2)三个数,这一点与C是不一样的。
    如果你的程序始终没有反应,可以把com的2、3口连起来,这样能实现自己发送,自己接收。
    你的程序中有一处我没看懂,你先发送21,单片机停止工作,紧接着你又有一个数据85到达单片机,于是单片机又开始工作。这是什么意思?
      

  20.   

    to:gcj123(佛的光辉) 
    对我是一直用c.可惜我的机子只有一个串口.是这样,我是简化程序以便说清,上位机发21是为了程序初始化时检测单片机的状态,如果单片机正常,则上位机可以根据操作人员意图运行.
      

  21.   

    to:wildleon(释尊空相) 
    呵呵,对不住wildleon(释尊空相)朋友,别介意.我明白你的意思.你是让我看串口工作是否正常对吗?我觉得应该没问题.因为我用串口调试工具运行正常的.我加了条语句Debug.Print buffer在MSComm1.Output = av后面,并设断点,但是buffer显示0,是不是说明上位机的命令根本就没发出去那.
    to:gcj123(佛的光辉) 
    我单片机发循测信号,上位机响应并操作这算握手协议吗?运行后,单片机向上位机传数据,数据是有格式的,这应该算是通讯协议吧.还请教个问题,握手协议算是通讯协议一部分吗?
      

  22.   


    gcj123(佛的光辉)的意思是指:你每发送一次数据就等于发送一个数据包,这个包的结构是什么,即一个包应该是多少个数据,第一个数据是什么,第二个是什么,发送用的是多少的波特率,多少校验位,是什么校验。这就是上下微机的通讯协议,你必须把协议搞得很清楚,否则单片机是不会有反映的,毕竟它不是人。在你的通讯协议中没有特殊的声明,是可以不管握手协议的,它有默认值。
    你的单片机一直没有反映吗?那可能问题还出在你没把通讯协议看透。
      

  23.   

    这个我当然都定义的,我一帧数据5字节,首字节,一个识别命令字节,2个数据字节,校验字节.至于settings我程序也定义的.我说过我一开始用串口调试工具时一切正常的.说明单片机程序和串口都没问题呀.
    另外我还想问-我加了条语句Debug.Print buffer在MSComm1.Output = av后面,并设断点,但是buffer显示空值,单步时看到变量outbuffercount始终是0,是不是说明上位机的命令根本就没发出去那.我在Text7.Text = Hex(InBufferCount)设断点后inbuffercount显示空值,但在Text5.Text = Hex(buffer(4))加一条MSComm1.inbuffercount=0,单步时看到inbuffercount始终在增加.这是为什么那,还是我这样观察就不对那.
      

  24.   

    诡异的问题,竟然会调试工具行而程序不行。应该是程序数据发送与接收不对。
    outbuffercount那句话不需要,因为outbuffercount和Inbuffercount只是监测输出(入)缓冲区中有多少个数据,mscomm1.output=av之后,数据可能已经发送出去了,所以你检测到的数据量是0。
    你用调试工具是发送的是那几个数,你的程序中就应该发送那几个数据。
    在oncomm事件中加入以下代码试试看:
    Private Sub MSComm1_OnComm()
    Dim recData As Variant
    Dim bRec() As Byte
    recData=MSComm1.Input
    ReDim bRec(UBound(recData)) As Byte
    For i = 0 To UBound(recData)
    bRec(i) = recData(i)
    Text1=Text1 & bRec(i)
    Next
    End Sub
    Text1中显示的就是你接收的信息。
      

  25.   

    to:wildleon(释尊空相) 
    你说得对,我现在就是程序数据发送与接收不对。我试了你的代码.它是5字节5字节的接受,但是一律是85,就是0x55,是单片机的循测信号.这是第一个要解决的问题.朋友能帮想些思路吗?
      

  26.   

    问题应该是,
    如果用二进制发送,应该定义一个动态字节数组,例如,dim bytOut() as byte,然后不用redim,直接给(0),(1)...扶植,然后将bytOut发送:MSComm.Output=bytOut,应该可以解决问题,试试看
      

  27.   

    Private Sub Form_Load()
    Dim i As Integer
    Dim av(9) As Byteav(0) = 21
    av(1) = 21
    av(2) = 21
    av(3) = 21
    av(4) = 21
    av(5) = 81
    av(6) = 81
    av(7) = 81
    av(8) = 81
    av(9) = 81
    MSComm1.CommPort = 1          '初始化串口通信
    MSComm1.Settings = "9600,n,8,1"
    MSComm1.InputMode = 1
    MSComm1.PortOpen = True
    If (MSComm1.PortOpen = True) Then
    Beep
    End If
    MSComm1.OutBufferCount = 0
    MSComm1.Output = avMSComm1.RThreshold = 5
    MSComm1.InputLen = 5
    MSComm1.InBufferCount = 0
    MSComm1.InBufferCount = 0
    End SubPrivate Sub MSComm1_OnComm()
    Dim recData As Variant
    Dim bRec() As Byte
    recData = MSComm1.Input
    ReDim bRec(UBound(recData)) As Byte
    For i = 0 To UBound(recData)
    bRec(i) = recData(i)
    Text1 = Text1 & bRec(i)
    Next
    End Sub
      

  28.   

    to:wildleon(释尊空相) 
    昨天和一位师兄解决了,原来是发送命令在传输到单片机途中可能出现问题,我上面程序把命令多发几次就正常接受数据拉.还是我经验不足,遇到问题不知道从何处下手,以后要向各位多多学习.
    我想问个问题,我重复发命令那十行有没有经典的代码代替,我这样处理总是不可靠的.
      

  29.   

    但我觉得这种方法不可靠,再说我到底重复发送几次才能保证命令送达单片机那,现场情况又不一样拉.所以有没有好的方法判别单片机受到命令没有,我目前的编程经验没想出太好的办法,各位有什么好办法吗?谢过!
    还有我设断点后在监视窗口中看到MSComm1中有2个input,一个在/object中,而且他们的数据不一致.哪位能帮我解释?