www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Eine "1" um x Schritte verschieben


Autor: M.B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte gerne 8 Signale auswerten und Abweichungen über 8 LED's an 
PORT B ausgeben.
Um mir mit meinem AVR ATmega die Arbeit leicht zu machen, möchte ich 
durch eine Schleife und Bitschieben die Ausgabe "vorkonfigurieren". Der 
Ansatz ist unten aufgelistet. Kann ich das so machen, sind meine 
Gedanken richtig?
Ausgabe =0;
for(i=1;i<=8;i++)
{
  if istwert[i] >= sollwert 
    Ausgabe |= (1<<i);
}
PortB= Ausgabe;

Wenn meine Abweichungen jetzt bei Wert 1, 3 und 6 sind sollen 
entsprechend die LED's 1,3 und 6 leuchten. Mein Ausgabe- 
Zwischenspeicher ist 0 und es soll die "1" um i Stellen in den Zwischen 
speicher geschoben werden:
- eine "1" um eine Stelle nach links (Ausgabe = 0b 0000 0001) mit (1<<1)
- eine "1" um drei Stellen nach links (Ausgabe = 0b 0000 0101) mit 
(1<<3)
- eine "1" um sechs Stellen nach links (Ausgabe = 0b 0010 0101) mit 
(1<<6)

Danach möchte ich den Zwischenspeicher an die LED's ausgeben mit PortB = 
0b 0010 0101

Ist das so korrekt?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M.B. wrote:
> - eine "1" um eine Stelle nach links (Ausgabe = 0b 0000 0001) mit (1<<1)
Nö, das was da binär steht ist (1 << 0), also eine 1, die um null 
Stellen nach links geschoben ist!

> - eine "1" um drei Stellen nach links (Ausgabe = 0b 0000 0101) mit
> (1<<3)
(1 << 3) wäre 0b00001000...

Autor: M.B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ja richtig. Die "Grundstellung" ist ja 0b 0000 0001 und dann die 
Stellen der Verschiebung.
Danke für den Tipp, hatte ich nicht bedacht. Guter hinweis.

Aber hierzu:
>> - eine "1" um drei Stellen nach links (Ausgabe = 0b 0000 0101) mit
>> (1<<3)
>(1 << 3) wäre 0b00001000...

wie du im Code siehst ist das ganze ja verodert mit "|=" da soll der 
Wert von vorher ja beibehalten werden und die um drei Stellen 
verschobene "1" dazugerechnet werden.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M.B. wrote:

> Ist das so korrekt?

Im Prinzip passt das schon so. (Nach der Korrektur, dass i bei 0 anfängt 
und nicht bei 1)

Das einzige, was du bedenken solltest: Die Operation 1 << i ist für 
einen AVR ziemlich aufwändig, weil sie nicht in einem Schritt gemacht 
werden kann, sondern der Compiler muss das seinerseits als Schleife 
implementieren, bei der die 1 jeweils i mal um 1 geschoben wird. (Ausser 
natürlich: der Optimizer des Compilers ist seeeeehr gut. Da würde ich 
aber nicht drauf wetten). Da dein i aber schön aufsteigend durchlaufen 
wird, kannst du das auch selber etwas besser formulieren
  Ausgabe =0;
  Mask = 1;

  for( i = 1; i <= 8; i++ )
  {
    if( istwert[i] >= sollwert )
      Ausgabe |= Mask;
    Mask = Mask << 1;
  }

  PortB = Ausgabe;

PS: Bist du sicher, dass dein Array istwert wirklich von der Länge 9 
ist? Ansonsten greifst du auf das Array 'out of Bounds' zu. Ein Array

int istwert[8];

besitzt 8 Elemente. Diese haben die Indizes: 0, 1, 2, 3, 4, 5, 6, 7
(und keinen Index 8!). Zähl nach, es sind genau 8 Elemente.

Die übliche for-Schleife, um so ein Array abzuabeiten lautet daher

    for( i = 0; i < 8; i++ )

sie beginnt bei 0, und in der Vergleichsbedingung (welche immer auf 
"kleiner" lautet), steht die Arraygröße und nicht der höchste Index.

Ich würde daher wetten, dass dein Code eigentlich so aussehen sollte
  Ausgabe =0;
  Mask = 1;

  for( i = 0; i < 8; i++ )
  {
    if( istwert[i] >= sollwert )
      Ausgabe |= Mask;
    Mask = Mask << 1;
  }

  PortB = Ausgabe;

Autor: M.B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl heinz, Danke für die Info.
Ich bin immer froh für Tipps zur Codeoptimierung.

