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
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?
Ich so ungefähr in dieser Art aufrufen: toggel(PIND3); danach soll sich der Zustand des Pins invertiert haben.
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 ); }
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.
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).
Danke für den Hinweiß. Meiner kanns: AT90CAN128; hab gerade nachgeschaut.
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.