Seite 1 von 2
Nur ein Bit ändern
Verfasst: Samstag 21. Februar 2026, 21:49
von kiaralle
Hallo,
wie kann ich bei einem 8bit das 7. bit ändern?
Aufbau bit 7 ....... bit 0
Ist 10100110
Soll 00100110
Gruß Ralf
Re: Nur ein Bit ändern
Verfasst: Samstag 21. Februar 2026, 22:02
von Sirius3
Dafür gibt es bit-Operationen:
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 08:56
von kiaralle
Danke, ich hatte auch was gefunden aber das war nicht so schön erklärt.
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 12:24
von nezzcarth
kiaralle hat geschrieben: Sonntag 22. Februar 2026, 08:56
Danke, ich hatte auch was gefunden aber das war nicht so schön erklärt.
"Bitmaske" ist hier der Fachbegriff für die weitere Suche.
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 14:32
von kiaralle
Was möchte ich überhaupt machen.
Ich bekomme ein Hex der zum Beispiel "C9" ist
Diesen kann ich wenn nötig direkt auf Int umwandeln ... wäre 201.
Diese beiden Ergebnisse stellen dann eigentlich meine Binärzahl 11001001 dar, welche den Aufbau und Funktion eines Datenfeldes im Speicher wiedergeben.
Möchte ich das Datenfeld aus dem Speicher löschen, so wird nur das 7.bit auf 0 gesetzt. der Rest bleibt im Speicher als "unsichtbar" bestehen.
Alles andere ist erst einmal unwichtig.
Sehe ich es richtig, das ein reines 11001001 nicht funktioniert? Es benötigt immer das 0b vor meiner Binärzahl bei bin() benötigt?
Code: Alles auswählen
df_status_int = 201
df_status_bin = bin(df_status_int)#[2:].zfill(8)
print(df_status_bin)
df_status_bin = df_status_bin & ~(1 << 7)
print(df_status_bin)
Error: unsupported operand type(s) for &: 'str' and 'int'
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 16:19
von __blackjack__
@kiaralle: Ein ”reines” 11001001 ist die Dezimalzahl elf Millionen und eintausend und eins. 0b11001001 ist die Dezimalzahl 201. `bin()` liefert eine Zeichenkette und keine Zahl und mit Zeichenketten kann keine Bitoperationen durchführen. Das macht also keinen Sinn die 201 in eine Zeichenkette in Binärdarstellung zu wandeln. Rechnen und Bitoperationen macht man mit Zahlen, nicht mit Zeichenketten. In eine Zeichenkette würde man das vielleicht zur Anzeige umwandeln wenn der Benutzer oder der Programmierer das gerne mal in Binärdarstellung sehen möchte. Ansonsten ist das 201 und nach dem löschen des Bits 73 dezimal (oder C9 und 49 hexadezimal, oder 311 und 111 oktal, …). Das sind ja alles nur verschiedene Darstellungen der selben beiden Zahlen als Zeichenketten.
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 18:47
von kiaralle
So, meine doch etwas andere Lösung. Warum nicht gleich mit Hex rechnen.
Ich bekomme den Status meines Datenfeldes gemeldet..... Hex C8
Ich weiß , dass ich immer 10.000.000 abziehen muss um das Datenfeld abzuschalten..... Hex 80
C8 = 11001000
- 80 = 10000000
48 = 01001000
Also rechnen wir,
Code: Alles auswählen
hex_a ="C8"
hex_b = "80"
hex_c = hex(int(hex_a,16) - int(hex_b,16))[2:]
print(hex_c)
Ergebniss = 48
Damit kann ich den Datensatz löschen.
Jetzt muss ich an das erstellen des neuen Datenfeldes gehen, den ich wieder als Hex schreiben kann.
bit
7 Datenfeld aktiv
6 beschreibbar
5/4 Passwort 0-3
3 Passwort aktiv
2/1/0 Speichergröße 16/32/64.....
Es bleibt wie immer spannend
Danke noch mal in die Runde.
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 19:20
von Sirius3
@kiaralle: Wenn Du Zahlen hast, dann solltest Du auch mit Zahlen rechnen und nicht immer alles in Strings umwandeln. Natürlich kann man dann für die Ausgabe ein passendes Ausgabeformat wählen.
Auch den Input wirst Du ja in irgendeiner binären Form erhalten und nicht als Hexadezimaldarstellung.
Minus zu benutzen hat das Problem, falls das Bit gar nicht gesetzt war, dass dann ein komisches Ergebnis rauskommt. Das ist beim binären UND nicht der Fall.
Code: Alles auswählen
eingabe = 0xC8
ergebnis = eingabe & 0x7F
print(f"{ergebnis:02x}")
Besser man benutzt statt kryptischer Zahlen IntFlags:
Code: Alles auswählen
import enum
class AccessBits(enum.IntFlag):
ACTIVE = 0x80
WRITEABLE = 0x40
PASSWORD = 0x30
PASSWORD_ENABLED = 0x08
SIZE = 0x07
value = 0xC8
value &= ~AccessBits.ACTIVE
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 20:33
von kiaralle
Danke für deine Hilfe und Hinweise.
Ich erhalte den Input wirklich als Hex.
Deshalb war es für mich logisch und mit meine Wissensstand kann ich nur so vorzugehen.
Hier habe ich vorher die Anzahl der Datenfelder abgefragt.
Dann lese ich den Aufbau der Datenfelder aus.
Ich wandle den response der als Hex kommt in Bin um und kann so schön die Info der einzelnen Positionen auswerten.
Das funktioniert. Deinen Weg muss ich erst verstehen und werde es dann versuchen umzusetzen.
Code: Alles auswählen
i= 0
while i <= number_of_datafields -1:
df = "{:02x}".format(i)
data = bytearray.fromhex("FF 4C" + df)
data.append(ChecksumXor8.calc(data))
try:
serial_interface.reset_input_buffer()
serial_interface.reset_output_buffer()#flush output buffer, aborting current output
time.sleep(0.010) #give the serial port sometime to receive the data
serial_interface.write(data)
time.sleep(0.01)
response = serial_interface.read(7)
if response.hex()[2:4] == "50" or ChecksumXor8.calc(response) != 0:
self.info_error["text"] = sick_error.srm_errors(response.hex()[4:6])
else:
datenfeld_int=int.from_bytes(response[3:4],'big',signed=False)
datenfeld_bin =bin(datenfeld_int)[2:].zfill(8)
df_mem =str((int(datenfeld_bin[5:])+1) *16)
df_nummer = "\n" + str(i) + " \t"
i+=1
if int(datenfeld_bin[0:1]) == 0:
df_enable = "nein\t"
else:
df_enable = "ja\t"
if int(datenfeld_bin[1:2]) == 0:
df_writable = "nein\t"
else:
df_writable = "ja\t"
df_password = str(int(datenfeld_bin[2:4])) +"\t"
if int(datenfeld_bin[4:5]) == 0:
df_password_aktiv = "nein\t"
else:
df_password_aktiv = "ja\t"
data = df_nummer + df_enable + df_writable + df_password + df_password_aktiv + df_mem
self.datenfeld_info.insert('end',data)
except Exception as e1:
print ("error communicating...: " + str(e1))
self.datenfeld_info.config(state='disabled')
Re: Nur ein Bit ändern
Verfasst: Sonntag 22. Februar 2026, 21:42
von Sirius3
Also, Du wandelst ein `i` in Hex um, um es gleich danach wieder über bytearray.fromhex in Bytes umzuwandeln. Dann liest Du sieben Bytes und wandelst diese in Hex um.
Oder `datenfeld_int in eine Binärdarstellung um diese dann als Dezimalzahl zu interpretieren.
Also: Nein, Du bekommst keine Hex- oder Binärdaten, sondern bist selbst dafür verantwortlich, dass das alles so kompliziert ist.
Deine while-Schleife sollte eine for-Schleife sein und statt auf einer String-Repräsentation Deiner Zahlen solltest Du direkt mit den Zahlen selbst arbeiten:
Code: Alles auswählen
for i in range(number_of_datafields):
data = bytearray([0xff, 0x4c, i])
data.append(ChecksumXor8.calc(data))
try:
# flush output buffer, aborting current output
serial_interface.reset_input_buffer()
serial_interface.reset_output_buffer()
time.sleep(0.010)
serial_interface.write(data)
# give the serial port sometime to receive the data
time.sleep(0.01)
response = serial_interface.read(7)
if response[0] == 0x50 or ChecksumXor8.calc(response) != 0:
self.info_error["text"] = sick_error.srm_errors(hex(response[1]))
else:
datenfeld = response[3]
mem = datenfeld & AccessBits.SIZE
enabled = "ja" if datenfeld & AccessBits.ACTIVE else "nein"
writeable = "ja" if datenfeld & AccessBits.WRITEABLE else "nein"
password = datenfeld & AccessBits.PASSWORD
password_active = "ja" if datenfeld & AccessBits.PASSWORD_ENABLED else "nein"
info = f"\n{i}\t{enabled}\t{writeable}\t{password}\t{password_active}\t{mem}"
self.datenfeld_info.insert('end', info)
except Exception as error:
print(f"error communicating...: {error}")
self.datenfeld_info.config(state='disabled')
Re: Nur ein Bit ändern
Verfasst: Montag 23. Februar 2026, 17:40
von kiaralle
@Sirius
Du zeigst mir gerade neue Wege auf.
Das scheint ja wirklich einfacher zu sein als mein Weg.
Mein Code hat jetzt zwar ca. 1000 Zeilen aber ich habe keinen Zeitdruck und ich werde deine Tipps annehmen und den Code umschreiben.
Schön das du mir den Weg zeigst.
Mein Programm funktioniert zu 90% und ich kann es zur Montage von Gebern am Servomotor bereits verwenden.
Aber ich lerne gern was dazu.
Bin halt doch nur ein Schlosser

Aber das wird...
Danke
Re: Nur ein Bit ändern
Verfasst: Montag 23. Februar 2026, 19:14
von kiaralle
Noch mal ich,
ich habe mal deinen Code als Versuch genommen.
Die Variable "datenfeld" zeigt mir jetzt 200 an.
Damit kann ich ja so nichts anfangen. Ich benötige wieder die 11001000 um zu schauen welches bit wie gesetzt ist.
Oder hab ich es noch nicht ganz verstanden?
Wie kommt man sonnst an AccessBits.SIZE.... ?
1
data = bytearray([0xff, 0x4c, 0x01])
data.append(ChecksumXor8.calc(data))
try:
serial_interface.reset_input_buffer()
serial_interface.reset_output_buffer()
time.sleep(0.010)
serial_interface.write(data)
time.sleep(0.01)
response = serial_interface.read(7)
if response[0] == 0x50 or ChecksumXor8.calc(response) != 0:
print(sick_error.srm_errors(hex(response[1])))
else:
datenfeld = response[3]
"""
mem = datenfeld & AccessBits.SIZE
enabled = "ja" if datenfeld & AccessBits.ACTIVE else "nein"
writeable = "ja" if datenfeld & AccessBits.WRITEABLE else "nein"
password = datenfeld & AccessBits.PASSWORD
password_active = "ja" if datenfeld & AccessBits.PASSWORD_ENABLED else "nein"
"""
print(datenfeld) # 200
except Exception as error:
print(f"error communicating...: {error}")
Re: Nur ein Bit ändern
Verfasst: Montag 23. Februar 2026, 19:47
von __blackjack__
@kiaralle: Da kommt man dran in dem man alle anderen Bits ausmaskiert. Du musst Dir wirklich mal diese Operationen anschauen was die machen. Bei 200 hat ”size” den Wert 0:
Re: Nur ein Bit ändern
Verfasst: Montag 23. Februar 2026, 20:13
von DeaD_EyE
Code: Alles auswählen
def set_bit(data: int, bit: int, value: bool):
"""
Set or clear a bit of given data and return it.
Look here: https://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching
"""
return data ^ (-value ^ data) & (1 << bit)
Re: Nur ein Bit ändern
Verfasst: Montag 23. Februar 2026, 20:48
von kiaralle
Mal sehen ob ich es richtig verstanden habe.
Mit 0b10000000 frage ich das 7.bit ab mit mit 0b01000000 das 6.bit?...
enabled = "ja" if datenfeld & 0b10000000 else "nein"..... sagt bei 200 = 11001000 ... ja
Re: Nur ein Bit ändern
Verfasst: Montag 23. Februar 2026, 21:59
von DeaD_EyE
Ja, ich würde es aber so nicht im Quelltext verwenden.
Code: Alles auswählen
BIT6 = 1 << 6
value = 255
if BIT6 & value:
print("Bit 6 ist gesetzt")
Man muss wissen, dass ein bool(0) immer False ergibt und alle andere Zahlen (auch negativ) ein bool(x) == True.
Die if-Anweisung fragt den boolschen Wert eines Objektes ab und bool ist von int vererbt.
Noch einfacher ist es sich eine Funktion zu schreiben:
Code: Alles auswählen
def get_bit(value: int, bit: int) -> bool:
return bool(value & 1 << bit)
Und falls du mehrere Bits auf einmal prüfen möchtest:
Code: Alles auswählen
from typing import Iterable
def get_bits(value: int, bits: Iterable[int]) -> list[bool]:
return [bool(value & 1 << bit) for bit in bits]
oder als Dict zurückgeben:
Code: Alles auswählen
def get_bits(value: int, bits: Iterable[int]) -> list[bool]:
return {bit: bool(value & 1 << bit) for bit in bits}
Oder wenn z.B. nur ein True zurückgegeben werden soll, wenn mehrere Bits gleichzeitig gesetzt sind.
Code: Alles auswählen
def is_set(value: int, bits: Iterable[int]) -> list[bool]:
mask = sum(1 << bit for bit in bits)
return value & mask == mask
PS: Die Typehints sind nicht notwendig. Das kannst auch wieder entfernen, da es keinen Einfluss auf das Programm hat. Das macht nur Sinn, wenn man konsistent Typehints nutzt oder eine Bibliothek schreibt.
Re: Nur ein Bit ändern
Verfasst: Montag 23. Februar 2026, 23:01
von Sirius3
@DeaD_EyE: oder man nimmt, wie ich ja schon gezeigt habe, ein enum.IntFlag, denn dann hat man sprechende Namen, statt irgendwelcher Bit-Werte.
Re: Nur ein Bit ändern
Verfasst: Dienstag 24. Februar 2026, 10:57
von DeaD_EyE
Sirius3 hat geschrieben: Montag 23. Februar 2026, 23:01
@DeaD_EyE: oder man nimmt, wie ich ja schon gezeigt habe, ein enum.IntFlag, denn dann hat man sprechende Namen, statt irgendwelcher Bit-Werte.
Das kann man auch machen, aber dann lernt man nichts über Bit-Manipulation und spätestens wenn Datenblätter verstehen muss, hat man ein Problem das Protokoll zu verstehen.
Nehmen wir z.B. das Modul, mit dem ich mich gerade beschäftige. Es geht um die Ansteuerung von Dosierpumpen einer VT-Anlage:
Technologiemodul TM Pulse 2x24V
Siemens war so nett, Datentypen bereitzustellen, aber in vielen Fällen muss man das auch selbst machen.
D.h. wenn man z.B. später im Beruf SPS programmieren will, muss man die Bit-Manipulation verstehen. Wenn man jedes Mal Nachlesen muss, kommt man nicht weit.
Re: Nur ein Bit ändern
Verfasst: Dienstag 24. Februar 2026, 12:27
von kiaralle
Ich teste das heute Abend.
Ich sehe jetzt Licht am Ende des Tunnels.
Aber, wie Werte ich zum Beispiel drei Bits aus.
Bit 0-2 zeigen mir die Speichergröße an.
Bit 0-2 = 000 = (1 +bit) x 16 = 16
001 = (1+ bit) x16 = 32
....
Geht das auch auf diesen Wege?
Re: Nur ein Bit ändern
Verfasst: Dienstag 24. Februar 2026, 15:50
von __blackjack__
@kiaralle: Das hatte ich doch schon gezeigt. Wenn man die letzten drei Bits haben möchte, dann muss man die anderen einfach alle ausmaskieren mit ``&`` und 0b111 oder 0x07 oder 0o007 oder 7. Das sind ja alles nur verschiedene Schreibweisen für den gleichen Wert. Also: