Bitmanipulation

Gast #92056
Lesenswert?

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 #92058
Lesenswert?

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 #92059
Lesenswert?

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 #92060
Lesenswert?

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 #92061
Lesenswert?

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 #92062
Lesenswert?

Ä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
#92063
Lesenswert?

"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 #92065
Lesenswert?

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 #92066
Lesenswert?

@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 #92067
Lesenswert?

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 #92069
Lesenswert?

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 #92070
Lesenswert?

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 #92071
Lesenswert?

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 #92072
Lesenswert?

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 #92073
Lesenswert?

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 #92074
Lesenswert?

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 #92075
Lesenswert?

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 #92076
Lesenswert?

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 #92077
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren