VB串口通讯程序,总是误报"端口已打开", 若删除Mscomm1.PortOpen = True则提示"只有端口打开时,操作有效"

Private Sub Form_Load()
With MSComm1
.CommPort = 2
.Settings = "9600,N,8,1"
.InBufferSize = 100
.OutBufferSize = 100
.InBufferCount = 0
.OutBufferCount = 0
.InputLen = 0
.InputMode = comInputModeBinary
.Handshaking = comNone
.RThreshold = 1
.NullDiscard = False
End With
Dim OutB(1) As Byte
OutB(0)=&H0
OutB(1)=&H1
With MSComm1
.OutBufferCount = 0
.InBufferCount = 0
If .PortOpen = False Then
.PortOpen = True '此处出错提示"端口已打开"
End If
.Output = OutB 'OutB是字节数组
End With
End Sub
问题是若端口是打开的, 就不可能进入这个判断, 请高手指点!
小弟家贫, 若问题解决, 将奉上全部家产100分
另外补充:
程序共3个窗体,窗体之间可以互相调用, 程序目的是, 在每个窗体打开时向PLC发送2两个字节的数据, 每个窗体结束时Unload里面都有加MSComm1.portopen=false

这个程序在我的电脑上没有出现上述问题,说明您的COM2串口,可能是被其它程序占用的。
做几个测试,可以证明是否是程序自身的问题:
1、将“.CommPort = 2”改为其它端口,例如COM1、COM3、COM4...试一下问题是否依旧;
2、用其它串口调试软件,如“串口调试助手”打开COM2,试一下能否正常打开。

另外我建议,你的想法很好,但是在每个窗体加载时都打开COMM(.PortOpen=True)并不是个好办法,人非圣贤孰能无过,任何人的程序都不能不存在BUG,但这种用法,会让你的程序故障转移,出现类似脚病了头却疼、手指病了牙却疼的现象,给将来的调试和维护带来很高的成本。
我的建议是,对于COMM2,既然容易引发冲突,那么建议在整个程序里只能有1处“.PortOpen=True”,MSComm控件也只要1个,不要弄得遍地都是。若多个窗体要使用,让它们调用一个公共函数岂不更好?追问

感谢如此快速的回答!受你启发:
a. 我3个窗体上各放置了1个Mscomm1, 是否因为都叫Mscomm1程序会判断不出是哪个窗体的Mscomm1的端口已关闭或打开? 若每个窗体分别改成不同的名字是否可行?
b. 我欲采用你说的公共函数, 只用1个MScomm, 但实际上我的每个窗体上是发送和接收不同长度的字节数组, 比如1个窗体发送2个字节,却接收10个字节, 另外1个窗体是发送6个字节,接收6个字此种情况下, 是否方便用公共函数实现? 如何实现
谢谢!

追答

a. 不会的,即使控件名称一样,但位于不同的窗体,互相是完全是独立的(改名的办法不可行)。但系统的COM2口却是唯一的,也就是说,这几个窗体的COMM控件,同一时刻最多只有一个能打开COM2。
b.你的用法存在问题,发送几个字符、接收几个字符,应与控件无关。不仅如此,在通讯中,偶而会有丢字节、多字节、串位情况的出现,那么这个程序会有很多不可预知的问题出现。
我的建议是,发送的字节随意,与控件无关;接收的字节:有多少则收多少,收完以后先判断数据是否完整,再进行数据处理。建议您先参考一下VB的MSDN,写一个最简化的GotData()和SendData(iData() as byte)函数,试试如何?
回头想想,好像说跑题了。先的解决你的眼前问题,你用第三方串口调试软件试过吗?类似“串口调试助手”这样的软件是必备的,找个安全的网站下一个吧,试一试先。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-08-23
Option Explicit
Dim strInput As String
Dim strSend As String
Dim sum As Integer

Private Sub Command1_Click()
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
End Sub

Private Sub Form_Load()
MSComm1.Settings = "9600,n,8,1"
MSComm1.InputMode = comInputModeText
MSComm1.RThreshold = 1
MSComm1.PortOpen = True
Timer1.Interval = 100 '控制发送延迟时间
Timer1.Enabled = False
End Sub

Private Sub MSComm1_OnComm()
Select Case MSComm1.CommEvent
Case comEvReceive
MSComm1.InputLen = 0
strInput = strInput & MSComm1.Input
Text1 = strInput
If strInput = "Q" Then
strSend = "R"
strInput = ""
Timer1.Enabled = True
ElseIf Len(strInput) < 8 And strInput <> "R" Then
strSend = strInput
strInput = ""
'MSComm1.RThreshold = 8
Timer1.Enabled = True
Else ' Then
sum = sum + 8
Text2 = sum / 8
If sum >= 160 Then
strSend = "E"
'MSComm1.PortOpen = False '本句似乎可不用
sum = 0
Else
strSend = "C"
End If
strInput = ""
Timer1.Enabled = True
End If
End Select
End Sub

Private Sub Timer1_Timer()
If MSComm1.PortOpen = True Then
MSComm1.Output = strSend
Timer1.Enabled = False
End If
End Sub

补充:2进制接收
Option Explicit
Dim strInput As String
Dim strSend() As Byte
Dim sum As Integer
Dim strSj As String
Private Sub Command1_Click()
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
End Sub

Private Sub Form_Load()
MSComm1.Settings = "9600,n,8,1"
MSComm1.InputMode = comInputModeBinary
'MSComm1.InputMode = comInputModeText
MSComm1.RThreshold = 1
MSComm1.PortOpen = True
Timer1.Interval = 100 '控制发送延迟时间
Timer1.Enabled = False
End Sub

Private Sub MSComm1_OnComm()
Dim buffer() As Byte
Dim i As Integer
Select Case MSComm1.CommEvent
Case comEvReceive
MSComm1.InputLen = 0
buffer = MSComm1.Input
For i = 0 To UBound(buffer)
strInput = strInput & Right("0" & Hex(buffer(i)), 2)
Next
If Mid(strInput, 1, 2) = "51" Then
ReDim strSend(0)
strSend(0) = &H52
strInput = ""
Timer1.Enabled = True
ElseIf Len(strInput) < 16 And Mid(strInput, 1, 2) <> "51" Then
ReDim strSend(1 To Len(strInput) / 2)
For i = 1 To Len(strInput) Step 2
strSend((i + 1) / 2) = Val("&H" & Mid(strInput, i, 2))
Next
strInput = ""
Timer1.Enabled = True
Else ' Then
sum = sum + 8
Text2 = sum / 8
strSj = strSj & strInput '& vbCrLf
If sum >= 160 Then
ReDim strSend(0)
Text1 = strSj
'请进入数据处理代码,转换为ASCII字符号。
MSComm1.PortOpen = False '本句似乎可不用
strSend(0) = &H45
sum = 0
Else
ReDim strSend(0)
strSend(0) = &H43
End If
strInput = ""
Timer1.Enabled = True
End If
End Select
End Sub

Private Sub Timer1_Timer()
If MSComm1.PortOpen = True Then
MSComm1.Output = strSend
Timer1.Enabled = False
End If
End Sub
相似回答