我单片机的程序没问题,用串口调试工具通过的。我做的是单片机与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),我看到大多程序都有,具体意思我不知道。这个问题卡了一周,请各位前辈指点一二,分数不成问题。(拱手)!
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),我看到大多程序都有,具体意思我不知道。这个问题卡了一周,请各位前辈指点一二,分数不成问题。(拱手)!
INPUT队列是指对方输入到你的计算机的字串临时存放在MSCOMM中的队列中等待你接收
OUTPUT队列是你向对方发送字串时你发送的字串在MSCOMM中存放的临时地点等待对方接收。
或许我说得还不是十分明白,请看MSDN中关于MSCOMM控件的说明。
我在开始初始化时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语句,应该能发送出命令,但单片机怎么不接受那。
就是byte型的数组吗?hex()返回16进制,chr$()返回string,可能不行。
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里面的设置是不是这样,我不清除,需要你单片机接收数据的协议。
是这样,我单片机程序一直向上位机发送循测信号0x55,如果从上位机接受0x15(既是hex(21))则单片机停止发送循测信号,当再从上位机接受开始命令0x51(既是hex(85))则开始向上位机传送数据.
hex(13)是没用的,一开始没搞懂,呵呵.我用do loop循环保证上位机的命令发送呀,但结果显示竟然上位机接受的一帧数据都为0x55,就是说单片机没响应上位机命令.我就搞不懂拉,不知道如何下手,请大侠给些建议!
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
你先试试看,只要单片机有反应就行了,即使是错误的反映。
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
我设置应该都对的,我又检查一遍.你说得那段代码不会有作用吧,总之都是发命令,和我原来的代码没什么区别吧.我想请教一下有什么办法能知道单片机到底接受到我的上位机命令没有,比如用仿真器可以吗.还是我没理解你代码的意思,请给个详细思路.分数最后一定给,请大家帮帮忙!
mscomm1.output=&H15
gcj123(佛的光辉)也是这个意思。你最好试试看,因为单片机接收的数据多一个或是少一个都不行,如果他接收的数据不能解析,他会把接收到的数据全部舍弃,即使你数据前面都正确,而最后多了一个chr(13).
MSComm1.Output = chrb(85)
朋友,能解释清楚些吗.chrb什么意思.我明天到公司才能调试.希望明天能得到你的帮助.
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
先谢谢各位朋友,我白天又查了些资料,没及时回复各位.我发现有几个地方没弄情,请各位帮我会诊.
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呀.
我有这么多问题,希望各位能解答我其中某个问题也行,我真的挺感激帮我的这些朋友,分数我最后会自觉给的,倾家荡产在所不惜,呵呵.(拱手)
你以前是学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到达单片机,于是单片机又开始工作。这是什么意思?
对我是一直用c.可惜我的机子只有一个串口.是这样,我是简化程序以便说清,上位机发21是为了程序初始化时检测单片机的状态,如果单片机正常,则上位机可以根据操作人员意图运行.
呵呵,对不住wildleon(释尊空相)朋友,别介意.我明白你的意思.你是让我看串口工作是否正常对吗?我觉得应该没问题.因为我用串口调试工具运行正常的.我加了条语句Debug.Print buffer在MSComm1.Output = av后面,并设断点,但是buffer显示0,是不是说明上位机的命令根本就没发出去那.
to:gcj123(佛的光辉)
我单片机发循测信号,上位机响应并操作这算握手协议吗?运行后,单片机向上位机传数据,数据是有格式的,这应该算是通讯协议吧.还请教个问题,握手协议算是通讯协议一部分吗?
gcj123(佛的光辉)的意思是指:你每发送一次数据就等于发送一个数据包,这个包的结构是什么,即一个包应该是多少个数据,第一个数据是什么,第二个是什么,发送用的是多少的波特率,多少校验位,是什么校验。这就是上下微机的通讯协议,你必须把协议搞得很清楚,否则单片机是不会有反映的,毕竟它不是人。在你的通讯协议中没有特殊的声明,是可以不管握手协议的,它有默认值。
你的单片机一直没有反映吗?那可能问题还出在你没把通讯协议看透。
另外我还想问-我加了条语句Debug.Print buffer在MSComm1.Output = av后面,并设断点,但是buffer显示空值,单步时看到变量outbuffercount始终是0,是不是说明上位机的命令根本就没发出去那.我在Text7.Text = Hex(InBufferCount)设断点后inbuffercount显示空值,但在Text5.Text = Hex(buffer(4))加一条MSComm1.inbuffercount=0,单步时看到inbuffercount始终在增加.这是为什么那,还是我这样观察就不对那.
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中显示的就是你接收的信息。
你说得对,我现在就是程序数据发送与接收不对。我试了你的代码.它是5字节5字节的接受,但是一律是85,就是0x55,是单片机的循测信号.这是第一个要解决的问题.朋友能帮想些思路吗?
如果用二进制发送,应该定义一个动态字节数组,例如,dim bytOut() as byte,然后不用redim,直接给(0),(1)...扶植,然后将bytOut发送:MSComm.Output=bytOut,应该可以解决问题,试试看
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
昨天和一位师兄解决了,原来是发送命令在传输到单片机途中可能出现问题,我上面程序把命令多发几次就正常接受数据拉.还是我经验不足,遇到问题不知道从何处下手,以后要向各位多多学习.
我想问个问题,我重复发命令那十行有没有经典的代码代替,我这样处理总是不可靠的.
还有我设断点后在监视窗口中看到MSComm1中有2个input,一个在/object中,而且他们的数据不一致.哪位能帮我解释?