Forum: Mikrocontroller und Digitale Elektronik Bitmanipulation


von Stephan schwarz (Gast)


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.

von Hagen (Gast)


Lesenswert?

X1 = ((~X1) & Maske) | (X1 & (~Maske))

X1 = (not X1 and Maske) or (X1 and not Maske)

X1 = X1 ^ Maske
X1 = X1 xor Maske

Gruß Hagen

von Stephan Schwarz (Gast)


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.

von Hagen (Gast)


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

von Stephan Schwarz (Gast)


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

von Ingo Henze (Gast)


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

von Ingo Henze (Gast)


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

von Peter D. (peda)


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

von Stephan Schwarz (Gast)


Lesenswert?

@Peter&Ingo    U R right!!

is mir dann auch aufgefallen, das mir da eine Information fehlt (ORT).

werds nun mal testen.

von uli (Gast)


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!!

von Stephan Schwarz (Gast)


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.

von Ingo Henze (Gast)


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

von Stephan Schwarz (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Ingo Henze (Gast)


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;
}

von Stephan Schwarz (Gast)


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.

von Ingo Henze (Gast)


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);

von Ingo Henze (Gast)


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.

von Stephan Schwarz (Gast)


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?

von Ingo Henze (Gast)


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.

von Stephan Schwarz (Gast)


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.

von Khani (Gast)


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

von Ingo Henze (Gast)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.