www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Bitmanipulation


Autor: Stephan schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter&Ingo    U R right!!

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

werds nun mal testen.

Autor: uli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!!

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stephan Schwarz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stephan Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Khani (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ingo Henze (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.