MSCOMM控件取数据的问题!

hzc1 2008-12-10 03:17:37
我现在遇到了一个这样的问题,就是我在接收数据的时候,如果发生了错位现象,我需要关闭端口,再打开,再接收就正常了,可是非得要点击按钮来进行手动关闭再开,如果放在ONCOMM中或者TIMER过程中关闭再打开,都没有用是为何?
...全文
105 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
zdingyun 2008-12-11
  • 打赏
  • 举报
回复
数据帧应该有:帧头、用户数据、帧尾和确定的数据帧字节总长
其中帧头或帧尾应由明确的字符,如回车,换行或其它字符
这样可以便于接收判断。
你接收的数据帧有2种长度,更须严格定义。
下面是XM 系列仪表通讯说明,供参考:
XM 系列仪表通讯说明
通讯格式为8 位数据,2 个停止位,无校验位。数据包采用16 位求和校验,它的纠错能力比 奇偶校验高数万倍,可确保通讯数据的正确可靠。XM 系列仪表在上位计算机、通讯接口或 线路发生故障时,仍能保持仪表本身的正常工作。
仪表读写方式如下:
读指令: Addr+80H Addr+80H 52H 要读参数的代号 00 00 CRC 校验码
写指令: Addr+80H Addr+80H 43H 要写参数的代号 写入数低字节 写入数高字节 CRC 校验码
读指令的CRC 校验码为:52H+Addr 要读参数的代号,Addr 为仪表地址参数值范围是0~100
写指令的CRC 校验码为:43H+要写的参数值+Addr 要写的参数代号。
每2 个8 位数据代表一个16 位整型数,低位字节在前,高位字节在后,热电偶或热电阻输入时其 单位都是0.1℃。1V 或0V 等线性输入时,单位都是线性最小单位。因为传递的是16 位二进制数,所 以无法表示小数点,要求用户在上位机处理。
只要上位机发送的命令格式正确时,将返回以下数据:
XX XX XX XX XX XX XX XX XX XX
A1 A2 A3 A4 A5
每个变量由两个字节组成,前面为低字节、后面为高字节
含义如下:第一行的A1、A2、A3、A4、A5 为变量名称,第一列为仪表为各仪表的型号
仪表返回数据的CRC 校验码算法为:A5 = A1 + A2 + A3 + A4 + Addr
例1:如需接收测量值和Loc 值,且仪表的通信地址为1,则发送读指令如下:
81 81 52 00 00 00 53 00
其中 81 81 为仪表的地址代号,52 00 为读参数的指令,53 00 为CRC 校验码。
注:所有的数据读写的时候均为高位在后低位在前,十六进制。
例2:当仪表通讯地址为2,需将仪表参数地址为05H 参数改为123,则发送数据格式为:
82 82 43 05 7B 00 C0 05
123 转换为16 进制为7B。
05C0=43+7B+2+100×5 (注:此公式为16 进制的运算)
返回数据为 16 01 58 02 00 00 7B 00 EB 03
PV 测量值为278(0116H)。CRC 的计算方法为:0116+0258+0000+007B+0002=03EB
其中XMT仪表的
、仪表与上位机通讯,返回数据格式
XX XX XX XX XX XX XX XX XX XX
PV 测量值 仪表状态 对应通信地址数据 CRC 校验码
A1 A2 A3 A4 A5
每个变量由两个字节组成,前面为低字节、后面为高字节

hzc1 2008-12-11
  • 打赏
  • 举报
回复
谢谢指教,我想请问如何定义通信协议?
zdingyun 2008-12-11
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hzc1 的回复:]
谢谢帮忙,不过我还要说明一下问题:
我是在接收几帧数据后,终端会自动发四帧数据过来,比如我在接收四帧数据后,终端自动跟随发送另外的四帧长度也是一样的数据,只不过头尾都加了回车和换行
代码如下:
Private Sub MSComm1_OnComm()
Dim xx() As Byte
Select Case j
Case 1, 2, 3, 4, 6, 7
MSComm1.InputLen = 14
MSComm1.RThreshold = 14
Case 5,8
MSComm1.InputLen = 0
MSComm…
[/Quote]
LZ:有一个严格的通信协议,对于串口通信的正常起到事半功倍的作用。
Tiger_Zhao 2008-12-11
  • 打赏
  • 举报
回复
RThreshold 必须在 OnComm() 之前设置,所以你的 Select Case j 部分应该在 Output 之前先设置好接收方式。
检查已收到多少字符用 InBufferCount 检查。
不要重新开关端口,只要将 InBufferCount = 0 就可以清除接收缓冲区。
hzc1 2008-12-11
  • 打赏
  • 举报
