获取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)