crc-16 cccitt 问题 - 计算不正确
crc-16 cccitt problem - incorrect calculation
尝试在我的蓝牙 ios 移动应用程序中实现此 CRC16 CITT 校验和:
extension Data {
typealias bit_order_16 = (_ value: UInt16) -> UInt16
typealias bit_order_8 = (_ value: UInt8) -> UInt8
func crc16Check() -> UInt16 {
let data = self as! NSData
let bytes = UnsafePointer<UInt8>(data.bytes.assumingMemoryBound(to: UInt8.self))
let length = data.length
return crc16ccitt(message: bytes, nBytes: length)
}
func straight_16(value: UInt16) -> UInt16 {
return value
}
func reverse_16(value: UInt16) -> UInt16 {
var value = value
var reversed: UInt16 = 0
for i in stride(from: 0, to: 16, by: 1) {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func straight_8(value: UInt8) -> UInt8 {
return value
}
func reverse_8(value: UInt8) -> UInt8 {
var value = value
var reversed: UInt8 = 0
for i in stride(from: 0, to: 8, by: 1) {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func crc16(message: UnsafePointer<UInt8>, nBytes: Int, data_order: bit_order_8, remainder_order: bit_order_16, remainder: UInt16, polynomial: UInt16) -> UInt16 {
var remainder = remainder
for byte in stride(from: 0, to: nBytes, by: 1) {
remainder ^= UInt16(data_order(message[byte]) << 8)
var bit = 8
while bit > 0 {
if (remainder & 0x8000) != 0 {
remainder = (remainder << 1) ^ 0x1021
} else {
remainder = (remainder << 1)
}
bit -= 1
}
}
return remainder_order(remainder)
}
func crc16ccitt(message: UnsafePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0xffff, polynomial: 0x1021)
}
func crc16ccitt_xmodem(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0x0000, polynomial: 0x1021)
}
func crc16ccitt_kermit(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
let swap = crc16(message: message, nBytes: nBytes, data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x1021)
return swap << 8 | swap >> 8
}
func crc16ccitt_1d0f(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0x1d0f, polynomial: 0x1021)
}
func crc16ibm(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x8005)
}
}
我设置固定数据类型
let tData = Data.init(bytes: [0x05, 0x02, 0x03] as [UInt8], count: 3)
let crcString = String.init(format: "CRC error, calculated: %04X", tData.crc16Check())
print(crcString)
//打印出CC9C
CC9C 不正确。
答案应该是:716D
似乎无法在 crc16 ccitt 计算中找到错误。有人可以帮助发现问题,因为我真的不确定哪里错了。花了太长时间试图弄清楚。感谢社区的任何帮助。谢谢。
错误是这里操作顺序错误:
remainder ^= UInt16(data_order(message[byte]) << 8)
8 位值 data_order(message[byte])
向左移动 8 位 - 结果始终为零。应该是
remainder ^= UInt16(data_order(message[byte])) << 8
以便将数字转换为 16 位值然后将其左移。
在类似的 C 程序中可能不会出现该问题,其中所有整数操作数在进行计算之前都被提升为 int
– 这种隐式类型转换不会在 Swift.[=26 中完成=]
另一个错误是您的 func crc16()
使用固定多项式 0x1021
而不是 polynomial
参数。这会导致 crc16ibm
校验和的错误结果。
另请注意,不需要在 crc16Check()
中转换为 NSData
。该方法可以简化为
func crc16Check() -> UInt16 {
return self.withUnsafeBytes { [length = self.count] in
crc16ccitt(message: [=12=], nBytes: length)
}
}
甚至更好:让所有方法都在 self
上进行运算,而不是传递 Unsafe(Mutable)Pointer
和周围的长度:
extension Data {
typealias bit_order_16 = (_ value: UInt16) -> UInt16
typealias bit_order_8 = (_ value: UInt8) -> UInt8
func straight_16(value: UInt16) -> UInt16 {
return value
}
func reverse_16(value: UInt16) -> UInt16 {
var value = value
var reversed: UInt16 = 0
for _ in 0..<16 {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func straight_8(value: UInt8) -> UInt8 {
return value
}
func reverse_8(value: UInt8) -> UInt8 {
var value = value
var reversed: UInt8 = 0
for _ in 0..<8 {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func crc16(data_order: bit_order_8, remainder_order: bit_order_16, remainder: UInt16, polynomial: UInt16) -> UInt16 {
var remainder = remainder
for byte in self {
remainder ^= UInt16(data_order(byte)) << 8
for _ in 0..<8 {
if (remainder & 0x8000) != 0 {
remainder = (remainder << 1) ^ polynomial
} else {
remainder = (remainder << 1)
}
}
}
return remainder_order(remainder)
}
func crc16ccitt() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0xffff, polynomial: 0x1021)
}
func crc16ccitt_xmodem() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0x0000, polynomial: 0x1021)
}
func crc16ccitt_kermit() -> UInt16 {
let swap = crc16(data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x1021)
return swap.byteSwapped
}
func crc16ccitt_1d0f() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0x1d0f, polynomial: 0x1021)
}
func crc16ibm() -> UInt16 {
return crc16(data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x8005)
}
}
用法示例(针对 Swift 4+ 更新了代码):
let tData = Data([0x05, 0x02, 0x03])
print(String(format: "crc16ccitt: %04X", tData.crc16ccitt())) // 716D
print(String(format: "crc16ccitt_xmodem: %04X", tData.crc16ccitt_xmodem())) // BDF1
print(String(format: "crc16ccitt_kermit: %04X", tData.crc16ccitt_kermit())) // 9638
print(String(format: "crc16ccitt_1d0f: %04X", tData.crc16ccitt_1d0f())) // ACFD
print(String(format: "crc16ibm: %04X", tData.crc16ibm())) // 6051
这些数字与 Online CRC calculator.
的结果一致
尝试在我的蓝牙 ios 移动应用程序中实现此 CRC16 CITT 校验和:
extension Data {
typealias bit_order_16 = (_ value: UInt16) -> UInt16
typealias bit_order_8 = (_ value: UInt8) -> UInt8
func crc16Check() -> UInt16 {
let data = self as! NSData
let bytes = UnsafePointer<UInt8>(data.bytes.assumingMemoryBound(to: UInt8.self))
let length = data.length
return crc16ccitt(message: bytes, nBytes: length)
}
func straight_16(value: UInt16) -> UInt16 {
return value
}
func reverse_16(value: UInt16) -> UInt16 {
var value = value
var reversed: UInt16 = 0
for i in stride(from: 0, to: 16, by: 1) {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func straight_8(value: UInt8) -> UInt8 {
return value
}
func reverse_8(value: UInt8) -> UInt8 {
var value = value
var reversed: UInt8 = 0
for i in stride(from: 0, to: 8, by: 1) {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func crc16(message: UnsafePointer<UInt8>, nBytes: Int, data_order: bit_order_8, remainder_order: bit_order_16, remainder: UInt16, polynomial: UInt16) -> UInt16 {
var remainder = remainder
for byte in stride(from: 0, to: nBytes, by: 1) {
remainder ^= UInt16(data_order(message[byte]) << 8)
var bit = 8
while bit > 0 {
if (remainder & 0x8000) != 0 {
remainder = (remainder << 1) ^ 0x1021
} else {
remainder = (remainder << 1)
}
bit -= 1
}
}
return remainder_order(remainder)
}
func crc16ccitt(message: UnsafePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0xffff, polynomial: 0x1021)
}
func crc16ccitt_xmodem(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0x0000, polynomial: 0x1021)
}
func crc16ccitt_kermit(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
let swap = crc16(message: message, nBytes: nBytes, data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x1021)
return swap << 8 | swap >> 8
}
func crc16ccitt_1d0f(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: straight_8, remainder_order: straight_16, remainder: 0x1d0f, polynomial: 0x1021)
}
func crc16ibm(message: UnsafeMutablePointer<UInt8>, nBytes: Int) -> UInt16 {
return crc16(message: message, nBytes: nBytes, data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x8005)
}
}
我设置固定数据类型
let tData = Data.init(bytes: [0x05, 0x02, 0x03] as [UInt8], count: 3)
let crcString = String.init(format: "CRC error, calculated: %04X", tData.crc16Check())
print(crcString)
//打印出CC9C
CC9C 不正确。
答案应该是:716D
似乎无法在 crc16 ccitt 计算中找到错误。有人可以帮助发现问题,因为我真的不确定哪里错了。花了太长时间试图弄清楚。感谢社区的任何帮助。谢谢。
错误是这里操作顺序错误:
remainder ^= UInt16(data_order(message[byte]) << 8)
8 位值 data_order(message[byte])
向左移动 8 位 - 结果始终为零。应该是
remainder ^= UInt16(data_order(message[byte])) << 8
以便将数字转换为 16 位值然后将其左移。
在类似的 C 程序中可能不会出现该问题,其中所有整数操作数在进行计算之前都被提升为 int
– 这种隐式类型转换不会在 Swift.[=26 中完成=]
另一个错误是您的 func crc16()
使用固定多项式 0x1021
而不是 polynomial
参数。这会导致 crc16ibm
校验和的错误结果。
另请注意,不需要在 crc16Check()
中转换为 NSData
。该方法可以简化为
func crc16Check() -> UInt16 {
return self.withUnsafeBytes { [length = self.count] in
crc16ccitt(message: [=12=], nBytes: length)
}
}
甚至更好:让所有方法都在 self
上进行运算,而不是传递 Unsafe(Mutable)Pointer
和周围的长度:
extension Data {
typealias bit_order_16 = (_ value: UInt16) -> UInt16
typealias bit_order_8 = (_ value: UInt8) -> UInt8
func straight_16(value: UInt16) -> UInt16 {
return value
}
func reverse_16(value: UInt16) -> UInt16 {
var value = value
var reversed: UInt16 = 0
for _ in 0..<16 {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func straight_8(value: UInt8) -> UInt8 {
return value
}
func reverse_8(value: UInt8) -> UInt8 {
var value = value
var reversed: UInt8 = 0
for _ in 0..<8 {
reversed <<= 1
reversed |= (value & 0x1)
value >>= 1
}
return reversed
}
func crc16(data_order: bit_order_8, remainder_order: bit_order_16, remainder: UInt16, polynomial: UInt16) -> UInt16 {
var remainder = remainder
for byte in self {
remainder ^= UInt16(data_order(byte)) << 8
for _ in 0..<8 {
if (remainder & 0x8000) != 0 {
remainder = (remainder << 1) ^ polynomial
} else {
remainder = (remainder << 1)
}
}
}
return remainder_order(remainder)
}
func crc16ccitt() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0xffff, polynomial: 0x1021)
}
func crc16ccitt_xmodem() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0x0000, polynomial: 0x1021)
}
func crc16ccitt_kermit() -> UInt16 {
let swap = crc16(data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x1021)
return swap.byteSwapped
}
func crc16ccitt_1d0f() -> UInt16 {
return crc16(data_order: straight_8, remainder_order: straight_16, remainder: 0x1d0f, polynomial: 0x1021)
}
func crc16ibm() -> UInt16 {
return crc16(data_order: reverse_8, remainder_order: reverse_16, remainder: 0x0000, polynomial: 0x8005)
}
}
用法示例(针对 Swift 4+ 更新了代码):
let tData = Data([0x05, 0x02, 0x03])
print(String(format: "crc16ccitt: %04X", tData.crc16ccitt())) // 716D
print(String(format: "crc16ccitt_xmodem: %04X", tData.crc16ccitt_xmodem())) // BDF1
print(String(format: "crc16ccitt_kermit: %04X", tData.crc16ccitt_kermit())) // 9638
print(String(format: "crc16ccitt_1d0f: %04X", tData.crc16ccitt_1d0f())) // ACFD
print(String(format: "crc16ibm: %04X", tData.crc16ibm())) // 6051
这些数字与 Online CRC calculator.
的结果一致