Forum: Mikrocontroller und Digitale Elektronik Bit auf Bitbreite weiten


von bit-te (Gast)


Lesenswert?

Hallo,

kann mir bitte jemand sagen, wie man in C (gcc) ein Bit eines Vektors 
auf eine bestimmte Bitbreite weitet?
Sinn ist ein Bit eines Vektors zu extrahieren, dass als Gate für ein 
Byte dienen soll.

Z.B.

uint8_t vect = 0b00000001;

uint8_t gate = "Hier soll Bit 0 von vect auf 8 Bit vergrößert werden"

uint8_t output = input & gate;

Ich weiß, dass man das über eine if-Abfrage nach dem gesetzten Bit 
machen könnte. Ich möchte hier aber ein explizites Gate haben.

von retreti (Gast)


Lesenswert?

du könntest das bit nach links shiften so oft wie du es eben brauchst.
in assembler geht das mit lsl, in c wirds auch vermutlich ähnlich gehen.

von Karl H. (kbuchegg)


Lesenswert?

bit-te schrieb:
> Hallo,
>
> kann mir bitte jemand sagen, wie man in C (gcc) ein Bit eines Vektors
> auf eine bestimmte Bitbreite weitet?
> Sinn ist ein Bit eines Vektors zu extrahieren, dass als Gate für ein
> Byte dienen soll.
>
> Z.B.
>
> uint8_t vect = 0b00000001;
>
> uint8_t gate = "Hier soll Bit 0 von vect auf 8 Bit vergrößert werden"
>


Da das betreffende Bit nur 0 ode 1 sein kann

  if( vect & 0x01 )
    gate = 0xFF;
  else
    gate = 0x00;

> uint8_t output = input & gate;

von bit-te (Gast)


Lesenswert?

Danke für eure Antworten.
Einen expliziten Befehl scheint es also nicht zu geben, aber das sind 
auch gute Möglichkeiten.
Sind die Ausführzeiten vom if- und else-Zweig eigentlich gleich 
(vorausgesetzt es steht etwas gleicher Ausführungslänge innerhalb der 
Zweige) oder benötigt der Sprung zum else z.B. länger?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

bit-te schrieb:
> Ich weiß, dass man das über eine if-Abfrage nach dem gesetzten Bit
> machen könnte. Ich möchte hier aber ein explizites Gate haben.

Was den für ein Gate? Außer das du durch diese Aktion ein paar Befehle 
extra brauchst hast du überhaupt nix gewonnen....
1
if( vect & 0x01 )
2
    output = input;
3
  else
4
    output = 0x00;
Ist genau gleichwertig sparrt aber die zusätzliche Verknüpfung wenn der 
Compiler die nicht schon selbst verwirft.

Und ja if/else haben u.U. verschiedene Ausführungszweige, obige else/if 
KÖNNTE der compiler aber in sbis/sbic übersetzen wodurch man eine 
gleiche ausführungszeit zwischen else und if erhält.

von bit-te (Gast)


Lesenswert?

Gut, dann andere Frage:
Wie muss ich es anstellen, dass ich gleiche Ausführungszeiten bekomme?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Das geht nur mit inline assembler, was hast du den genau vor?

von Maxxie (Gast)


Lesenswert?

Das Bit normieren und dann einfach multiplizieren.

Der Totschläger, aber eben ohne conditions (if/else, cond?a:b):
1
#define BIT_AUFBREITEN(value,bitnum,breite) ((((value >> bitnum) & 1) * ((1 << breite) - 1))

Die Konstanten werden entsprechend optimiert, wenn bitnum, breite 
konstant sind.

Das vector Beispiel von oben übersetzt sich dann mit
1
vector = BIT_AUFBREITEN(vector,0,8) ;

Was nach der Konstantenevaluierung zu
1
vector =  (value & 1) * 0xFF ;

von bit-te (Gast)


Lesenswert?

Ich möchte zwei uC genau synchron halten, auf denen dasselbe Programm 
laufen soll. Beide bekommen ein gemeinsames IRQ von außen, alles was 
dann folgt, soll ohne weitere Signale von außen synchron laufen. Ich 
gehe also davon aus, dass ab dem Eintritt in die ISR beide bei t_0 sind 
und dass sie nach ein paar Befehlen (alle in der ISR ohne andere IRQs), 
in denen sie genau dasselbe machen sollen nur mit teilweise anderen 
Werten (hierfür eben if-else), sie bei einem bestimmten Befehl immer 
noch synchron sind und diesen gleichzeitig bearbeiten.

