Извлечение значений без знака из определенных битов в C # ushort - PullRequest
0 голосов
/ 18 ноября 2010

Мне нужен хороший способ извлечения значений из определенных битов внутри короткого знака без знака:

Определение 4 сигналов тревоги внутри ushort:

Name......Range.......Bits
Alarm4....0-15....13/16-16/16
Alarm3....0-15....9/16-12/16
Alarm2....0-15....5/16-8/16
Alarm1....0-15....1/16-4/16

Значение ushort:4383 или (1000100011111 в двоичном формате)

Итак, чего я хочу достичь:

1001100110011001
Alarm1.....Alarm2.....Alarm3......Alarm4
1001.......1001.......1001........1001

Gets translated into:
Alarm1....Alarm2....Alarm3....Alarm4
9............9............9............9

Использование псевдокода:

getValueFunc(ushort bits, int offset);  
ushort u = 4383;
UInt16 Alarm1Value = getValueFunc(u, 1);
UInt16 Alarm2Value = getValueFunc(u, 5);
UInt16 Alarm3Value = getValueFunc(u, 9);
UInt16 Alarm4Value = getValueFunc(u, 13);

С уважением, Йохан

Ответы [ 5 ]

4 голосов
/ 18 ноября 2010
int GetFromBits(ushort bits, int offset)
{
 return (bits >> (offset - 1)) & 0xF;
}
2 голосов
/ 18 ноября 2010
bool GetBit(ushort bits, int offset) {
    return (bits & (1<<offset)) != 0;
}
0 голосов
/ 24 ноября 2010

Пример VB с использованием флагов enum

Public Class Form1

    <FlagsAttribute()> _
    Public Enum Alarms As UShort
        'bits in short
        '1 1 1 1 1 1
        '5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
        No_Alarms = 0 'do not change

        Alarm1All = &HF
        HighTemp1 = 1 << 0
        LowOilPress1 = 1 << 1
        HighRPM1 = 1 << 2
        LowRPM1 = 1 << 3

        Alarm2All = &HF0 'alarm two is a 4 bit value 0 - 15
        _bit0AL2 = 1 << 4
        _bit1AL2 = 1 << 5
        _bit2AL2 = 1 << 6
        _bit3AL2 = 1 << 7

        Alarm3All = &HF00
        Cond3_0 = 1 << 8
        Cond3_1 = 1 << 9
        Cond3_2 = 1 << 10
        Cond3_3 = 1 << 11

        Alarm4All = &HF000
        DoorAjar = 1 << 12
        O2Sensor = 1 << 13
        LightsOn = 1 << 14
        LowFuel = 1 << 15

        All_Alarms = &HFFFF 'do not change

        zAlarm1Offs = 0US
        zAlarm2Offs = 4US
        zAlarm3Offs = 8US
        zAlarm4Offs = 12US
    End Enum

    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles Button1.Click

        Dim foo As Alarms = Alarms.No_Alarms 'set no alarms
        debugAlarm(foo)

        'turn some alarms on
        foo = Alarms.HighTemp1 Or Alarms.LowOilPress1
        debugAlarm(foo)

        'turn some more on
        foo = foo Or Alarms._bit0AL2 Or Alarms._bit3AL2 Or Alarms.Cond3_2 Or Alarms.Cond3_3 Or Alarms.LightsOn Or Alarms.LowFuel
        debugAlarm(foo)

        'check Alarm4
        If (foo And Alarms.Alarm4All) <> Alarms.No_Alarms Then 'any fours on
            'check which 4
            If (foo And Alarms.DoorAjar) = Alarms.DoorAjar Then
                'Cond4_0 on
                Stop
            ElseIf (foo And Alarms.O2Sensor) = Alarms.O2Sensor Then
                'Cond4_1 on
                Stop
            ElseIf (foo And Alarms.LightsOn) = Alarms.LightsOn Then
                'Cond4_2 on
                foo = foo And (Alarms.All_Alarms Xor Alarms.LightsOn) 'turn off Cond4_2
            ElseIf (foo And Alarms.LowFuel) = Alarms.LowFuel Then
                'Cond4_3 on
                Stop
            End If
        End If
        debugAlarm(foo)

        'check Alarm2 
        If (foo And Alarms.Alarm2All) <> Alarms.No_Alarms Then 'any twos on
            'check Alarm2 for values
            Select Case CUShort(foo And Alarms.Alarm2All) 'foo And Alarms.Alarm2All
                Case 1US << Alarms.zAlarm2Offs 'Alarms._bit0AL2
                    Stop
                Case 2US << Alarms.zAlarm2Offs 'Alarms._bit1AL2
                    Stop
                Case 3US << Alarms.zAlarm2Offs 'Alarms._bit0AL2 or Alarms._bit2AL2
                    Stop
                Case 4US << Alarms.zAlarm2Offs
                    Stop
                Case 5US << Alarms.zAlarm2Offs
                    Stop
                Case 6US << Alarms.zAlarm2Offs
                    Stop
                Case 7US << Alarms.zAlarm2Offs
                    Stop
                Case 8US << Alarms.zAlarm2Offs
                    Stop
                Case 9US << Alarms.zAlarm2Offs
                    debugAlarm(foo And Alarms.Alarm2All)
                    Stop
                Case 10US << Alarms.zAlarm2Offs
                    Stop
                Case 11US << Alarms.zAlarm2Offs
                    Stop
                Case 12US << Alarms.zAlarm2Offs
                    Stop
                Case 13US << Alarms.zAlarm2Offs
                    Stop
                Case 14US << Alarms.zAlarm2Offs
                    Stop
                Case 15US << Alarms.zAlarm2Offs
                    Stop
            End Select
        End If
        debugAlarm(foo)

    End Sub

    Private Sub debugAlarm(ByVal _alarm As Alarms)
        Debug.WriteLine("")
        Dim asUshort As UShort = _alarm
        Debug.WriteLine(_alarm.ToString)
        Debug.WriteLine(Convert.ToString(asUshort, 2).PadLeft(16, "0"c))
    End Sub
End Class
0 голосов
/ 18 ноября 2010

Использовать перечисления:

[Flags]
public enum Alarm : int
{
    AlarmValue1 = 0x1,
    AlarmValue2 = // the Hex Value,
    AlarmValue3 = // the Hex Value,
    AlarmValue4 = // the Hex Value

}


ushort myValue = 0x687;
Alarm alarm = (Alarm) myValue;

Console.WriteLine(alarm & AlarmValue3);
0 голосов
/ 18 ноября 2010

Если нет особых причин использовать ushort, я настоятельно рекомендую использовать enum flags .Это была предполагаемая замена для побитовых операций в C #.

...