2010-11-18 28 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