博客
关于我
利用Kotlin扩展函数实现MODBUS协议CRC16生成和校验
阅读量:776 次
发布时间:2019-03-23

本文共 2420 字,大约阅读时间需要 8 分钟。

Modbus协议CRC16指令

为了实现Modbus协议中的CRC16数据包校验,本文将详细介绍如何通过拼接命令、使用预定义方法生成CRC校验位,并验证计算结果。

获取CRC16校验位

在Modbus协议中,CRC16校验位是数据包的一个重要组成部分。为了获取CRC16校验位,拼接好命令后,可以将数据字节或整数值传递给crc16()方法。该方法将返回一个包含低有效八位和高有效八位的字节数组。通过将这个结果拼接到原始数据中,可以创建完整的数据包。

以下是获取CRC16校验位的步骤:

  • 创建初始化值:初始化结果值为0xFFFF
  • 迭代处理每个数据字节:对每个数据字节,更新结果值。具体方法是:将当前结果值与数据字节进行异或运算(使用FF掩码与65280进行按位与运算)。
  • 多位微程序轮回器:对每一位(从最低有效位到最高有效位),执行以下运算:
    • 如果当前结果值的最低有效位为1,则进行右移一位后进行异或POLYNOMIAL运算。
    • 否则,仅进行右移一位。
  • 生成CRC16校验位:最后,将结果值的高八位作为高有效字节,低八位作为低有效字节,拼接到原始数据中。
  • 验证CRC16校验位

    为了验证计算结果,可以使用crc16Verify()方法。该方法首先对数据包尾部的两字节进行校验:

  • 初始化结果值:设置为0xFFFF
  • 迭代处理数据包所有字节(除了最后两个校验位):更新结果值,按照与生成CRC16校验位相同的步骤。
  • 校验高低有效字节:将计算得到的高有效字节与实际数据包中的倒数第二个字节进行比较。同样,低有效字节与实际数据包中的最后一个字节进行比较。
  • 返回验证结果:如果两边完全一致,则返回true,表示校验成功。否则,返回false
  • 使用示例

    以下是一个使用示例:

    import java.lang.RuntimeExceptionconst val BITS_OF_BYTE = 8const val POLYNOMIAL = 0xA001const val INITIAL_VALUE = 0xFFFFconst val FF = 0xFFfun ByteArray.crc16(): ByteArray {    var res = INITIAL_VALUE    for (data in this) {        res = res xor (data.toInt() and FF)        for (i in 0 until BITS_OF_BYTE) {            res = if (res and 0x0001 == 1) {                res shr 1 xor POLYNOMIAL            } else {                res shr 1            }        }    }    val lowByte = (res shr 8 and FF).toByte()    val highByte = (res and FF).toByte()    return this.plus(highByte).plus(lowByte)}fun ByteArray.crc16Verify(): Boolean {    if (this.size < 3) throw RuntimeException("数组长度不合法")    var res = INITIAL_VALUE    for (index in 0..this.size - 3) {        res = res xor (this[index].toInt() and FF)        for (i in 0 until BITS_OF_BYTE) {            res = if (res and 0x0001 == 1) {                res shr 1 xor POLYNOMIAL            } else {                res shr 1            }        }    }    val lowByte = (res shr 8 and FF).toByte()    val highByte = (res and FF).toByte()    return highByte == this[this.size - 2] &&           lowByte == this[this.size - 1]}@Testfun testCPC16() {    val data: ByteArray = byteArrayOf(0x01, 0x06, 0x00, 0x47, 0x09, 0xC4.toByte())    val data2 = intArrayOf(0x01, 0x06, 0x00, 0x47, 0x09, 0xC4)    val data3 = byteArrayOf(        0x01, 0x06, 0x00, 0x47, 0x09, 0xC4.toByte(),        0x3E, 0x1C    )    println("CRC16计算结果:" + Crc16Util.byteTo16String(data.crc16()))    println("数组式计算结果:" + Crc16Util.byteTo16String(data2.crc16()))    println("完整数据校验:" + data3.crc16Verify())}

    以上代码示例展示了如何在Kotlin中实现CRC16数据包校验。通过对原始数据包进行计算并附加校验位,可以确保数据传输过程中的完整性和一致性。

    转载地址:http://zdczk.baihongyu.com/

    你可能感兴趣的文章
    svn访问报错500
    查看>>
    org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned
    查看>>
    org.apache.ibatis.type.TypeException: Could not resolve type alias 'xxxx'异常
    查看>>
    org.apache.poi.hssf.util.Region
    查看>>
    org.apache.xmlbeans.XmlOptions.setEntityExpansionLimit(I)Lorg/apache/xmlbeans/XmlOptions;
    查看>>
    org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /
    查看>>
    org.hibernate.HibernateException: Unable to get the default Bean Validation factory
    查看>>
    org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
    查看>>
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    查看>>
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    查看>>
    org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded
    查看>>
    org.tinygroup.serviceprocessor-服务处理器
    查看>>
    org/eclipse/jetty/server/Connector : Unsupported major.minor version 52.0
    查看>>
    org/hibernate/validator/internal/engine
    查看>>
    SQL-36 创建一个actor_name表,将actor表中的所有first_name以及last_name导入改表。
    查看>>
    ORM sqlachemy学习
    查看>>
    Ormlite数据库
    查看>>
    orm总结
    查看>>
    os.path.join、dirname、splitext、split、makedirs、getcwd、listdir、sep等的用法
    查看>>
    os.system 在 Python 中不起作用
    查看>>