Forum: Compiler & IDEs Frage zur eleganten Bitmanipulation


von Hendrik L. (lbd)


Lesenswert?

Hallo

ich suche die Vereinfachung für folgende 2 Befehlzeilen zu einem Befehl:

...
PORTA &=  ~(1 << PINA1);
PORTA |= MP.mp.MPTA & (1 << PIN1);
...

Ich möchte also in Abhängigkeit von bit1 in der uint8_t MP.mp.MPTA 
Struktur den PIN1 in PORTA auf LOW oder HIGH setzen.

Danke!

von Stefan E. (sternst)


Lesenswert?

1
PORTA = (PORTA & ~(1 << PIN1)) | (MP.mp.MPTA & (1 << PIN1));

von Lukas K. (carrotindustries)


Lesenswert?

Stefan Ernst schrieb:
> PORTA = (PORTA & ~(1 << PIN1)) | (MP.mp.MPTA & (1 << PIN1));
Ist sogar noch ein Takt schneller als der Zweizeiler des TO.

von Hendrik L. (lbd)


Lesenswert?

Luk4s K. schrieb:
> Stefan Ernst schrieb:
>> PORTA = (PORTA & ~(1 << PIN1)) | (MP.mp.MPTA & (1 << PIN1));
> Ist sogar noch ein Takt schneller als der Zweizeiler des TO.

Danke.

Verstehe, weil der PORT erst nach der Ermittlung des Endergebnisses 
gesetzt wird, während er vorher immer erst einmal auf LOW gesetzt wird - 
oder ?

von Lukas K. (carrotindustries)


Lesenswert?

Hendrik L. schrieb:
> Luk4s K. schrieb:
>> Stefan Ernst schrieb:
>>> PORTA = (PORTA & ~(1 << PIN1)) | (MP.mp.MPTA & (1 << PIN1));
>> Ist sogar noch ein Takt schneller als der Zweizeiler des TO.
>
> Danke.
>
> Verstehe, weil der PORT erst nach der Ermittlung des Endergebnisses
> gesetzt wird, während er vorher immer erst einmal auf LOW gesetzt wird -
> oder ?

Ich hab's durch den Complier geschoben:
1
PORTA &=~(1<<PIN1);
2
  50:  d9 98         cbi  0x1b, 1  ; 27
3
  PORTA |= s&(1<<PIN1);
4
  52:  9b b3         in  r25, 0x1b  ; 27
5
  54:  82 70         andi  r24, 0x02  ; 2
6
  56:  89 2b         or  r24, r25
7
  58:  8b bb         out  0x1b, r24  ; 27
1
  PORTA = (PORTA&~(1<<PINA1)) | (s & (1 << PIN1));
2
  50:  9b b3         in  r25, 0x1b  ; 27
3
  52:  82 70         andi  r24, 0x02  ; 2
4
  54:  9d 7f         andi  r25, 0xFD  ; 253
5
  56:  89 2b         or  r24, r25
6
  58:  8b bb         out  0x1b, r24  ; 27
Beides sind 5 Instruktionen, aber das cbi braucht 2 Takte; in, andi, or, 
out nur je einen.

von Andreas B. (Gast)


Lesenswert?

Hendrik L. schrieb:
> Verstehe, weil der PORT erst nach der Ermittlung des Endergebnisses
> gesetzt wird, während er vorher immer erst einmal auf LOW gesetzt wird -
> oder ?

PORTA ist als IO-Register volatile, das heißt, der Compiler muss genauso 
viele Lese- und Schreibzugriffe in der selben Reihenfolge durchführen, 
wie es im Programm steht. Im Beispiel mit zwei Zeilen wird PORTA zweimal 
modifiziert, was zweimal lesen-modifizieren-schreiben heißt. In diesem 
Spezialfall konnte eine der Operationen in einem einzigen cbi Befehl 
abgehandelt werden.

Die Version in einer Zeile liest PORTA einmal und schreibt einmal. Den 
selben Effekt könnte man auch mit einer temporären Variable erzeugen:
1
uint8_t tmp;
2
3
tmp = PORTA;
4
tmp &=  ~(1 << PINA1);
5
tmp |= MP.mp.MPTA & (1 << PIN1);
6
PORTA = tmp;

Das sollte dasselbe Ergebnis wie der Einzeiler ergeben.

von Hendrik L. (lbd)


Lesenswert?

Danke an Alle,

habe viel gelernt!

Grüße

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.