HJ212-2017《污染物在线监控(监测)系统数据传输标准》中 CRC 数据校验算法 VBJS 源码

HJ212-2017《污染物在线监控(监测)系统数据传输标准》中 CRC 数据校验算法 VBJS 源码,第1张

PS:源代码采集自: HJT212 的CRC循环冗余校验 - 开发者知识库  

我整理合并成一个函数,至此,终于搞定这份蛋疼的代码了。

源起:

    这几天准备自己写个支持 HJ212-2017《污染物在线监控(监测)系统数据传输标准》的简易数据接收端玩玩,仔细研读通讯协议文本发现通讯中需要对数据块做 CRC16 校验,于是翻出老早些年前的 CRC16 代码,用例子测试了一把( 标准中19、20页 ),

发现结果居然不一致,我原有代码 :

Public Function crc16Str(s As String) As String
    Dim data() As Byte
    Dim ReturnData(1) As Byte
    Dim CRC_Reg_Lo, CRC_Reg_Hi As Byte
    Dim CL, CH As Byte
    Dim SaveHi, SaveLo As Byte
    Dim i, j As Integer
    CRC_Reg_Lo = &HFF
    CRC_Reg_Hi = &HFF   'CRC寄存器&H FF FF
    CH = &HA0
    CL = &H1        '多项式&H A0 01
    data = StrConv(s, vbFromUnicode)
    For i = 0 To UBound(data)
        CRC_Reg_Lo = CRC_Reg_Lo Xor data(i) '依次和寄存器低8位进行异或运算
        For j = 0 To 7
            SaveHi = CRC_Reg_Hi             '保存高位,是为了判断右移时是否向低位字节进1
            SaveLo = CRC_Reg_Lo             '保存地位,是为了判断LSB是否为0
'以下是右移'''''''''''''''''''''''''''''''''''''
            CRC_Reg_Hi = CRC_Reg_Hi \ 2
            CRC_Reg_Lo = CRC_Reg_Lo \ 2
            If ((SaveHi And &H1) = &H1) Then
                CRC_Reg_Lo = CRC_Reg_Lo Or &H80
            End If
'右移完成'''''''''''''''''''''''''''''''''''''''
            If ((SaveLo And &H1) = &H1) Then
                CRC_Reg_Hi = CRC_Reg_Hi Xor CH
                CRC_Reg_Lo = CRC_Reg_Lo Xor CL
            End If
        Next j
    Next i
    ReturnData(0) = CRC_Reg_Lo  '低位
    ReturnData(1) = CRC_Reg_Hi  '高位
    s = ""
    For i = 0 To UBound(ReturnData)
        s = Right("00" & Hex(ReturnData(i)), 2) & s
    Next
    crc16Str = s
End Function

校验例子串:

QN=20160801085857223;ST=32;CN=1062;PW=100000;MN=010000A8900016F000169DC0;Flag=5;CP=&&RtdInterval=30&&

得到结果为 &H0759,并非 &H1C80,查了一下,发现 CRC16 居然有好多版本,我上面这个属于 ModBus 算法,从在线 CRC 计算器: CRC(循环冗余校验)在线计算_ip33.com,中试了其中所有 CRC16 算法,发现结果均不匹配。

看来这样的话,只能直接按照 HJ212 标准中的 C 语言算法来改了。又乱翻中,发现  污染物在线自动监控(监测)系统数据传输标准 (HJ212-2017)-CRC数据校验 - Liu Siyuan - 博客园  中有个 Java 算法 http://t.csdn.cn/jGja6 ,为了快速调试,我把它改成 JS 语言,扔进浏览器试了一下,结果居然匹配:







其中 strToUtf8Bytes 来自:JS中实现Java的getBytes()方法_kinpowoo的博客-CSDN博客  。

一下子懒得自己改成 VB ,瞎翻中又在搜索命中率越来越低的 bd 搜索结果中一个花了 3 分钟才打开的网页:HJT212 的CRC循环冗余校验 - 开发者知识库 上发现在其后半页有段 VB 代码,马上拿过来,改了一下:

Function CRC16forHJ212_2017(s As String) As String  '(data() As Byte) As Long
    Dim r As Long
    Dim hi As Byte
    Dim flag As Byte
    Dim i As Long, j As Long, data() As Byte
    data = StrConv(s, vbFromUnicode)
    r = &HFFFF&
    For j = 0 To UBound(data)
        hi = r \ &H100&
        hi = hi Xor data(j)
        r = hi
        For i = 1 To 8
            flag = r And 1
            r = r \ 2
            If flag = 1 Then
                r = r Xor &HA001&
            End If
        Next
    Next
    CRC16forHJ212_2017 = Right("0000" & Hex(r), 4)
End Function

测试了几条数据,结果和 HJ212-2017 中的完全匹配。

’------------------

此记!

相关资源(5积分):HJ212-2017《污染物在线监控(监测)系统数据传输标准》-C文档类资源-CSDN下载

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1324885.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存