回复
谢谢帮忙,不过我还要说明一下问题:
我是在接收几帧数据后,终端会自动发四帧数据过来,比如我在接收四帧数据后,终端自动跟随发送另外的四帧长度也是一样的数据,只不过头尾都加了回车和换行
代码如下:
Private Sub MSComm1_OnComm()
Dim xx() As Byte
Select Case j
Case 1, 2, 3, 4, 6, 7
MSComm1.InputLen = 14
MSComm1.RThreshold = 14
Case 5,8
MSComm1.InputLen = 0
MSComm1.RThreshold = 16
End Select
Select Case MSComm1.CommEvent
Case comEvReceive
If MSComm1.InBufferCount Then
xx = MSComm1.Input

For i1 = 0 To UBound(xx)
yy = yy & " " & hex(xx(i1))
Label1.Caption = Label1.Caption & Chr(xx(i1))
label1.caption=""
Next
List1.AddItem Label1.Caption & "/" & Len(Label1.Caption) & "--" & j & yy
Label1.Caption = ""
If j = 8 Then
j=1
Else
j = j + 1
End If
End If
End Select
End Sub
如果这一轮接收完成,如果有数据挪位,也就是说终端自动发送的数据格式因为不规则,导致收14位的位置挪位,这个时候我需要点击关闭端口,再打开端口,然后再接收,位置就正确了.但是在ONCOMM和TIMER中用关闭和打开的作用等于没有,非得用手动,不明原因.
再我想补充问一个问题,那就是,缓冲中的数据我要如何知道到底有多少位,我取的时候发现时长时短的.头痛
zdingyun 2008-12-10
  • 打赏
  • 举报
回复

Option Explicit
Dim yy As String
Private Sub Command1_Click()
MSComm1.CommPort = 3
MSComm1.Settings = "9600,n,8,1"
MSComm1.InBufferCount = 0
MSComm1.InputLen = 0
MSComm1.RThreshold = 14
MSComm1.InputMode = comInputModeBinary
MSComm1.PortOpen = True
End Sub

Private Sub Command2_Click()
MSComm1.PortOpen = False
End Sub

Private Sub MSComm1_OnComm()
Dim xx() As Byte
Dim i As Integer
Select Case MSComm1.CommEvent
Case comEvReceive
xx = MSComm1.Input
For i = 0 To UBound(xx)
If Len(Hex(xx(i))) = 1 Then
yy = yy & "0" & Hex(xx(i))
Else
yy = yy & Hex(xx(i))
End If
Next
If Len(yy) = 28 Then '本句最好有对首字节符合通信协议规定的判断
Label1.Caption = yy
List1.AddItem yy & "/" & Len(yy)
yy = ""
End If
End Select
End Sub
duyin2004 2008-12-10
  • 打赏
  • 举报
回复
1.'你要动态定义数组的长度,你都没定义数组的长度,还取上标,能不错吗
dim intInputLen as integer
intInputLen = MSComm1.InBufferCount
ReDim xx (intInputLen)
xx= MSComm1.Input

2.用timer来清
ReDim xx (0)
intInputLen=0
hzc1 2008-12-10
  • 打赏
  • 举报
回复
Private Sub Command1_Click()

MSComm1.CommPort = 3
MSComm1.Settings = "9600,n,8,1"
MSComm1.PortOpen = True
MSComm1.InBufferCount = 0
MSComm1.InputLen = 14
MSComm1.RThreshold = 14
MSComm1.InputMode = comInputModeBinary
End Sub

Private Sub Command2_Click()
MSComm1.PortOpen = False
End Sub

Private Sub MSComm1_OnComm()
Dim xx() As Byte
Select Case MSComm1.CommEvent
Case comEvReceive

If MSComm1.InBufferCount Then
xx = MSComm1.Input

For i1 = 0 To UBound(xx)
yy = yy & " " & xx(i1)
Label1.Caption = Label1.Caption & Chr(xx(i1))
Next
List1.AddItem Label1.Caption & "/" & Len(Label1.Caption) End Select
MSComm1.PortOpen = False'这里我将端口关闭
MSComm1.CommPort = 3
MSComm1.Settings = "9600,n,8,1"
MSComm1.PortOpen = True
MSComm1.InBufferCount = 0
MSComm1.InputLen = 14
MSComm1.RThreshold = 14
MSComm1.InputMode = comInputModeBinary
End Select
End Sub
这是我的代码.不知道是我用得不对还是?反正如果数据接收的时候挪位了,我要清空缓存,必须手动点击按钮才行
zdingyun 2008-12-10
  • 打赏
  • 举报
回复
请叙述完整的通信协议,并将你的接收代码贴上,方能进行分析。

1,451

社区成员

发帖
与我相关
我的任务
社区描述
VB 控件
社区管理员
  • 控件
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