-
        

Ergebnis 1 bis 9 von 9

Thema: IO-Pins in Variablen festlegen [solved]

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    18.06.2005
    Ort
    Hattenhofen
    Alter
    30
    Beiträge
    55

    IO-Pins in Variablen festlegen [solved]

    Anzeige

    Hallo allerseits,

    ich weiß, das ist eine Anfängerfrage, aber mich interessierts trotzdem:

    Ich will, weil ich noch nicht weiß, wie das genaue Layout aussehen wird, mal die IO-Ports nich fest hardcoden, sondern in einer externen Datei festlegen. Dass ich also statt dem PORTA (z.B. hängt da Motor 1) das Register PORTM1 verwende, um später festlegen zu können, wo was hängt.

    Was ich jetzt nicht weiß: Wenn ich ihm irgendwo eine Variable mit
    Code:
    uint_8 PORTM1;
    erzeuge und anschließend den Wert PORTA zuweise, wird dann nicht im Speicher irgendwo ein Speicherplatz reserviert, der "tot" ist? Wie kann ich das umgehen?

    Wenn ich den Motor am 1 Pin (LSB) habe, kann ich ja (mit PINM1=0) den Motor mit
    Code:
    PORTM1 |= _BV(PINM1);
    einschalten. Wenn ich jetzt aber mit
    Code:
    PORTM1 |= _BV(PINM1) + _BV(PINM2);
    noch den 2. Motor mit dazuschalte, rechnet er mir doch jedes Mal im µC die beiden Zahlen zusammen (braucht eine gewisse Zeit und v.a. mehrere Speicherzeilen im Flash) und Oder-verknüpft das Ergebnis dann mit PORTM1, oder? Wie kann ich den Compiler dazu bringen, dass er das als feste Konstante dem AVR überginbt?

    MfG
    Christian

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    42
    Beiträge
    1.140
    Die Lösung Deines Problems ist die Compileranweisung #define.
    Mit
    Code:
    #define PORTM1 PORTA
    sagst Du dem Compiler, dass er beim compilieren PORTM1 mir PORTA ersetzen soll. Das ganze belegt also keinen Speicherplatz im µC. PORTM1 nennt sich dann nicht Variable, sondern Makro.
    PORTA ist übrigens auch nur ein Makro...

    Gruß,
    askazo

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    18.06.2005
    Ort
    Hattenhofen
    Alter
    30
    Beiträge
    55
    Kann ich dann auch folgendes sagen?:
    Code:
    #define M1_vorw _BV(PINM1A) + _BV(PINM1E)
    Bemerkung: PINM1A und PINM1E sind zwei von drei Steuerleitungen (Enable und Halbbrücke)

    Es geht halt drum, dass er die beiden Werte _BV(PINM1A) und _BV(PINM1E) erst addiret und dann in dem Makro ablegt.

    MfG
    Christian

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    42
    Beiträge
    1.140
    Das müsste auch funktionierten.
    Einfach mal ausprobieren....

    askazo

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Die Addition stört nicht weiter, das Ergebnis ist ja zur Compilezeit bekannt. Oder willst du eine Bibliothek mit zulinkbaren Modulen machen, die nur dazugebunden werden sollen? Dann geht es natürlich nicht über Makros.

    Bei deinem Beispiel müssen PINM1A und PINM1E auf dem gleichen Port liegen, voll flexibel bist du da immer noch nicht.

    Ausserdem musst du nicht nur den Port kennen (PORTX-Register) sondern auch Direction-Register (DDRX) und evtl Port Input Register (PINX). Die liegen nicht bei allen AVRs nebeneinander im Adressraum.

    Werte werden auch nicht in einem Makro "abgelegt". Ein Makro macht nichts weiter als reinen Textersatz zur Compilezeit.

    Falls du Makros willst wie SET(PORTB_1), CLR(PORTB_1) oder MAKE_OUTPUT(PORTB_1) geht das zwar, aber die Makros werden recht unübersichtlich, weil im MAKE_OUTPUT() das DDR angefasst werden muss und im SET() das PORT-Register und mit CLR() noch eine Maskenoperation hinzukommt. Der Compiler macht zwar den optimalen Code, weil er nur Konstanten zu falten hat, aber einen Fehler aus so verschlungenen Makros rausfischen ist keine Freude.
    Disclaimer: none. Sue me.

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    18.06.2005
    Ort
    Hattenhofen
    Alter
    30
    Beiträge
    55
    Ich hab jetzt hier mal die aktuelle Version meines Codes (Nur die die Hardware ansteuernde Codes). Wie leicht ersichtlich, gibt es eine Unmenge kleine Prozeduren, die nur ein Bit setzen oder löschen. Gibt es eine schönere/schnellere/bessere/klarere Programmiermöglichkeit?

    MfG
    Christian
    Angehängte Dateien Angehängte Dateien

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Das kommt darauf an, was du haben willst. Und was "schön" ist, wird ja ganz unterschiedlich gesehen.

    So wie du es organisiert hast, kannst du gut von der Hardware abstrahieren. Wenn du einen anderen µC nimmst, bräuchest du nur diesen Hardware-abhängigen Teil auszutauschen/neuschreiben. Funktionsaufrufe sind für so was natürlich langsamer als inline-Funktionen oder Makros (die ja direkt in den Code eingeflickt werden).

    Klarer wären zumindest klarere Namen. Wenn du in 3 Monaten wieder auf die Quelle schaust, wird's schwer, das zu verstehen mit den kryptischen Bezeichnern.
    Disclaimer: none. Sue me.

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    18.06.2005
    Ort
    Hattenhofen
    Alter
    30
    Beiträge
    55
    Das mit den Bezeichnern passt schon. Die sind in einem Schaltplan und einer technischen Zeichnung im Unterverzeichnis sofort zuzuordnen.

    Wie würde das noch schneller gehen? (Rein Interessehalber) Du sagst irgendwas mit inline? Wäre das dann:
    Code:
    uint8_t inline function UW_STOP(){ [...] }
    Mfg
    Christian

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Ich nehm hier mal das UW_R.

    Das Original:
    Code:
    UW_R(){
      OUT = OUT & 255 - _BV(UW_M) | _BV(UW_P);
      UW_ACTION = UW_A_R;
    }
    Als inline-Funktion (In den Header schreiben und includieren):
    Das Original:
    Code:
    static inline void UW_R()
    {
      OUT &= ~(_BV(UW_M) | _BV(UW_P));
      UW_ACTION = UW_A_R;
    }
    Als Makro (ebenfalls in den Header, evtl. Seiteneffekte beachten!)
    Code:
    #define UW_R() \
       do {
      OUT &= ~(_BV(UW_M) | _BV(UW_P));
      UW_ACTION = UW_A_R;
    } while(0)
    Das while (0) macht man, damit das ganze ein Block wird, und wie gewohnt benutzbar ist. Etwa:

    if (...)
    UW_R();
    else
    ...

    In beiden Fällen muss in dem Header auch das Zeug includet werden, das man sonst so braucht (<avr/io.h>, OUT, ...).

    Kommt auch drauf an, wo die Priorität ist, ob bei Code-Größe oder Geschwindigkeit und was OFF ist, etc.

    Inline ist übrigens nur eine Empfehlung an den Compiler, Code zu inlinen. Eine externe Funktion zu inlinen, kann z.B. nicht gehen. Die wird als ganz normale Funktion da stehen später. Und während ein Makro immer aufgelöst wird, wird nicht bei allen Optimierungsstufen geinlinet.
    Disclaimer: none. Sue me.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •