www.mikrocontroller.net

Forum: Compiler & IDEs int zusammensetzen


Autor: Ephraim Hahn (ephi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich habe über zwei ports verteilt einen 9poligen DIP switch an meinem 
ATMega8 angeschlossen. Ich verwende die internen PullUps und lasse die 
Dips nach gnd schalten. Nun möchte ich aus diesen 9 bits einen Int 
zusammenbauen.

Die Belegung ist wie folgt:
DIP1 -> PC5
DIP2 -> PC4
DIP3 -> PC3
DIP4 -> PC2
DIP5 -> PC1
DIP6 -> PC0
DIP7 -> PD5
DIP8 -> PD6
DIP9 -> PD7

die Stati der Eingänge kommen zumindest einmal korrekt im AVR an, das 
habe ich mit ein paar LEDs verifiziert.

nun versuche ich wie folgt daraus einen uint16_t zu machen:
uint16_t addr;

PORTD |= (1<<PD5)|(1<<PD6)|(1<<PD7);
PORTC = 0xFF;

addr |= ((PINC & (1<<PC5))<<0);
addr |= ((PINC & (1<<PC4))<<1);
addr |= ((PINC & (1<<PC3))<<2);
addr |= ((PINC & (1<<PC2))<<3);
addr |= ((PINC & (1<<PC1))<<4);
addr |= ((PINC & (1<<PC0))<<5);
addr |= ((PIND & (1<<PD5))<<5);
addr |= ((PIND & (1<<PD6))<<5);
addr |= ((PIND & (1<<PD7))<<5);

addr = ~addr;

aber es kommt nicht das raus was sein soll. Mangels 
klartextausgabemöglichkeit in meiner Schaltung kann ich nicht genau 
sagen, was passiert, aber auf jeden fall erhalte ich nicht den mit den 
DIP schaltern eingestellten Wert.

Wäre schön, wenn mir jemand weiterhelfen kann!

Autor: Marvin S. (demo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(PINC & (1<<PC5)
 gibt ein Byte mit einem Bit an Stelle PC5 gesetzt (oder eben nicht) 
aus. Schieb das Bit einfach wieder zurueck:
addr |= (((PINC & (1<<PC5))>> PC5)<<0);

Gruesse

Marvin

Autor: Ephraim Hahn (ephi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab ich grad getestet, funktioniert aber auch nicht.
Naja, ich werd mich morgen in ausgeschlafenem zustand nochmal drum 
kümmern.

Autor: Ephraim Hahn (ephi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab die Sau dochnoch schnell gefunden:

anfangs hatte ich alle bits direkt invertiert, das ging irgendwie nicht 
und da hab ich geistesabwesend schnell den ganzen 16bit int invertiert, 
und nicht bedacht das alles ab bit10 vorher 0 war, also jetzt immer 1 
ist womit ich immer astronomische Zahlen bekomme. hab ihn jetzt einfach 
schnell aufgefüllt, und sieheda, es geht!
addr |= ( ( (PINC & (1<<PC5)) >>PC5) <<0);
  addr |= ( ( (PINC & (1<<PC4)) >>PC4) <<1);
  addr |= ( ( (PINC & (1<<PC3)) >>PC3) <<2);
  addr |= ( ( (PINC & (1<<PC2)) >>PC2) <<3);
  addr |= ( ( (PINC & (1<<PC1)) >>PC1) <<4);
  addr |= ( ( (PINC & (1<<PC0)) >>PC0) <<5);
  addr |= ( ( (PIND & (1<<PD5)) >>PD5) <<6);
  addr |= ( ( (PIND & (1<<PD6)) >>PD6) <<7);
  addr |= ( ( (PIND & (1<<PD7)) >>PD7) <<8);
  addr |= (1<<9);
  addr |= (1<<10);
  addr |= (1<<11);
  addr |= (1<<12);
  addr |= (1<<13);
  addr |= (1<<14);
  addr |= (1<<15);
  
  addr = ~addr;

Morgen wird die ganze Sache noch etwas verhübscht.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Etwas verhübschen oder zumindest beschleunigen könnte man
die Sache, indem man nicht die Bits nach rechts schiebt (was
Zeit kostet), sondern nur gegen 0 testet.
Das sollte schneller gehen, z.B. statt:
  addr |= ( ( (PIND & (1<<PD7)) >>PD7) <<8);
besser:
  addr |= ( ( (PIND & (1<<PD7)) !=0) <<8);

Noch etwas beschleunigen könnte man alles, wenn man
auf die vielen einzelnen Shifts um mehrere Stellen
verzichtet und stattdessen immer nur um 1 schiebt, das
geht schneller:
  addr = -2;  // binaer: ....1111110

  addr |= ( (PIND & (1<<PD7)) !=0);
  addr <<= 1;
  addr |= ( (PIND & (1<<PD6)) !=0);
  addr <<= 1;
  addr |= ( (PIND & (1<<PD5)) !=0);
  addr <<= 1;
  addr |= ( (PINC & (1<<PC0)) !=0);
  addr <<= 1;
  addr |= ( (PINC & (1<<PC1)) !=0);
  addr <<= 1;
  addr |= ( (PINC & (1<<PC2)) !=0);
  addr <<= 1;
  addr |= ( (PINC & (1<<PC3)) !=0);
  addr <<= 1;
  addr |= ( (PINC & (1<<PC4)) !=0);
  addr <<= 1;
  addr |= ( (PINC & (1<<PC5)) !=0);

  // Setzen der oberen Bits zu 1 entfällt wg. Initialisierung...

Wenn ich mich nicht vertan habe, sollte dasselbe rauskommen.

Autor: Marvin S. (demo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Das sollte schneller gehen, z.B. statt:
>
>   addr |= ( ( (PIND & (1<<PD7)) >>PD7) <<8);
> 
> besser:
>
>   addr |= ( ( (PIND & (1<<PD7)) !=0) <<8);
> 

Stellt sich nur die frage, ob der compiler den shift nicht sowieso 
wegoptimiert. Ansonsten ist es wohl am effizientesten, das ganze manuell 
auf einen shift zu reduzieren und den Vergleich mit null fallen zu 
lassen.

Gruesse

Marvin

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh, sehe gerade; es sollen die abgefragten Bits ja invertiert
rauskommen.
Dann müsste bei meinen Vorschlägen jeweils !=0 durch ==0 ersetzt
werden.

@Marvin: das war ja auch nur ein erster Vorschlag zum
Beschleunigen.
Meinen zweiten wirst du so (wenn ich dich richtig verstanden
habe, also jeweils um Differenz der alten und der neuen Position
zu schieben) bzgl. Effizienz auch nicht toppen, weil dann i.d.R.
immer noch um mehrere Positionen geschoben werden muß, was auf
AVR länger dauert als um 1 zu schieben.

Es sei denn der Compiler erkennt den Sinn, dann ist es eh egal.
Aber das würde ich hier erstmal probieren, bevor ich es
unterschreibe.

Autor: Ephraim Hahn (ephi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank für eure Vorschläge!

Ich hab es jetzt mit der == 0 prüfung gemacht, addr also doch wieder mit 
0 initialisiert und mir dann die Invertierung gespart.
addr |= (!(PIND & (1<<PD7)));
  addr <<= 1;
  addr |= (!(PIND & (1<<PD6)));
  addr <<= 1;
  addr |= (!(PIND & (1<<PD5)));
  addr <<= 1;
  addr |= (!(PINC & (1<<PC0)));
  addr <<= 1;
  addr |= (!(PINC & (1<<PC1)));
  addr <<= 1;
  addr |= (!(PINC & (1<<PC2)));
  addr <<= 1;
  addr |= (!(PINC & (1<<PC3)));
  addr <<= 1;
  addr |= (!(PINC & (1<<PC4)));
  addr <<= 1;
  addr |= (!(PINC & (1<<PC5)));

So funktioniert das erstmal einwandfrei.
Ob man sich auf irgendeine Weise jetzt noch ein paar takte sparen könnte 
ist recht unkritisch, da von den DIPs nur beim Programmstart eine 
Adresse gelesen wird. Später sind die quasi unbenutzt.

Vielen Dank nochmal für die Hilfestellungen

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.