Forum: Compiler & IDEs int zusammensetzen


von Ephraim H. (ephi)


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:
1
uint16_t addr;
2
3
PORTD |= (1<<PD5)|(1<<PD6)|(1<<PD7);
4
PORTC = 0xFF;
5
6
addr |= ((PINC & (1<<PC5))<<0);
7
addr |= ((PINC & (1<<PC4))<<1);
8
addr |= ((PINC & (1<<PC3))<<2);
9
addr |= ((PINC & (1<<PC2))<<3);
10
addr |= ((PINC & (1<<PC1))<<4);
11
addr |= ((PINC & (1<<PC0))<<5);
12
addr |= ((PIND & (1<<PD5))<<5);
13
addr |= ((PIND & (1<<PD6))<<5);
14
addr |= ((PIND & (1<<PD7))<<5);
15
16
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!

von Marvin S. (demo)


Lesenswert?

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

Gruesse

Marvin

von Ephraim H. (ephi)


Lesenswert?

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

von Ephraim H. (ephi)


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!
1
addr |= ( ( (PINC & (1<<PC5)) >>PC5) <<0);
2
  addr |= ( ( (PINC & (1<<PC4)) >>PC4) <<1);
3
  addr |= ( ( (PINC & (1<<PC3)) >>PC3) <<2);
4
  addr |= ( ( (PINC & (1<<PC2)) >>PC2) <<3);
5
  addr |= ( ( (PINC & (1<<PC1)) >>PC1) <<4);
6
  addr |= ( ( (PINC & (1<<PC0)) >>PC0) <<5);
7
  addr |= ( ( (PIND & (1<<PD5)) >>PD5) <<6);
8
  addr |= ( ( (PIND & (1<<PD6)) >>PD6) <<7);
9
  addr |= ( ( (PIND & (1<<PD7)) >>PD7) <<8);
10
  addr |= (1<<9);
11
  addr |= (1<<10);
12
  addr |= (1<<11);
13
  addr |= (1<<12);
14
  addr |= (1<<13);
15
  addr |= (1<<14);
16
  addr |= (1<<15);
17
  
18
  addr = ~addr;

Morgen wird die ganze Sache noch etwas verhübscht.

von Klaus W. (mfgkw)


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:
1
  addr |= ( ( (PIND & (1<<PD7)) >>PD7) <<8);
besser:
1
  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:
1
  addr = -2;  // binaer: ....1111110
2
3
  addr |= ( (PIND & (1<<PD7)) !=0);
4
  addr <<= 1;
5
  addr |= ( (PIND & (1<<PD6)) !=0);
6
  addr <<= 1;
7
  addr |= ( (PIND & (1<<PD5)) !=0);
8
  addr <<= 1;
9
  addr |= ( (PINC & (1<<PC0)) !=0);
10
  addr <<= 1;
11
  addr |= ( (PINC & (1<<PC1)) !=0);
12
  addr <<= 1;
13
  addr |= ( (PINC & (1<<PC2)) !=0);
14
  addr <<= 1;
15
  addr |= ( (PINC & (1<<PC3)) !=0);
16
  addr <<= 1;
17
  addr |= ( (PINC & (1<<PC4)) !=0);
18
  addr <<= 1;
19
  addr |= ( (PINC & (1<<PC5)) !=0);
20
21
  // Setzen der oberen Bits zu 1 entfällt wg. Initialisierung...

Wenn ich mich nicht vertan habe, sollte dasselbe rauskommen.

von Marvin S. (demo)


Lesenswert?

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

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

von Klaus W. (mfgkw)


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.

von Ephraim H. (ephi)


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.
1
addr |= (!(PIND & (1<<PD7)));
2
  addr <<= 1;
3
  addr |= (!(PIND & (1<<PD6)));
4
  addr <<= 1;
5
  addr |= (!(PIND & (1<<PD5)));
6
  addr <<= 1;
7
  addr |= (!(PINC & (1<<PC0)));
8
  addr <<= 1;
9
  addr |= (!(PINC & (1<<PC1)));
10
  addr <<= 1;
11
  addr |= (!(PINC & (1<<PC2)));
12
  addr <<= 1;
13
  addr |= (!(PINC & (1<<PC3)));
14
  addr <<= 1;
15
  addr |= (!(PINC & (1<<PC4)));
16
  addr <<= 1;
17
  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

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.