Forum: Compiler & IDEs Einfachere Schreibweise gesucht


von Guenter B. (gbl)


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;

von Oliver (Gast)


Lesenswert?

Einfach ist immer relativ...

Es ginge auch so:
1
PORTC &= 0xF3 | (PIND & 0xC0)>>4);

Oliver

von Julian B. (julinho)


Lesenswert?

richtig ist:

PORTC &=  ~((PIND & (1<<PIND6))>>4);

von Yalu X. (yalu) (Moderator)


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 ;-)

von Guenter B. (gbl)


Lesenswert?

Danke für die Beispiele.

@yalu

Ich wollte wirklich zuerst 2 Transistoren nehmen, um die beiden 
Eingängszustände mit Hilfe zweier LED's darzustellen.
Da ich aber noch reichlich Ausgänge am Mega8 habe ...

von Julian B. (julinho)


Lesenswert?

Yalu X. schrieb:
> Noch richtiger ist
>
>
1
>     PORTC = PORTC & 0xF3 | (PIND & 0xC0)>>4;
2
>
>

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

von Peter D. (peda)


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

von Yalu X. (yalu) (Moderator)


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.

von Oliver (Gast)


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

von Yalu X. (yalu) (Moderator)


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.

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.