用VB写的,协议是modbus rtu
手上有一块仪表,现在就是对其中一个参数的读和写有点疑惑一直搞不明白
请大家帮忙分析到底是我代码的问题还是仪表的限制假设这个参数是SR,从我的软件上去修改它的数值,最大不能修改超过3276.7这个数
如果仪表上显示超过6553.5,那么我的软件上通讯过来的显示一直都是3276.8一、我要修改SR参数为一个大于3276.7的数,比如4000.0。仪表的通讯手册说明小数点不做传送
我要把SR修改成4000实际我就要发送成40000,转成十六进制就是9C40发送帧命令
地址 功能码 第一个字地址  字的值    CRC
02     06     00  A1          9C  40      B0EB 正常情况接收帧命令应该是这样的
02     06     00  A1          9C  40      B0EB 可是为什么在我的软件上返回的却是 028603F261 ???
我自己分析估计是CRC计算错误造成的仪表返回错误数据,
我用前面数值在其他CRC计算工具上有的计算结果是B0D8
在我的软件上测试只要把SR这个参数改成大于3276.7的数据即要发送的数据大于32767
就无法修改,小于这个数就可以正常修改二、现在再说下从仪表读取SR参数的问题
只要仪表的SR这个参数大于6553.5,那么软件上就一直显示3276.8发送帧命令
02 03 00 A1 00 01 D5DB只要SR>6553.5那么返回的数据都是下面这个
02 03 02 FF FF FDF4还有查看了这写和读的极限值好像写正好卡在Ingter 整形数范围-32768~32767
而读好像是String 字符串最大值65535,和这两个有关吧,我是个新手到底是什么原因麻烦帮忙看下三、下面附上我的代码SR读:txtSegRate.Text = Euro3504(.txtDevAdd.Text, 3, 0, "A1", 0, 1, True) / 10SR写:Private Sub cmdSegRate_Click()     strData = Replace(Format(DEC_to_HEX(txtSegRate.Text * 10), "@@@@"), " ", "0")    Call Euro3504(txtDevAdd.Text, 6, 0, "A1", Left(strData, 2), Right(strData, 2), True)
   
End Sub
模块代码:
Public Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long)Public Function Euro3504(A1 As String, A2 As String, A3 As String, A4 As String, A5 As String, A6 As String, Flag As Boolean) As StringDim CRC_JS() As Byte
Dim CRCC() As ByteDim Reply As String
Dim R_S As Variant
Dim RR() As Byte
Dim i As Integer'MESSAGE FRAME FORMAT 消息帧格式   ReDim CRCC(5)
     CRCC(0) = "&H" + A1
     CRCC(1) = "&H" + A2
     CRCC(2) = "&H" + A3
     CRCC(3) = "&H" + A4
     CRCC(4) = "&H" + A5
     CRCC(5) = "&H" + A6
         
     CRC_JS = CRC16(CRCC)  '调用CRC效验计算函数
         
    If Flag = True Then        Eurotherm.MSComm1.Output = CRCC '发送帧命令
        Eurotherm.MSComm1.Output = CRC_JS
        Eurotherm.MSComm1.OutBufferCount = 0 '清除传输缓冲区
          
        Delay 300 '超过35ms就可以
   
        R_S = Eurotherm.MSComm1.Input
        Eurotherm.MSComm1.InBufferCount = 0 '清除传输缓冲区
    
         RR = R_S
    
         Reply = ""
    
          For i = 0 To UBound(RR)
          
            Reply = Reply + Right("0" + Hex(Int(Str(RR(i)))), 2) + ""
                                   
          Next    End If    If Reply <> "" Then
    
         Euro3504 = HEX_to_DEC(Mid(Reply, 7, 4))  ' 转十进制
         
      '显示负数,排除Segment Rate地址A1,这个参数只要显示超过3278.6就显示负数了
      '因为小数点不传送读取出来就是>32786
            If Euro3504 > 32786 And A4 <> "A1" Then
             Euro3504 = Euro3504 - 65536
            End If
            
    End If      
