Frage zur eleganten Bitmanipulation

OP #2138520
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!
#2138548
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.
Gast #2138555
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren