Bitmanipulation

Gast #92056
Hallo

Ich steh gerade etwas auf dem Schlauch Leute.

Fall1:
Variable X1 = 01010100
Maske       = 00000001

Fall2:
Variable X1 = 01010101
Maske       = 00000000

Wie muss ich das Vernküpfen, um nur das Bit 0 ( also das rechte) je
nach Zustand der Maske zu verändern, während die anderen ihren Zustand
halten sollen.
Ich finde gerade keine Lösung dafür.
Gast
Danke Hagen

dein 1. Ansatz funktioniert.
hab gedacht sowas wäre einfacher zu realisieren.

Mit dem XOR hatte ich auch schon gespielt, aber da kann ich das Bit nur
toggeln lassen. Es wird nur im Fall 1 der Wert der Maske angenommen.
Fall2 geht damit nicht.
Aber ich hab ja schonmal einen Lösungsweg.
Gast
die XOR Operation oben ist aber nur das was die Kombination aus
and/or/not macht. Sie müsste entsprechend deinen Vorderungen
funktionieren ?!

Beide Lösungen toggln das Bit wenn in Maske das entsprechende Bit auf 1
gesetzt wurde. Alle Bits die 0 in der Maske sind bleiben unverändert.
Somit sind beide Vorschläge identisch.

Deine Fragestellung ist nicht ganz eindeutig.

Gruß Hagen
Gast
Hast schon recht mit der Fragestellung, und das mit dem XOR stimmt auch.
So wie ich das beim 2 mal testen sehe.

Das Ding, was ich haben will, gibt es wohl garnicht.
Ich will nicht toggel, sondern Die Variable soll den Zustand der Maske
an einer bestimmten Stelle ( Bit n) übernehemen.
 Ich werde mir da einfach eine andere Logik überlegen müssen
Gast
Naja, geht zumindest nicht in einem Schritt, aber vielleicht so:

- alle nicht zu verändernden Bits in Maske auf 1 setzen
- X1 mit Maske UND verknüpfen
- X1 mit Maske ODER verknüpfen
Gast
Ähmmm, nicht ganz, war zu schnell :-=

- alle nicht zu verändernden Bits in Maske auf 1 setzen
- X1 mit Maske UND verknüpfen
- alle nicht zu verändernden Bits in Maske auf 0 setzen
- X1 mit Maske ODER verknüpfen
"sondern Die Variable soll den Zustand der Maske
an einer bestimmten Stelle ( Bit n) übernehemen."

Und woher soll die Funktion wissen, welche Bits übernommen werden
sollen ?

Du brauchst also immer 2 Variablen, eine Maske, die sagt welche Bits
übernommen werden und einen Wert, der dann übernommen wird, z.B.:

alt:   00001111
maske: 00110011
wert:  01010101
---------------
neu:   00011101

neu = (alt & ~maske) | (wert & maske);


Peter
Gast
schön aber, warum nennst du eine Variable X?
nenne sie doch einfach var oder v?
oder in dem Fall M für "Maske"!

dann bist du wenn du dir das ganze in 3 Wochen nochmals anschaust
gleich klug und must nicht noch mal hin und herschauen!!
Gast
@ULI
X1 steht für eine bestimmte Vorgabe, und trägt numal diese Bezeichnung.


Ich will mit dieser Bitmanipulation eine serielle Information in ein
Byte einlesen.
Aber das läuft irgendwie noch nicht.
An PORTD PIND5 liegt jeweils immer das Eingangssignal z.B. 01010101
oder so.

Codeschnipsel:

int i;
int mask;
int wert;
int delaytime;

for(i=0;i<=7;i++)
{
mask=0x01;
mask=mask<<i;

wert=bit_is_set(PIND,PIND5);
wert=wert<<i;

delaytime_x1=((delaytime_x1&(~mask)) | (wert&mask));
}

Sollte doch aller Logik nach funktionieren.
Aber, delaytime steht dann immer auf null oder eins, aber nimmt nie den
Wert des Eingans an.

Ich nerve ja ungern mit so Pillepalle Zeug, aber das Ding sollte bis
Mittag fertig sein.
Gast
Hmmm, zunächst mal sollte delaytime_x1 vor der Schleife initialisert
werden (z.B. delaytime_x1 = 0 ).
Was mir nicht ganz klar ist, wie Du das Einlesen der ja quasi seriell
am PIND5 anliegenden Signalfolge synchronisieren willst.
Wenn Du die Schleif so wie angegben durchläufst, ist es gut möglich,
das da dann halt PIND5 immer 0 oder 1 hat und damit dann eben nur
00000000 bzw. 11111111 drinsteht.
Oder hab ich es irgendwie nicht ganz begriffen?

Gruß
Ingo
Gast
Hallo Ingo

