我正在尝试与接受/发送16位值的PLC通信,每个位都允许进行检查或不进行检查。
为此,我一直在尝试使用.Net BitArray,但结果却不成功。
底层结构由两个字节的数组组成,两个字节均初始化为0。
当我使用这些字节之一创建一个新的位数组时,我希望得到一个将8个值设置为false的数组。 情况并非如此。
字节值为0时,位数组的长度和计数也为零。尽管我可以假定前导零被删除了,但这似乎很违反直觉。
当我使用一个值为200的字节创建位数组时,我期望得到一个具有8个值的数组( True,True,False,False,True,False,False,False ) 。但是,我却得到了一个长度为 200 的位数组?
代码当前为:
Private FaultBits as Byte = 0
Public Sub SetBitValue(index As Integer, value As Boolean)
Try
If index < 0 Then
Throw New Exception("Index is below zero!")
End If
If index > 7 Then
Throw New Exception("Index out of bounds! Maximum allowed index value is 7")
End If
'If BitConverter.IsLittleEndian Then
'ToDo
'End If
Dim bitArray_Section As BitArray = Nothing
bitArray_Section = New BitArray(FaultBits)
'bitArray_Section.Length = 8 'Truncates incorrectly
bitArray_Section.Item(index) = value 'Set the individual bit
FaultBits = ConvertToByte(bitArray_Section) 'Set back to byte
Catch ex As Exception
Throw New Exception("clsFaultBits : SetBitValue : w. Index " & index & " : Exception : " & ex.Message())
End Try
End Sub
与get等效:
Public Function GetBitValue(index As Integer) As Boolean
Try
If index < 0 Then
Throw New Exception("Index is below zero!")
End If
If index > 7 Then
Throw New Exception("Index out of bounds! Maximum allowed index value is 7")
End If
Dim bitArray_Section As BitArray = Nothing
bitArray_Section = New BitArray(FaultBits)
'bitArray_Section.Length = 8
Return bitArray_Section.Item(index)
Catch ex As Exception
Throw New Exception("clsFaultBits : GetBitValue : w. Index " & index & " : Exception : " & ex.Message())
End Try
End Function
convert函数,我以为长度为8,这是错误的:
Public Function ConvertToByte(bits As BitArray) As Byte
Try
If bits.Count <> 8 Then
Throw New Exception("Invalid amount of bits!")
End If
Dim returnbyte(1) As Byte
bits.CopyTo(returnbyte, 0)
Return returnbyte(0)
Catch ex As Exception
Throw New Exception("clsFaultBits : ConvertToByte : Exception : " & ex.Message())
End Try
End Function
ByteValue :: BitarrayLength /计数
0 :: 0/0
200 :: 200/200
10 :: 10/10
我想完成的事情:
接收一个字节(1-0-0-1-0-0-1-0)
通过读取各个位来在程序中启用布尔值: Check1,Check4,Check7
设置从0-0-0-0-0-0-0-0开始的输出字节的各个位
打开5:0-0-0-0-1-0-0-0
打开2:0-1-0-0-1-0-0-0
发送字节
我完全滥用BitArray类吗?我究竟做错了什么? 是什么让我可以在不陷入混乱的情况下更改单个位的值?
为什么BitArray的长度/计数与Byte相同,而不是由Byte组成的位数?
我知道代码尚未考虑字节顺序。
预先感谢
已解决:
我没有意识到向BitArray发送一个非数组字节会将其隐式转换为整数,因此它创建了一个长度/计数相等的BitArray值为字节。现在完全有意义了。
这也使我意识到我的隐式强制转换的编译器警告不会触发,因为Byte to Integer不被视为隐式的,因为通常在发生隐式强制转换时都会得到通知。
感谢您的帮助!
答案 0 :(得分:0)
我不确定BitArray类是否是您所需要的。无论如何,您不能从Integer值创建BitArray。例如,语句New BitArray(200)
将创建200个项的BitArray,所有项均设置为0。
如果您需要发送16位值,我认为使用UShort
(也称为UInt16
)数据类型代替BitArray并使用@djv建议检查单个位会更简单。要设置位,您必须使用一些“二进制”代数和And
运算符。记住要始终使用无符号数据类型,并且要注意位数是从右开始的。
答案 1 :(得分:0)
不幸的是,BitArray不允许您与16位值之间进行转换。
但是,它确实适用于Byte()和Integer()。
所以我们可以从32位整数转换为32位整数,这应该可以正常工作。
也不清楚您如何拥有原始数据。是两个单独的字节,还是单个16位值?
我将假定一个未分配的16位值。
因此我们将获得以下代码:
Sub Testset()
Dim i16 As UInt16
i16 = 255
SetBits(i16, 9, False)
SetBits(i16, 9, True)
Debug.Print(GetBits(i16, 9).ToString)
End Sub
上面的输出
00000000 11111111
00000010 11111111
True
这两个例程是:
Public Sub SetBits(ByRef My16Bits As UInt16, MyINdex As Integer, MyValue As Boolean)
' toss the passed 16 bits into a 32 bit interger
' we do this, since the conversion routines only work
' for built in primitaves ike byte() or integer().
Dim My32(0) As Integer
My32(0) = My16Bits
Dim My32Bits As New BitArray(New Integer() {My32(0)})
My32Bits(MyINdex) = MyValue
' now convert bit array back to our 32 bit integer
My32Bits.CopyTo(My32, 0)
' now copy our 32 bit interger back to that 16 bit
My16Bits = My32(0)
For i = 15 To 0 Step -1
Debug.Write(IIf(My32Bits(i), "1", "0"))
If i = 8 Then Debug.Write(" ")
Next i
Debug.Print("")
End Sub
Public Function GetBits(My16Bits As UInt16, MyIndex As Integer) As Boolean
' convert Int16 to bit array
Dim My32(0) As Integer
My32(0) = My16Bits
Dim My32Bits As New BitArray(New Integer() {My32(0)})
Return My32Bits(MyIndex)
End Function
当然可以删除显示值的循环。
如果在您希望位数组以一种或另一种方式转换之前必须被称为“多次”-那么您可以将转换为位数组作为单独的例程分离出来,并将其传递给获取/设置位例程,然后执行代码的最终调用,将bitArrary转换回Int16值。这实际上取决于您期望获得/设置位的次数。所以1或2次,然后以上就可以了。如果必须始终测试许多位并设置许多位,则在调用+使用两个例程设置/获取值之前,将值转换为位数组。因此,可以将与位数组之间来回转换的代码分离为单独的代码。