利用Kotlin扩展函数实现MODBUS协议CRC16生成和校验

获取MODBUS协议CRC16指令
只要拼接好命令,byte数组或者int后.crc16()就返回一个byte数组.
验证用byte数组直接.crc16Verify()

使用方式
新建一个kt,复制下面的进去

import java.lang.RuntimeException

const val BITS_OF_BYTE = 8
const val POLYNOMIAL = 0xA001
const val INITIAL_VALUE = 0xFFFF
const val FF  = 0xFF

fun 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: Byte = (res  shr 8 and FF).toByte()
    val highByte: Byte = (res and FF).toByte()
    return this.plus(highByte).plus(lowByte)
}

fun IntArray.crc16(): ByteArray{
    val byteArray = ByteArray(this.size+ 2)
    var res = INITIAL_VALUE
    for (index in this.indices) {
        res = res xor this[index]
        byteArray[index] = this[index].toByte()
        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: Byte = (res  shr 8 and FF).toByte()
    val highByte: Byte = (res and FF).toByte()
    byteArray[this.size] = highByte
    byteArray[this.size + 1] = lowByte
    return byteArray
}

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: Byte = (res  shr 8 and FF).toByte()
    val highByte: Byte = (res and FF).toByte()
    return highByte == this[this.size - 2] && lowByte == this[this.size - 1]
}

验证

@Test
    fun testCPC16(){
        val data: ByteArray = byteArrayOf(0x01 ,0x06, 0x00, 0x47, 0x09, 0xC4.toByte())
        val data2 = intArrayOf(0x01 ,0x06, 0x00, 0x47, 0x09, 0xC4)
        println(Crc16Util.byteTo16String(data.crc16()))
        println(Crc16Util.byteTo16String(data2.crc16()))

        val data3 = byteArrayOf(0x01 ,0x06, 0x00, 0x47, 0x09, 0xC4.toByte(),0x3e,0x1c)
        println(data3.crc16Verify())
    }

20201/08/29

自己封装了一个android串口通信,协议配置从java层带入c++层后,c++返回处理完所有返回一个整帧数据。所以校验就在c++层了。附C++,CRC16代码:

inline
bool crc16(const unsigned char *array, int len, int checkRes) {
    int crc = 0xFFFF;
    for (int i = 0; i < len; i++) {
        crc ^= array[i];
        for (int j = 0 ;j < 8 ; j++) {
            if (crc & 0x0001) {
                crc = (crc >> 1 ) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return (crc & 0xFFFF) == checkRes;
}

kotlin层修改了最后return部分,kotlin的plus调用的深copy(java system.copy最后是调的native内存copy,具体性能看c++层怎么去调用malloc函数和运气),2次plus对性能消耗不如直接再静态分配一次。所以修改为:

return byteArrayOf(*this,highByte,lowByte)
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
用户可以根据需求在驱动库里选择相对应的通讯驱动程序,配置相应的通讯握手参数,自由定义需要控制和采集的变量名、通讯地址、数据类型和初始值。功能说明及图片展示: 1.安装完成首次进入将会显示三页功能简要展示页面。 2.点击“立即使用”按钮,进入登录界面(公测账户为admin,密码admin)。 3.登录成功进入APP主页,此时主页所有状态为初始未配置状态。 4.在主页状态下向右滑动,可打开功能模块选择列表。 5.点击“WIFI连接”进入连接现场设备网络页面,如果此时用户已通过手机WIFI页面连接现场设备,则直接跳过此步骤。 6.连接成功后返回功能模块选择列表,点击“参数设置”进入通讯相关参数配置页面(首先进入驱动配置页面),目前驱动库中只有支持Modbus TCP的驱动,后续会持续更新,用户通过在驱动库列表中长按操作将选中的驱动挑选至已选列表中,如果要取消,可以在已选列表中通过同样的长按操作完成。 7.配置要访问的设备通讯参数,与主页的操作逻辑一致,在驱动配置页面向右滑动打开配置功能列表,点击“通讯参数配置”进入通讯参数配置页,然后点击右上角的加号,此时软件会根据已选的驱动类型自动添加一条相对应的通讯参数,用户可以通过双击的方式打开修改列表,然后在列表的某一条参数处通过长按的方式进入最终的修改对话框,修改完成后,可以通过长按的方式选定当前需要的参数配置信息到已选区域。 8.通讯参数配置完成后,向右滑动进入配置功能列表,点击“IO参数配置”进入地址段的分配,点击右上角的加号,在弹出的对话框中根据实际需求分配响应的起始地址以及地址数量,分配完成后,可在屏幕右侧边缘向左滑动调出隐藏功能菜单,通过功能菜单可查看和修改配置地址段的功能对应的IO点信息。 9.所有配置完成后,可返回主页,此时主页显示当前配置的信息,其中“控制操作”功能可以通过按钮发送布尔值,操作逻辑为当前值为0时发送1,当前值为1时发送0,而“参数设置”功能通过对子项长按可以设置调出输入框设置相应的参数值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值