hast schon recht, das ist aus dem Code nicht ersichtbar.
Ich hab mal den vollständigen Code angehangen.
An PORTD,PIND5 liegt ein wechselndes Signal an.
Das Sagt mir mein OSZI.
Angehängte Dateien:
Gast
Ahso, nun hab ich's wohl begriffen.
Es sollen also 8 Schalter abgefragt werden, die Gemuxt sind.
Ich denke mal, da kann man sich das ganze Bit-Verwurschteln sparen, und
einfach vor Begin der Schleife X1 auf 0 setzen.
In der Schleife zunächst X1 einmal nach links schieben.
Dann einfach X1 mit dem Wert verodern.

also etwas so:

delaytime_x1 = 0;
for(i=0;i<=7;i++)
{
  PORTB=i;
  delaytime_x1 = delaytime_x1<<1;
  wert=bit_is_set(PIND,PIND5);
  delaytime_x1 = delaytime_x1 | wert;
}
Gast
Aber damit kann ich dann den Zustand nur der Schalter nur einmal
einlesen.
Die Abfrage, läuft aber dauernt in der For(;;).
Daher brauche ich X1 auch nicht initialisieren, da der Zustand  sich eh
ständig ändern kann.
Ich will ja evtl. auch mal die Bits zurücksetzen. Das geht aber nicht
mir dem verodern.

Bei einer einmaligen Abfrage geben ich dir natürlich recht.
Gast
Achso, weil Du asynchron auf delaytime_x1 in Interrupt0 zugreifen
willst, oder?
Na dann mußt Du es doch so machen, wie in Deinem Programm, nur die
Veknüpfung scheint nicht ganz zu stimmen.
So etwas könnte es gehen:

delaytime_x1= delaytime_x1 & (wert|(~mask));
delaytime_x1= delaytime_x1 | (wert&mask);
Gast
Naja, oder doch einfach

delaytime_x1= ((delaytime_x1&(~mask)) | (wert&mask));

(so wie Peter das oben geschrieben hat :-)
Die Frage ist aber, was gibt bit_is_set() wirklich zurück.
nur 0x00 und 0x01 ?
Wo anders sehe ich erstmal keine Fehlerquelle.
Gast
Das sehe ich im Moment genauso.
Wenn ich das ganze auf Papier durchspiele funktioniert es ja auch.
Ich gehe mal davon aus, das bit_is_set()   True oder Fals rausgibt,
also 0b0000 0001  oder 0b0000 0000.
Was sollte es sonst machen sonst?
Gibt es denn alternativen dazu, bit_is_set zu verwenden?
Gast
Naja, um sicher zu gehen bzw. zum testen, das man wirklich nur 0x00 oder
0x01 hat, kann man das TRUE oder FALSE ja auch logisch auswerten (was
allerdings mehr Rechenleistung verpulvert).

wert = bit_is_set(PIND,PIND5)? 1: 0;

Aber vielleicht weiß ja jemand, was bit_is_set() wirklich zurückgibt.
Ich vermute, das es nur das maskierte Bit zurückliefert, was dann
natürlich je nach Bit was anderes für TRUE ergibt.
Gast
good man !!!

da hatte wir jetzt beide die gleiche Idee

if(bit_is_set(PIND,PIND5)) wert=0x01;
     else wert =0x00;

funktioniert:  Dann is True oder Falls wohl doch was anderes als 0x00
oder 0x01.




vielen Dank   Ingo    nice WE

muss jetzt dringend weiterbasteln, da die Schaltung noch heute fertig
werden soll.
Gast
Hallo,

die Lösung von Ingo funktioniert genau dann am besten (und am
einfachsten) auch mit fortlaufendem Einlesen, wenn man in der Schleife
for (i.....) eine temporäre Variable verwendet, deren Inhalt am Ende
(also als letztes in der Endlos-Hauptschleife) in delaytime_x1 kopiert.
Keine Gehirnverrenkung und mann muss sich auch keine Gedanken machen,
dass einem der Interrupt mit dem Auslesen von delaytime_x1 in die Suppe
spuckt !

MfG, Khani
Gast
Ja, das wäre wohl das Beste, in der inneren Schleife eine temporäre
Variable verwenden und in der Endlos-Hauptschleife diesen Wert dann an
X1 zuweisen.
Das vermeidet eine weitere mögliche Fehlerquelle durch den asynchronen
Zugriff mit Int0.

delaytime_x1= ((delaytime_x1&(~mask)) | (wert&mask));

Denn im ersten Teil des Ausdrucks wird ja zunächst das gerade aktuelle
Bit pauschal auf 0 gesetzt (gelöscht). Wenn genau dann der Interrupt
auftritt, wird ein möglicherweise fälschlicherweise gelöschtes Bit
verwendet, weil die ODER-Verknüpfung mit dem aktuellen Wert ja erst
dannach erfolgt.

Wär mal interessant, was der Compiler da überhaupt für einen Code
erzeugt. In C ist das ja so eine schön einfache Zeile, als ASM-Code
dürften es aber doch ein paar Zeilen mehr sein :-)

Gruß
Ingo

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 22 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.