Bitweise setzen einer Integer Variable

Gibt es eine Lösung die einfach ist und funktioniert?

In anderen Sprachen wird das 2. Bit einer Variable mit Test.1=1 gesetzt.

Da bleiben andere Bit’s unberührt.

Ich habe das hier probiert… geht nicht. kann mir jemand helfen?

SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,0);
$Pokey_Bit1 = GetValueBoolean(44236 /*[ModBus Pokey\ModBus Gerät Adresse 00\Value]*/);
if ($Pokey_Bit1 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) or 1)) ;
}
Else
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) and 0xFE)) ;
}
$Pokey_Bit2 = GetValueBoolean(36861 /*[ModBus Pokey\ModBus Gerät Adresse 01\Value]*/);
if ($Pokey_Bit2 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) or 2)) ;
}
Else
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) And 0xFD)) ;
}
$Pokey_Bit3 = GetValueBoolean(57447 /*[ModBus Pokey\ModBus Gerät Adresse 02\Value]*/);
if ($Pokey_Bit3 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) or 4)) ;
}
Else
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) and 0xFC)) ;
}
$Pokey_Bit4 = GetValueBoolean(56118 /*[ModBus Pokey\ModBus Gerät Adresse 03\Value]*/);
if ($Pokey_Bit4 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) or 8)) ;
}
Else
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) and 0xFB)) ;
}
$Pokey_Bit5 = GetValueBoolean(52783 /*[ModBus Pokey\ModBus Gerät Adresse 04\Value]*/);
if ($Pokey_Bit5 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) or 16)) ;
}
Else
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) and 0xFA)) ;
}

Danke und Gruß
Helmut

Hallo
Zum setzen eines Bits nehme ich immer die ODER Funktion

$x = $x | 2

setze Bit 2.

Eine Funktion zum Testen wuerde so aussehen.

	$var = 2;

	for($x=0;$x<=16;$x++)
	   echo "
" . setze_bit($var,$x);
 
function setze_bit($x,$bit)
	{
	$bit = 1 << $bit;
	$x = $x | $bit ;
	return $x;
	}

Setze in der Variablen $var nacheinander jeweils das xte Bit.

Guten Morgen,

ja, so habe ich in der „1“ Abfrage auch gedacht.

Das Ergebniss ist aber falsch, da muß ich was falsch gedacht haben.

Ohne die Variable in anderen Bitstellen zu beeinflussen setze ich mit ODER das Bit und mit UND, bei der Else-Bedingung, mache ich es geziehlt zu „0“. Dachte ich…

Gruß Helmut

Man beachte

	$x = $x &    0xFA ; echo "
".$x;  // 250
	$x = $x &&   0xFA ; echo "
".$x;  // 1
	$x = $x and  0xFA ; echo "
".$x;  // 1

Also dein Fehler oben ist ja wohl das du nicht & und | verwendest. Ansonsten könnte man das aber auch eleganter bauen. Nur mal so eben als Schnellschuss


$ist = GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/);

$Bit[0] = GetValueBoolean(44236 /*[ModBus Pokey\ModBus Gerät Adresse 00\Value]*/);
$Bit[1] = ...

for each ($Bit as $key => $val) {
   $BitVal = Pow(2,$key) * $val;
   $ist = $ist & $BitVal | $BitVal;
}

SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/, $ist);

Das Auslesen am Anfang brauchen wir auch nur, wenn es noch weitere gespeicherte Bits gibt die nicht verändert werden sollen. Sonst kann man das weglassen und in der Schleife nur $ist += Pow(2,$key) * $val;

Gruß,
Jan

So, hier ist meine Lösung:

//   *************************   Fenster  und Türen an den ersten 6 Eingängen vom Modbus   ***************
//           die werden Oder verknüpft mit dem gesamten Integerwert (LowByte Touch Display Zustand EG)
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,0);
$Pokey_Bit1 = GetValueBoolean(44236 /*[ModBus Pokey\ModBus Gerät Adresse 00\Value Kuechen Fenster]*/);
if ($Pokey_Bit1 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/, (GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) | 1)) ;
}
if ($Pokey_Bit1 == 0)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/, (GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) & 0xFE)) ;
}
$Pokey_Bit2 = GetValueBoolean(36861 /*[ModBus Pokey\ModBus Gerät Adresse 01\Value Wz Terrassentuer]*/);
if ($Pokey_Bit2 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) | 2)) ;
}
if ($Pokey_Bit2 == 0)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) & 0xFD)) ;
}
$Pokey_Bit3 = GetValueBoolean(57447 /*[ModBus Pokey\ModBus Gerät Adresse 02\Value Wz Fenster links]*/);
if ($Pokey_Bit3 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) | 4)) ;
}
if ($Pokey_Bit3 == 0)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) & 0xFB)) ;
}
$Pokey_Bit4 = GetValueBoolean(56118 /*[ModBus Pokey\ModBus Gerät Adresse 03\Value Wz Fenster rechts]*/);
if ($Pokey_Bit4 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) | 8)) ;
}
if ($Pokey_Bit4 == 0)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) & 0xF7)) ;
}
$Pokey_Bit5 = GetValueBoolean(52783 /*[ModBus Pokey\ModBus Gerät Adresse 04\Value Eingangstuer]*/);
if ($Pokey_Bit5 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) | 16)) ;
}
if ($Pokey_Bit5 == 0)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) & 0xEF)) ;
}
$Pokey_Bit6 = GetValueBoolean(54601 /*[ModBus Pokey\ModBus Gerät Adresse 05\Value Fenster Bad u.]*/);
if ($Pokey_Bit6 == 1)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) | 32)) ;
}
if ($Pokey_Bit6 == 0)
{
SetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/,(GetValueInteger(18005 /*[USB Display\Erdgeschoss_Zustand_Low_Byte]*/) & 0xDF)) ;
}