Mein Array ist wirklich von der Länge 9, wobei ich die 0 leer lasse. 
(Platz habe ich genug)
Weil ich es einfach nicht so umständlich finde.Ich habe 1 bis 8 Signale 
durchlaufe die Schleife 1- 8 mal und die LED's 1 bis 8 leuchten. Für 
mich wäre es dann irritierend wenn ich dann in den Speicherzellen 0-7 
die Werte speicher. War jetzt der Wert 4 für die vierte oder fünfte LED 
oder Signal. Oder war es doch das dritte?
So kann ich mir einfach merken in Zelle 4 steht das Signla des 4. 
Signals und ist für LED 4. Zelle 0 kann ich zur Not mit anderen Sachen 
benutzen falls erforderlich, für Summen oder zur Korntrolle oder für 
Zwischenwerte.

Mein Code dafür würde dann so aussehen:
 Ausgabe =0;
  Mask = 1;

  for( i = 0; i < 8; i++ )
  {
    if( istwert[i+1] >= sollwert )
      Ausgabe |= Mask;
    Mask = Mask << 1;
  }

  PortB = Ausgabe;

Nochmal vielen Dank für die Hinweise!

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@M.B.:
Du solltest Dir dringend die in der Technik übliche Zählweise 
angewöhnen, sonst kommst Du irgendwann wirklich durcheinander! Bei 
solchen Zusammenhängen, bei denen es um Bits in Variablen oder Registern 
geht, fängt die Zählung grundsätzlich bei 0 an, nicht bei 1. Auch Deine 
LEDs solltest Du von 0 bis 7 durchnummerieren, schließlich heißen die 
Portpins auch PORTx0...7 und nicht anders. Wenn Du das nicht 
verinnerlichst, wirst Du irgendwann massive Probleme bekommen. Das mit 
dem 1<<1 oben wäre Dir nämlich auch nicht passiert, wenn Du daran 
gedacht hättest...

Autor: M.B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Johannes,

ich werde darüber nachndenken. Hört sich schlüssig an. Besser frühzeitig 
umdenken als zu spät - aber für mich ist es halt noch eher umständlich.

Aber ich werde mich bemühen - versprochen!

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M.B. wrote:
> ich werde darüber nachndenken. Hört sich schlüssig an. Besser frühzeitig
> umdenken als zu spät
Genau das ist der Punkt. Nicht erst was falsches angewöhnen.

> - aber für mich ist es halt noch eher umständlich.
Nun, das sind viele Dinge auf den ersten Blick. Nur werden sie noch 
komplizierter, wenn man versucht, mit irgendwelchen Verrenkungen drumrum 
zu kommen...

Autor: Stephan Henning (stephan-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spätetens wenn man wegen einem Bit ein zusätzliches Byte anfassen muß.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch ist es deinem Compiler ziemlich egal, wo du für dich den ersten 
Index in ein Array siehst. Spätestens bei Strings kocht der sowieso sein 
eigenes Süppchen und lässt das char Array in dem ein String gespeichert 
ist beim Index 0 anfangen.

  char Test = "Hello world";

das 'H' ist nun mal an Position Test[0].

Auch vereinfachen sich viele Index-Berechnungsvorgänge, wenn man den 
ersten Index als 0 annimmt. Das ganze ist also nicht nur akademisch 
sondern hat durchaus einen ernsten Hintergrund.

Bsp: Du brauchst eine Umsetztabelle, die Zahlenwerte von 80 bis 83 
(jeweils inklusive) in neue Zahlen umsetzt.

    80   ->   256
    81   ->   123
    82   ->   205
    83   ->    78

Wie ist der übliche Ansatz:

   char Table[] = { 256, 123, 205, 78 };

   int NewValue = Table[ OldValue - 80 ];

Wenn OldValue den Wert 80 hat, dann ergibt OldValue - 80 die 0. Also den 
Index des ersten Eintrags.

Wenn du dein System konsistent durchziehen willst, dann müsstest du 
schreiben

   char Table[] = { 0, 256, 123, 205, 78 };

   int NewValue = Table[ OldValue - 80 + 1 ];

und das gibt es oft: Wenn Indizes berechnet werden müssen, sind die 
Formeln einfacher, wenn der erste Index die 0 hat.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
>    char Table[] = { 256, 123, 205, 78 };
Hmm, mit char wird das aber nix...

(Wenn Du es korrigiert hast, kannste dieses dann gegenstandslose Posting 
löschen...)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Karl heinz Buchegger wrote:
>>    char Table[] = { 256, 123, 205, 78 };
> Hmm, mit char wird das aber nix...

LOL.
Danke für die Korrektur.

> (Wenn Du es korrigiert hast, kannste dieses dann gegenstandslose
> Posting löschen...)

Kanns im Original nicht mehr korrigieren. Daher bleibt auch dein absolut 
korrekter Fehleraufschrei da :-)

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.