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


von Wolfgang B. (logox2)


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

von DOcean (Gast)


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?

von Wolfgang B. (logox2)


Lesenswert?

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

von Karl H. (kbuchegg)


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

von Wolfgang B. (logox2)


Lesenswert?

Danke. Genau das ist es.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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:
1
#include <avr/io.h>
2
3
#define CONCAT(a,b) a##b
4
#ifdef USE_PINx_TOGGLE
5
#  define TOGGLE(a,b) CONCAT(PIN,a) = (1 << (b))
6
#else
7
#  define TOGGLE(a,b) CONCAT(PORT,a) ^= (1 << (b))
8
#endif
9
10
void
11
foo(void)
12
{
13
        TOGGLE(D, 4);
14
        TOGGLE(A, 0);
15
}

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.

von Wolfgang B. (logox2)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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

von Wolfgang B. (logox2)


Lesenswert?

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

von Wolfgang B. (logox2)


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
1
void foo()
2
 {
3
   Toggle(&PORTD, PD7 );
4
 }
übergeben?

von Karl H. (kbuchegg)


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
>
1
> void foo()
2
>  {
3
>    Toggle(&PORTD, PD7 );
4
>  }
5
>
> übergeben?


Mea culpa. Ich habs vorher nicht compiliert.

von Wolfgang B. (logox2)


Lesenswert?

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

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.