IPS_RunScript(57711 /*[USB Display\USB Display beschreiben]*/);

Ich habe diese Lösung durch try and error erreicht, Die auch die anderen Bits „heil“ läßt und auch wieder richtig rücksetzt.

Gruß Helmut

Danke Jan,
ich verstehe den Code noch nicht so richtig, aber wenn der die vorhandenen Bit’s stehen läßt und auch richtig (bei „Low“) zurücksetzt, dann paßt er auch zu der Aufgabe.

Dachte auch, dass der Befehl OR nur mit „|“ abgekürzt wird…dann hatte ich noch falsche Hex-Werte in der „AND“-Zeile genommen…

Ich muß zugeben: PHP lerne ich nie so richtig, habe zu wenig damit zutun…
So REM-Zeilen wären hilfreich.
Gruß Helmut

Hallo Helmut,

habe auf der PHP Page auch noch einige Funktionen zum Setzen von Bits gefunden:


	$var = 0;

	echo (debug($var)).PHP_EOL;
	$var = SetBit($var,1);
	echo (debug($var)).PHP_EOL;
	$var = SetBit($var,2);
	echo (debug($var)).PHP_EOL;
	$var = SetBit($var,7);
	echo (debug($var)).PHP_EOL;
	$var = SetBit($var,4);
	echo (debug($var)).PHP_EOL;
	$var = ClearBit($var,2);
	echo (debug($var)).PHP_EOL;


   function setbit($val, $bit) {
       if (readbit($val, $bit)) return $val;
       return $val += '0x'.dechex(1<<($bit-1));
   }

   function clearbit($val, $bit) {
       if (!readbit($val, $bit)) return $val;
       return $val^(0+('0x'.dechex(1<<($bit-1))));
   }

   function readbit($val, $bit) {
       return ($val&(0+('0x'.dechex(1<<($bit-1)))))?'1':'0';
   }

   function debug($var, $bitlength=8) {
       for ($j=$bitlength;$j>0;$j--) {
           echo readbit($var, $j);
           if ($j%4 == 1) echo ' ';
       }
   }


Danke Dir Andreas,

ich lasse beide Beispiele gerade mal in meinen Kopf einwirken :wink:

Ich hatte das KNX/EIB-Display ja gerade in der EIB-Abteilung vorgestell und da dachte ich, ich verheirate mein Touch-Display (nicht das von dem EIB-Vorschlag) mal mit USB-HID und Pokey56E und IPSymcon.

Das kostet immer ein Gehirnschmalz und Zeit…aber macht Spaß :wink:

Gruß Helmut

Edit: Jan’s Codeschnipsel würde eine Schleife gebrauchen, Andreas Beispiel zeigt mehr Möglichkeiten.
Danke euch beiden !!!

man braucht in diesem Fall die „und“ und „oder“ Verknüpfung

hier mein beispiel:

$bit = 0;   //nummer des Bit's
$value = 1;   // true oder false
$integer  = 16; // integerwert

$integer &= ~(1 << $bit);     // setzt das Bit mit "und" Verknüfung auf false(0)
$integer |= ($value << $bit); // setzt das Bit mit "oder" Verknüpfung entsprechend $value (0 oder 1)

echo $integer;

@Bewohner von localhost

Super, danke sehr! Ich versuche mich mal mit toogeln heute Abend;-)

Gruß Helmut

Edit: Tooglen, ohne verändern der anderen Bits, versucht, sollte funktionieren:

<?
// Bitweise toogeln eines Integerwertes ohne Zerstörung des Restes
$bit = 3;   //nummer des Bit's
$integer  = 1; // integerwert

//echo " ";
//echo $integer;
$integer1 = (($integer OR !$integer) << $bit);
//echo " ";
//echo $integer1;

$erg = ($integer - $integer1);
//echo " ";
//echo $erg;
if ($erg < 0) $erg = ($erg*-1)+$integer+$integer;

//echo " ";
echo $erg;
?>