Meine nächste Idee ist nun, die verschiedenen Werte schon vorher in 
einer FSM auf eine gleiche Variable zu legen, wo es noch nicht auf 
Synchronität ankommt, und dann einfach zuzuweisen. Damit fällt if-else 
im zeitkritischen Teil weg.

von Gast (Gast)


Lesenswert?

Beide uC haben aber die selber Taktquelle, oder?

von bit-te (Gast)


Lesenswert?

Die uC haben den gleichen Takt, nicht dieselbe Quelle. Die dadurch 
entstehende Verschiebung von max. 1 Takt ist okay, möchte aber nicht 
durch den Programmcode zusätzliche Verschiebungen erzeugen.

von tuppes (Gast)


Lesenswert?

Lieber würde ich aber mal über die Forderung "zwei unsynchronisierte µCs 
sollen freiwillig eine Zeitlang absolut synchron laufen" nachdenken. 
Warum müssen die das tun, welche maximale Abweichung ist dabei zulässig, 
und was würde in diesem Fall passieren?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Die uC haben den gleichen Takt, nicht dieselbe Quelle.
> Die dadurch entstehende Verschiebung von max. 1 Takt ist okay...
Wie kommst du darauf, dass das nur 1 Takt sein könnte/sollte/dürfte?

von Karl H. (kbuchegg)


Lesenswert?

tuppes schrieb:
> Lieber würde ich aber mal über die Forderung "zwei unsynchronisierte
> µCs sollen freiwillig eine Zeitlang absolut synchron laufen"
> nachdenken. Warum müssen die das tun, welche maximale Abweichung
> ist dabei zulässig, und was würde in diesem Fall passieren?

Yep. Sehe ich auch so.

> Beide bekommen ein gemeinsames IRQ von außen, alles was
> dann folgt, soll ohne weitere Signale von außen synchron laufen.

Wenn die beiden µC vor dem IRQ nicht absolut synchron im Programm auf
dem exakt gleichen Maschinenbefehl liefen, dann ist diese Forderung
sowieso illusorisch. Wie lange ein Einstieg in die ISR dauert, hängt
auch davon ab, welcher Befehl gerade in der Bearbeitung war.

Fragt sich jetzt nur, wozu man 2 µC benötigt, die das exakt gleiche
Programm taktsynchron abarbeiten müssen. Alle Ausgänge führen immer
identische Pegel. Alle Eingänge verhalten sich absolut gleich. Warum
nimmt man nicht gleich nur einen µC anstelle des Aufwands 2 µC
miteinander zu synchronisieren.

Also entweder ist das eine teuflisch gut durchdachte Aufgabenstellung
oder es ist der größte Mumpitz der hier im Forum seit einiger Zeit
aufgetaucht ist.

(Hat das irgendetwas mit Ausfallsicherheit zu tun?)

von Martin V. (oldmax)


Lesenswert?

Hi
Ich glaube nicht, das du es schaffen wirst, mit einem Interrupt etwas 
Syncron zu bekommen, es sei denn, der Interrupt startet die Prozessoren 
neu. Wenn du aber zwei Prozessoren Redundant betreiben willst, würde ich 
folgendes vorschlagen:
Einfach beschrieben
Loop:
  Lese_Input
  Bearbeite_Input
  Merke_Ergebnis
  Setze_Fertigbit    ; für Partner
  Warte_auf_Partner
  Vergleiche_Ergebnis
  Setze_Err_Flag     ; 0 = ok, 1= Error und Errorhandling
Loop

Entweder weden die Ergebnisse getuscht, oder diese werden in Einen für 
beide µC erreichbare Speicher gesschrieben (Dualport RAM)
Bis zum Warte auf Partner ist die Laufzeit jedes Programmes unabhängig. 
Vielleicht ist eine Laufzeitrechnung und auch ein Vergleich beider 
Controler denkbar, um einen "müden" Prozess aufzudecken. Auch muß ein 
Errorhandling bei Ausfall eines Prozessors möglich sein. Allerdings sehe 
ich noch nicht zwingend einen Interrupt, höchstens für einen Timer. Das 
ist jetzt mal so aus dem Stegreif zusammengedacht und nichts 
Ausgereiftes.
Gruß oldmax

von bit-te (Gast)


Lesenswert?

