2010-11-18 66 views
0

我需要內部的無符號短提取的某些位值的好方法:提取物無符號值

的USHORT內的4個報警的定義:

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); 

問候, 約翰

回答

4
int GetFromBits(ushort bits, int offset) 
{ 
return (bits >> (offset - 1)) & 0xF; 
} 
+0

非常感謝!這確實適用於所有16位都被填充的情況。經過測試,它工作,我能夠提取所有的價值。 – 2010-11-18 13:54:40

2
bool GetBit(ushort bits, int offset) { 
    return (bits & (1<<offset)) != 0; 
} 
+0

是,只提取單個位。我要提取4個指定的位,然後得到最大值15 – 2010-11-18 13:33:57

+0

是的,我明白了。 Yossarian發佈了正確的解決方案。 – 2010-11-18 13:36:28

0

除非有使用USHORT一個特別的原因,我會強烈建議您使用 enum flags。這是C#中按位操作的預期替代。

0

使用枚舉:

[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

我正在解讀正在從硬件讀取的數據,我希望每一點都意味着什麼,但在這種情況下,每個鬧鐘可以有1到15個不同的狀態,這使得事情更加複雜。 – 2010-11-18 13:56:36

0

一個VB的範例使用枚舉標誌

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

我看到有人也在開發柴油發電機組的軟件!我發現了一種更有效的方法來管理這些警報,它們非常棘手,因爲它們中的每一個都有15種不同的狀態。 – 2010-11-25 06:34:01

+0

@Johan - 不,我不是,只是一個幸運的猜測。我試圖展示的是兩種不同的可能性。我展示瞭如何分別對待每個四位值,並使用Enums作爲值。 – dbasnett 2010-11-25 12:02:47