www.mikrocontroller.net

Forum: Compiler & IDEs Wie c-Funktion schreiben: Port-Pin toggeln?


Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,
wie muß ich eine Funktion in C (für AVR; avrlib-c) der ich als Parameter 
einen Port-Pin übergebe, und diese Funktion mir den dann toggeln soll?

Danke für Hilfe

Wolfgang

Autor: DOcean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soll sich bei jedem Aufruf der Funktion der Zustand ändern?

Oder soll das selbstständig ablaufen?

Wozu soll das gut sein?

Oder wie schnell willst du umschalten?

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich so ungefähr in dieser Art aufrufen:
 toggel(PIND3);
danach soll sich der Zustand des Pins invertiert haben.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang Birner wrote:
> Ich so ungefähr in dieser Art aufrufen:
>  toggel(PIND3);
> danach soll sich der Zustand des Pins invertiert haben.

So gehts gar nicht.
Du musst den Port und den Pin getrennt übergeben.
Den Port übergibst du als Pointer zu volatile uint8_t

void Toggle( volatile uint8_t* Port, uint8_t Pin )
{
  *Port ^= ( 1 << Pin );
}

void foo()
{
  Toggle( PORTD, PD7 );
}

Das Schieben in der Funktion ist nicht so toll, da es zur
Laufzeit gemacht werden muss. Besser wäre es daher, die
Schieberei in den Aufruf zu verlagern

void Toggle( volatile uint8_t* Port, uint8_t Value )
{
  *Port ^= Value;
}

void foo()
{
  Toggle( PORTD, 1 << PD7 );
}

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke. Genau das ist es.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Übergabe der Adresse und das generische Abarbeiten innerhalb
von Toggle() erzeugt aber einiges an Overhead.  Mit einem Makro
kann man das eleganter lösen:
#include <avr/io.h>

#define CONCAT(a,b) a##b
#ifdef USE_PINx_TOGGLE
#  define TOGGLE(a,b) CONCAT(PIN,a) = (1 << (b))
#else
#  define TOGGLE(a,b) CONCAT(PORT,a) ^= (1 << (b))
#endif

void
foo(void)
{
        TOGGLE(D, 4);
        TOGGLE(A, 0);
}

Wenn man einen neueren AVR hat, kann der seine Portpins umschalten,
indem man das PINx-Register beschreibt.  Dafür obiges Stück mit
-DUSE_PINx_TOGGLE compilieren.  Bei älteren AVRs geht das nicht,
da muss dann read/modify/write-Code generiert werden.

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was zählt denn zu den neueren/älteren AVRs?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang Birner wrote:

> Was zählt denn zu den neueren/älteren AVRs?

Musste ins jeweilige Datenblatt gucken.  Wenn die Funktionalität
existiert, gibt es eine eigene Zwischenüberschrift "Toggling the
Pin" unter "I/O-Ports" -> "Ports as General Digital I/O".

Idealerweise sollte der Compiler das wissen und könnte dann die
XOR-Operation gleich entsprechend optimieren, aber das hat ihm noch
keiner beigebracht (und es würde den Rahmen der derzeitigen
Klassifizierung der AVR-Cores im GCC sprengen, es müsste also
ziemlich viel neu gemacht werden).

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweiß.
Meiner kanns: AT90CAN128; hab gerade nachgeschaut.

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> void foo()
> {
>   Toggle( PORTD, PD7 );
> }

Beim ersten compilieren ist mir aufgefallen: müsste ich hier nicht 
eigentlich die Adresse mit
void foo()
 {
   Toggle(&PORTD, PD7 );
 }
übergeben?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wolfgang Birner wrote:
> Karl heinz Buchegger wrote:
>> void foo()
>> {
>>   Toggle( PORTD, PD7 );
>> }
>
> Beim ersten compilieren ist mir aufgefallen: müsste ich hier nicht
> eigentlich die Adresse mit
>
> void foo()
>  {
>    Toggle(&PORTD, PD7 );
>  }
> 
> übergeben?


Mea culpa. Ich habs vorher nicht compiliert.

Autor: Wolfgang Birner (logox2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke nochmal für die Hilfe, ich war wirklich irgendwie auf dem Schlauch 
gestanden und hab mein Brett vorm Kopf nicht gesehen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.