2016-02-28 42 views
5

我需要形成一个20字节的数据包,并通过蓝牙将有效载荷发送到硬件外设。如何在Swift中使用位操作?

这20字节的数据包内部分为14个数据集,每个11位,最后6位应该是空字符。

因此,总计: 160位(20个字节)= 14(套)* 11(比特)+ 6(空字符)

的11位被再次分成3组2位,3位和6位。然而,这对主要问题并不重要,我现在可以通过采用'Int16'来形成11位。我会做移位操作来过滤11位,我知道这一点。

如果我只有一个数据集,那么我应该填写所有20个字节,除了前面的11位空字符,如果两个数据集,然后除了22位之外的所有应该是空字符和分别。

我面临的问题是形成这个连续的160位,因为奇数位是11.我想采取一个'诠释'和做移位(< <)操作,然后按位或(|)但Int是64位。

目前我认为采取20个固定大小的字符数组将适合这种情况。尽管在概念上我认为这是最好的方式,但我无法通过所有条件来实现这一目标。我想我需要把所有的逻辑放在一个循环中。

任何人都可以告诉是否实现这一目标的正确方法,并指导我解决它,如果这是最好的方法。如果有的话,或者指出其他任何方式。

回答

1

您不需要将所有数据集打包成20字节的数组,直到最后,因此请将它们保存在长度为14的Int数组中。使用这种方式更容易。当您需要通过将其发送至硬件,将其转换为UInt8数组长度20:

struct DataPacket { 
    var dataSets = [Int](count: 14, repeatedValue: 0) 

    func toCArray() -> [UInt8] { 
     var result = [UInt8](count: 20, repeatedValue: 0) 
     var index = 0 
     var bitsRemaining = 8 
     var offset = 0 

     for value in self.dataSets { 
      offset = 10 

      while offset >= 0 { 
       let mask = 1 << offset 
       let bit = ((value & mask) >> offset) << (bitsRemaining - 1) 
       result[index] |= UInt8(bit) 

       offset -= 1 
       bitsRemaining -= 1 
       if bitsRemaining == 0 { 
        index += 1 
        bitsRemaining = 8 
       } 
      } 
     } 

     return result 
    } 
} 

// Usage: 
var packet = DataPacket() 
packet.dataSets[0] = 0b11111111111 
packet.dataSets[1] = 0b00000000011 
// etc... 

let arr = packet.toCArray() 

有很多移位操作回事,所以我无法解释这一切。一般的理想是将这11位数据集中的每一个分配到字节中,并根据需要溢出到下一个字节。

+0

谢谢你的详细代码。我把代码放入游乐场,并尝试了几个样本测试,它运行良好,我也了解完整的代码。再次感谢你。 :) –

1

通过代码的不同提出的解决方案的一种变体:

struct DataPacket { 
    var dataSets = [Int16](count: 14, repeatedValue: 0) 

    func getPacket() -> [UInt8] { 
     var packet = [UInt8](count: 20, repeatedValue: 0) 
     var idxPacket = 0 

     for dataSet in dataSets { 
      for idxBit in 1...11 { 
       if dataSet & 1 << (11 - idxBit) != 0 { 
        packet[idxPacket/8] |= UInt8(0b1000_0000 >> (idxPacket % 8)) 
       } 
       idxPacket += 1 
      } 
     } 

     return packet 
    } 
}