VBnet Доступ к отдельным битам байта // Длина и количество битов массива равны значению байта? - PullRequest
1 голос
/ 06 марта 2019

Я пытаюсь связаться с ПЛК, который принимает / отправляет 16-битные значения, причем каждый отдельный бит позволяет выполнять проверку или нет.

Для этого я пыталсяиспользовать .Net BitArray, но результаты были далеко не успешными.

Структура подложки состоит из массива из двух байтов, оба байта инициализируются значением 0.

Когда ясоздать новый битрейр, используя один из этих байтов, я ожидал получить массив с 8 значениями, установленными в false. Это не так .

При байтовом значении 0 длина и количество битрейров также равны нулю.Хотя я мог предположить, что ведущие нули отбрасываются, это кажется очень нелогичным.

Когда я создаю битовый массив, используя байт со значением 200, я ожидал получить массив с 8 значениями ( True,Правда, Ложь, Ложь, Правда, Ложь, Ложь, Ложь ).Однако вместо этого я получаю битовый массив с длиной и счетом 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

Функция преобразования, я предполагал, что она будет иметь длину 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 / Count

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 неявно приведёт его к целому числу и, следовательно, создаст BitArray, у которого длина / число равно значению байт .Что теперь имеет смысл.

Это также заставило меня осознать, что предупреждение моего компилятора о неявном приведении не срабатывает, поскольку Byte to Integer не считается неявным, поскольку я обычно получаю уведомление всякий раз, когда происходит неявное приведение.*

Спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

К сожалению, BitArray не позволяет вам конвертировать в / из 16-битного значения.

Однако он работает для Byte () и Integer ().

Так что мы можем конвертировать из/ 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 раза, затем выше, это нормально.Если вам нужно всегда проверять много битов и устанавливать много битов, то перед вызовом + конвертируйте значение в битовый массив, используйте две подпрограммы для установки / получения значения.Таким образом, код, который преобразуется в битовый массив и из него, может быть выделен как отдельный код.

0 голосов
/ 07 марта 2019

Я не уверен, что класс BitArray - это то, что вам нужно.В любом случае вы не можете создать BitArray из целочисленного значения.Например, оператор New BitArray(200) создаст BitArray из 200 элементов, все из которых установлены на 0. Если вам нужно отправить 16-битные значения, я думаю, что было бы проще использовать вместо этого тип данных UShort (также называемый UInt16).BitArray и используйте предложение @djv для проверки одного бита.Чтобы установить биты, вы должны использовать некоторую «двоичную» алгебру и оператор And.Не забывайте всегда использовать типы данных без знака и помните, что счетчик битов начинается справа.

...