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
每个变量由两个字节组成,前面为低字节、后面为高字节
我要用他来获取仪表显示的值,怎么能用VB编程表示出来?

解决方案 »

  1.   

    数据为字节型,先要把串口发送类型改为二进制型.在OnComm事件中处理数据.MSComm1.InputMode = comInputModeBinary  '以二进制形式发送和接收
    MSComm1.RThreshold = 1                  '当接收到一个字节时产生OnComm事件然后定义发送数据和接收数据的字节型数组.Dim CommSend() As Byte
    Dim CommReceive() As Byte比如你要发送例一的数据:如下Redim CommSend(7)
    CommSend(0)=&H81
    CommSend(1)=&H81
    CommSend(2)=&H52
    CommSend(3)=&H0
    CommSend(4)=&H0
    CommSend(5)=&H0
    CommSend(6)=&H53
    CommSend(7)=&H0
    MSComm1.Output=CommSend   '//发送81 81 52 00 00 00 53 00 然后当有数据返回,就会产生OnComm事件.Private Sub MSComm0_OnComm()
        CommReceive=MSComm1.Input
        '//然后自己可以根据定义取得CommReceive中各位的值.
        '//例如A2:    A2=CommReceive(3)*256+CommReceive(2)  高字节CommReceive(3)和低字节CommReceive(2)组成A2
    End Sub以上就是整个的思路吧,具体的比如设置波特率,打开关闭串口的就自己去完成了,按照这个思路做下来就没问题了.
      

  2.   

    LZ:先将接收部分代码贴上:
    Option Explicit
        Dim strData As StringPrivate Sub Form_Load()
        MSComm1.CommPort = 1
        MSComm1.Settings = "9600,N,8,2" '假设波特率是9600
        MSComm1.InBufferSize = 1024
        MSComm1.OutBufferSize = 512
        MSComm1.RThreshold = 1
        MSComm1.InputMode = comInputModeBinary '按2进制接收
        MSComm1.PortOpen = True
    End SubPrivate Sub MSComm1_OnComm()
        Dim BytReceived() As Byte
        Dim strBuff As String
        Select Case MSComm1.CommEvent
            Case 2
                MSComm1.InputLen = 0
                strBuff = MSComm1.Input
                BytReceived() = strBuff
                Dim i As Integer
                For i = 0 To UBound(BytReceived) '数据处理为16进制
                    If Len(Hex(BytReceived(i))) = 1 Then
                        strData = strData & "0" & Hex(BytReceived(i))
                    Else
                        strData = strData & Hex(BytReceived(i))
                    End If
                Next
                '数据处理代码
                If Len(strData) = 20 Then
                    Cls
                    Text1 = strData
                    Dim sj(4) As String
                    Dim sjByte(4)
                    Dim j As Integer
                    For j = 1 To Len(strData) Step 4
                        sj((j - 1) \ 4) = Mid(strData, j, 4)
                        sj((j - 1) \ 4) = Right(sj((j - 1) \ 4), 2) & Left(sj((j - 1) \ 4), 2)
                    Next j
                    For j = 0 To 4
                         sjByte(j) = Val("&H" & sj(j)) '
                         Print sjByte(j)
                    Next
                    If 2 + sjByte(0) + sjByte(1) + sjByte(2) + sjByte(3) = sjByte(4) Then
                        Print "ok"
                        '写进入接收正确数据处理代码
                    End If
                    strData = ""
                End If
        End Select
    End Sub
      

  3.   


    Option Explicit
        Dim strData As StringPrivate Sub Form_Load()
        MSComm1.CommPort = 1
        MSComm1.Settings = "9600,N,8,2" '假设波特率是9600
        MSComm1.InBufferSize = 1024
        MSComm1.OutBufferSize = 512
        MSComm1.RThreshold = 1
        MSComm1.InputMode = comInputModeBinary '按2进制接收
        MSComm1.PortOpen = True
    End SubPrivate Sub MSComm1_OnComm()
        Dim BytReceived() As Byte
        Dim strBuff As String
        Select Case MSComm1.CommEvent
            Case 2
                MSComm1.InputLen = 0'//这一步是干什么的?
                strBuff = MSComm1.Input 
                BytReceived() = strBuff'//这一步是没必要的,直接BytReceived=MSComm1.Input就行
                Dim i As Integer
                For i = 0 To UBound(BytReceived) '数据处理为16进制
                      If Len(Hex(BytReceived(i))) = 1 Then
                        strData = strData & "0" & Hex(BytReceived(i))
                    Else
                        strData = strData & Hex(BytReceived(i))
                    End If
                Next
                '数据处理代码
                If Len(strData) = 20 Then
                    Cls
                    Text1 = strData
                    Dim sj(4) As String
                    Dim sjByte(4)
                    Dim j As Integer
                    For j = 1 To Len(strData) Step 4
                        sj((j - 1) \ 4) = Mid(strData, j, 4)
                        sj((j - 1) \ 4) = Right(sj((j - 1) \ 4), 2) & Left(sj((j - 1) \ 4), 2)
                    Next j
                    For j = 0 To 4
                         sjByte(j) = Val("&H" & sj(j)) '
                         Print sjByte(j)
                    Next
                    If 2 + sjByte(0) + sjByte(1) + sjByte(2) + sjByte(3) = sjByte(4) Then
                        Print "ok"
                        '写进入接收正确数据处理代码
                    End If
                    strData = ""
                End If
        End Select
    End Sub
      

  4.   

    3楼贴的代码是本人的。
    现将发送与接收代码贴上:
    Option Explicit
        Dim strData As String
        Dim strBin(7) As Byte
        Dim addr As BytePrivate Sub CmdRead_Click()
        strBin(0) = &H80 + Val(txtaddr)
        strBin(1) = &H80 + Val(txtaddr)
        strBin(2) = &H52
        strBin(3) = &H0
        strBin(4) = &H0
        strBin(5) = &H0
        strBin(6) = strBin(2) + Val(txtaddr)
        strBin(7) = strBin(3)
        MSComm1.Output = strBin
    End SubPrivate Sub CmdWrite_Click()
        strBin(0) = &H80 + Val(txtaddr)
        strBin(1) = &H80 + Val(txtaddr)
        strBin(2) = &H43
        strBin(3) = Val("&H" & txtCsaddr)
        strBin(4) = Val(txtSj)
        Print strBin(4)
        strBin(5) = &H0
        Dim crcW As Integer
        crcW = strBin(2) + strBin(4) + 2 + 256 * 5
        Dim strcrcW As String
        strcrcW = Hex(crcW)
        If Len(strcrcW) = 3 Then
            strcrcW = "0" & strcrcW
        End If
        strBin(6) = Val("&H" & Right(strcrcW, 2))
        strBin(7) = Val("&H" & Left(strcrcW, 2))
        MSComm1.Output = strBin
    End SubPrivate Sub Form_Load()
        MSComm1.CommPort = 1
        MSComm1.Settings = "9600,N,8,2" '假设波特率是9600
        MSComm1.InBufferSize = 1024
        MSComm1.OutBufferSize = 512
        MSComm1.RThreshold = 1
        MSComm1.InputMode = comInputModeBinary '按2进制接收
        MSComm1.PortOpen = True
        Text1 = ""
        txtaddr = "" '地址
        txtSj = "" '写的参数值
        txtCsaddr = "" '写入参数地址
    End SubPrivate Sub MSComm1_OnComm()
        Dim BytReceived() As Byte
        Dim strBuff As String
        Select Case MSComm1.CommEvent
            Case 2
                MSComm1.InputLen = 0
                strBuff = MSComm1.Input
                BytReceived() = strBuff
                Dim i As Integer
                For i = 0 To UBound(BytReceived) '数据处理为16进制
                    If Len(Hex(BytReceived(i))) = 1 Then
                        strData = strData & "0" & Hex(BytReceived(i))
                    Else
                        strData = strData & Hex(BytReceived(i))
                    End If
                Next
                '数据处理代码
                If Len(strData) = 20 Then
                    Cls
                    Text1 = strData
                    Dim sj(4) As String
                    Dim sjByte(4)
                    Dim j As Integer
                    For j = 1 To Len(strData) Step 4
                        sj((j - 1) \ 4) = Mid(strData, j, 4)
                        sj((j - 1) \ 4) = Right(sj((j - 1) \ 4), 2) & Left(sj((j - 1) \ 4), 2)
                    Next j
                    For j = 0 To 4
                         sjByte(j) = Val("&H" & sj(j)) '
                         Print sjByte(j)
                    Next
                    If 2 + sjByte(0) + sjByte(1) + sjByte(2) + sjByte(3) = sjByte(4) Then
                        Print "ok"
                        '写进入接收正确数据处理代码
                    End If
                    strData = ""
                End If
        End Select
    End Sub
      

  5.   

    哦!那就行,只要数据没出错就行.这句"BytReceived() = strBuff".让一个数组等于一个字符串,不知是否可行,不知道你的程序是不是运行到这一句了.
      

  6.   

    首先解释1点:
    3楼 sulipeng007问MSComm1.InputLen = 0'//这一步是干什么的?
    见MSDN说明
    InputLen 属性
    设置并返回 Input 属性从接收缓冲区读取的字符数。
    InputLen 属性的缺省值是 0。设置 InputLen 为 0 时,使用 Input 将使 MSComm 控件读取接收缓冲区中全部的内容。
    从以上MSDN说明:
    MSComm1.InputLen = 0
    用法没错.

    其次我在上面贴出的代码是经双串口机器调试,不存在任何问题.
    至于sulipeng007网友所担忧的显然没有经过实际通信调试,凭猜测主观臆断所做的结论.
    VB的代码编写必须经调试,而且这种调试本身就是一种寻找代码错误的手段.
    建议sulipeng007网友在编写串口通信代码调试时,使用双串口机器,即使机器仅1个COM口,你可购买PCI插槽的串口扩展卡,费用不高,65元/张,那可避免不少麻烦.串口通信大量使用在工业实时控制,写好的代码如果只能在设备现场调试,将非常困难.一般我采用在单台机器做一个模拟现场装置要求的调试程序与PC机的VB应用程序调试,做到无错误后,再交付使用.
    LZ的问贴其重点在算法的设计,有正确的算法才能写出符合通信协议的串口通信代码.
      

  7.   

    谢谢~~~~~~~老板还谈不上,现在只是倒倒货而已....而且能不能起来都还是个大问题呢:)另外,去我帖子里聊吧,毕竟这是别人的提问帖,嘿嘿http://topic.csdn.net/u/20080903/23/1bb261ea-5e77-4dc9-b860-05811cf92c9b.html
      

  8.   

                Dim i As Integer
                For i = 0 To UBound(BytReceived) '数据处理为16进制
                      If Len(Hex(BytReceived(i))) = 1 Then
                        strData = strData & "0" & Hex(BytReceived(i))
                    Else
                        strData = strData & Hex(BytReceived(i))
                    End If
                Next这句时接受出来的数据是84FF31F8000031F8E7EF和想要得倒的8181520000005300不一样啊,不知道怎么回事,我没找出原因来