Die uC verständigen sich über Funk, daher gibt es keine gemeinsame 
Taktquelle. Dafür, dass die IRQs von den Funkmodulen zum gleichen 
Zeitpunkt kommen ist gesorgt. Der uC befindet sich zu der Zeit in einem 
Zustand der FSM, in der er nichts macht außer Schleifen drehen. Der 
längste Befehl ist also ein 2-Takt Assemblerbefehl für den 
Schleifenrücksprung, das gibt evtl. eine kleine Ungenauigkeit, wenn die 
ISR erst danach greift. Die Zeit vom Erkennen der IRQ-Flanke am Pin bis 
zum Aufruf der ISR sollte auf beiden uC bis auf +-1 Takt gleich sein, 
oder habe ich etwas übersehen?

Mein uC läuft mit 8MHz und ich möchte, dass ein Befehl auf beiden uC mit 
+-1us Genauigkeit ausgeführt wird, also 8 clk-cycles. Davon ausgehend, 
dass die ISRs gleichzeitig aufgerufen werden (wobei 1 Takt Unterschied 
auftreten könnte, wenn die Takte für das Samplen ungünstig zueinander 
liegen), arbeite ich danach ein paar Befehle innerhalb der ISRs ab, die 
letztendlich auf beiden uC die gleiche Ausführungszeit in Anspruch 
nehmen sollen, damit Befehl x anschließend möglichst genau gleichzeitig 
ausgeführt wird.

Sieht da erstmal jemand größere Probleme, die ich nicht beachtet habe? 
Bin noch nicht so firm in uC-Programmierung.

Problem ist unter anderem, dass auf beiden uC die gleiche Firmware 
laufen soll, allerdings arbeiten die uC unterschiedliche Zweige darin 
ab, wenn man es so ausdrücken will. Sinn ist, dass die Rollen getauscht 
werden können.
Wenn also innerhalb der ISR z.B. verschiedene Werte geschrieben werden 
sollen, je nachdem welcher uC angesprochen ist (Identität wird vorher 
zur Laufzeit bekannt), dann bekomme ich Schwierigkeiten mit der 
Ausführungszeit, insbesondere wenn ich jedesmal
if (uC1) {}
else if (uC2) {}
mache, da dass unterschiedliche viele Takte brauchen kann.

Mein erster Gedanke war etwas wie ein Gate und ein Multiplexer (da ich 
aus der FPGA-Ecke komme)

speicher = (datum_uC1 & gate) | (datum_uC2 & ~gate);

wobei Gate (uC1=0x11 oder uC2=0x00) die Identität des uC darstellt. Ich 
sehe ein, dass der Compiler da seine Optimierungen ansetzt und 
letztendlich möglicherweise doch nichts anderes als ein if/else 
rauskommt.

Dafür brauche ich eine Lösung.

von Ralph (Gast)


Lesenswert?

Ich würde hier einen anderen Ansatz wählen.

Das Funksignal triggert keinen IRQ sondern eine Zeitmessung über den 
Capture timer.

Beide µC verarbeiten ihre Daten und schalten bei Timer wert + x den 
Ausgang.

Je nach µC Architektur ( ich kenne die AVR hier nicht im Detail) kann 
der Ausgang auch hardwaregetriggert vom Timer geschaltet werden.
Erreichbare Genauigkeit wäre Timerauflösung +-1 und zusätzlich der 
Taktdrift durch 2 getrennte Takterzeugungen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> ... oder habe ich etwas übersehen?
Ich würde sagen: Ja, das hast du  :-o

Denn 1 Takt Unterschied kannst du schon haben, wenn alle Befehle gleich 
lang sind. Das ist erst mal die Abtastungenauigkeit aufgrund der beiden 
unabhängigen Oszillatoren (die ja auseinanderdriften).

Und dann kommt noch dein 2-Zyklen-Jitter von 1 Takt dazu.

Für mich können das bezogen auf den jeweils ersten der beiden uC also 0 
(Glück gehabt) bis +2 Takte (spät abgetstet und durch 2-Zyklen-Befehl 
verzögert) sein.

Bezogen auf irgendeinen der beiden uC ist m.E. die Ungenauigkeit also 
-2..+2 Zyklen.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Warum müssen die uC überhaupt "Taktsyncron" laufen?

> Wenn also innerhalb der ISR z.B. verschiedene Werte geschrieben werden
> sollen, je nachdem welcher uC angesprochen ist (Identität wird vorher
Wenn du den Platz im flash hast: Mach zwei Funktionen draus, lad an der 
stelle wo die umschaltung geschieht einen Funktionspointer und ruf 
diesen dann in der ISR auf --> jeder uC führt nur "seinen" Code aus.

Löst aber immer noch nicht das Problem das der Compiler verschiedene 
Codeblöcke ggf anders übersezt/optimiert.

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.