End Function
Public Function HEX_to_DEC(ByVal Hex As String) As Long  '十六进制转成十进制
    Dim i As Long
    Dim b As Long    Hex = UCase(Hex)
    For i = 1 To Len(Hex)
        Select Case Mid(Hex, Len(Hex) - i + 1, 1)
            Case "0": b = b + 16 ^ (i - 1) * 0
            Case "1": b = b + 16 ^ (i - 1) * 1
            Case "2": b = b + 16 ^ (i - 1) * 2
            Case "3": b = b + 16 ^ (i - 1) * 3
            Case "4": b = b + 16 ^ (i - 1) * 4
            Case "5": b = b + 16 ^ (i - 1) * 5
            Case "6": b = b + 16 ^ (i - 1) * 6
            Case "7": b = b + 16 ^ (i - 1) * 7
            Case "8": b = b + 16 ^ (i - 1) * 8
            Case "9": b = b + 16 ^ (i - 1) * 9
            Case "A": b = b + 16 ^ (i - 1) * 10
            Case "B": b = b + 16 ^ (i - 1) * 11
            Case "C": b = b + 16 ^ (i - 1) * 12
            Case "D": b = b + 16 ^ (i - 1) * 13
            Case "E": b = b + 16 ^ (i - 1) * 14
            Case "F": b = b + 16 ^ (i - 1) * 15
        End Select
    Next i
    HEX_to_DEC = b
End Function
Public Function DEC_to_HEX(Dec As Long) As String '十进制转化为十六进制
        Dim a As String
        DEC_to_HEX = ""
        Do While Dec > 0
        a = CStr(Dec Mod 16)
        Select Case a
        Case "10": a = "A"
        Case "11": a = "B"
        Case "12": a = "C"
        Case "13": a = "D"
        Case "14": a = "E"
        Case "15": a = "F"
        End Select
        DEC_to_HEX = a & DEC_to_HEX
        Dec = Dec \ 16
        Loop
End Function
Public Sub Delay(mmSec As Long) ' 延时ms 级过程    Dim start As Single
    DoEvents
    Sleep mmSec
    'DoEventsEnd Sub
Public Function CRC16(data() As Byte) As String       'CRC16校验位函数      Dim CRC16Lo As Byte, CRC16Hi As Byte      'CRC寄存器      Dim CL As Byte, CH As Byte                '多项式码&HA001      Dim SaveHi As Byte, SaveLo As Byte      Dim i As Integer      Dim Flag As Integer      CRC16Lo = &HFF      CRC16Hi = &HFF      CL = &H1      CH = &HA0      For i = 0 To UBound(data)        CRC16Lo = CRC16Lo Xor data(i) '每一个数据与CRC寄存器进行异或        For Flag = 0 To 7          SaveHi = CRC16Hi          SaveLo = CRC16Lo          CRC16Hi = CRC16Hi \ 2            '高位右移一位          CRC16Lo = CRC16Lo \ 2            '低位右移一位          If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1            CRC16Lo = CRC16Lo Or &H80      '则低位字节右移后前面补1          End If                           '否则自动补0          If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或            CRC16Hi = CRC16Hi Xor CH            CRC16Lo = CRC16Lo Xor CL          End If        Next Flag      Next i      Dim ReturnData(1) As Byte      ReturnData(0) = CRC16Lo             'CRC低位      ReturnData(1) = CRC16Hi             'CRC高位      CRC16 = ReturnData
    End Function

解决方案 »

  1.   

    一,
    CRC校验码B0EB是对的,
    返回的错误码代码是03,解释是"非法数据值",
    发送的时候高字节在后低字节在前,可能需要送出409C二,
    Integer类型只支持有符号数,超过32767的话会变成负数,所以需要定义成Long型数据
      

  2.   

    但是我的仪表通讯手册定义是高位在前低位在后的你看我的代码只有一处定义Integer,好像和这个没有关系吧?
    Dim i As Integer
      

  3.   

    能否帮我看下我这个问题
    和我另外重新发问的帖子里的手册内容有关,谢谢
    见这个帖子http://bbs.csdn.net/topics/390992706