Einfachere Schreibweise gesucht

OP #2160415
Lesenswert?

Hallo,

kennt jemand eine einfachere Funktionsweise für nachfolgenden Code?
(ATMEGA 8)

Prinzip:
Wenn Eingang PD6 low ist soll Ausgang PC2 high werden.
Wenn Eingang PD7 low ist soll Ausgang PC3 high werden.
Und jeweils umgekehrt.
Unten stehender Code funktioniert. Aber geht es nicht auch einfacher?
Wie PC2 != PD6
1
  while(1)
2
  {
3
  if (PIND & (1<<PIND6)) 
4
    {
5
      PORTC &= ~(1<<PC2);  //Setzt PC2 1
6
    }
7
      else
8
    {
9
      PORTC = PORTC | (1<<PC2);  //Setzt PC2 1
10
      
11
    
12
    }
13
  if (PIND & (1<<PIND7)) 
14
    {
15
      PORTC &= ~(1<<PC3);
16
      
17
    }
18
      else
19
    {
20
      PORTC = PORTC | (1<<PC3);
21
    }     
22
  
23
  }
24
return 1;
Moderator #2160446
Lesenswert?

Noch richtiger ist
1
    PORTC = PORTC & 0xF3 | (PIND & 0xC0)>>4;

Aber das ist zwar kurz in C, nicht jedoch im erzeugten Assembler Code.
Da ist die ursprüngliche Lösung mit den if-Abfragen wahrscheinlich
optimal.

Mit noch weniger Bytes und Nanosekunden geht es, wenn man den
Mikrocontroller durch ein 1/3 74HC04 (6fach-Inverter) ersetzt ;-)
#2160737
Lesenswert?

1
// Wenn Eingang PD6 low ist soll Ausgang PC2 high werden.
2
// Wenn Eingang PD7 low ist soll Ausgang PC3 high werden.
3

4
#include<avr/io.h>
5

6
// Access bits like variables:
7
struct bits {
8
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
9
} __attribute__((__packed__));
10
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
11
#define SBIT(x,y)       SBIT_(x,y)
12

13

14
#define PORT_C2         SBIT( PORTC, PC2 )
15
#define PORT_C3         SBIT( PORTC, PC3 )
16
#define PIN_D6          SBIT( PIND,  PD6 )
17
#define PIN_D7          SBIT( PIND,  PD7 )
18

19

20
int main()
21
{
22
  for(;;){
23
    PORT_C2 = ! PIN_D6;
24
    PORT_C3 = ! PIN_D7;
25
  }
26
}


Peter
Moderator #2160810
Lesenswert?

Julian Baugatz schrieb:
> Die Aufgabenstellung war, daß der Port auf High geht, wenn der Ausgang
> auf Low geht, die Lösung ist binär gesehen also FALSE :-)

Stimmt, ich habe gestern Abend nur gesehen, dass in Olivers Vorschlag
das &= nicht funktonieren kann, da erst die &- und dann die |-Verknüp-
fung erfolgen muss. Dass die Invertierung fehlt, habe ich übersehen.

Dein Vorschlag ist aber auch nicht perfekt, denn zum einen behandelt nur
einen der zwei Eingänge bzw. Ausgänge, zum anderen kann auch er das Aus-
gangsbit nur löschen, aber nicht setzen.

Neuer Vorschlag (PIND wird vor der Verwendung invertiert):
1
    PORTC = PORTC & 0xF3 | (~PIND & 0xC0)>>4;

... auf die Gefahr hin, dass ein weiterer Denkfehler darin steckt ;-)

Aber wie gesagt, der vom Compiler erzeugte Code sieht in der ursprüng-
lichen Lösung von Günter mit Abstand am besten aus.
Gast #2161214
Lesenswert?

Yalu X. schrieb:
> Aber wie gesagt, der vom Compiler erzeugte Code sieht in der ursprüng-
> lichen Lösung von Günter mit Abstand am besten aus.

Die ursprüngliche Lösung hat, wie man an der Vielzahl der zwar kurzen, 
aber falschen Lösungen sieht (woran allerdings auch die klassisch 
sinnlosen und falschen Kommentare schuld sind), auch den Vorteil, 
schnörkellos und einfach verständlich zu sein.

KISS - keep it simple and stupid.

Oliver
Moderator #2161900
Lesenswert?

Oliver schrieb:
> Die ursprüngliche Lösung hat, wie man an der Vielzahl der zwar kurzen,
> aber falschen Lösungen sieht (woran allerdings auch die klassisch
> sinnlosen und falschen Kommentare schuld sind), auch den Vorteil,
> schnörkellos und einfach verständlich zu sein.

So ist es. Zudem brauchen bei Hardwareänderungen einfach nur die Port-
und Pin-Namen angepasst werden. Bei der Einzeilenlösungen werden
hingegen gewisse Dinge vorausgesetzt, bspw. dass die Eingangs- und
Ausgangspins jeweils dem gleichen Port zugehören.

Peters Version ist sogar noch lesbarer und wartungsfreundlicher, führt
aber leider auch zum umständlichsten Assemblercode aller Vorschläge, da
der AVR-GCC nicht gut mit variablen Zuweisungen von und zu Bitfeldern
umgehen kann. Ändert man jedoch
1
    PORT_C2 = ! PIN_D6;
2
    PORT_C3 = ! PIN_D7;

in
1
    if(PIN_D6)
2
      PORT_C2 = 0;
3
    else
4
      PORT_C2 = 1;
5

6
    if(PIN_D7)
7
      PORT_C3 = 0;
8
    else
9
      PORT_C3 = 1;

erzeugt der Compiler den gleichen Code wie im ursprünglichen Beispiel.

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