Forum: Compiler & IDEs Datenübergabe an Headerdatei, eigene Headerdatei schreiben
Hallo zusammen,
bin gerade dabei eine eigene headerdatei zu schreiben um für folgende
projekte einfacher starten zu können, arbeite mich gerade in GCC und
atmelstudio ein. es geht darum, dass ich die ein- und ausgaben auf GPIOs
einfacher gestalten will.
hier erst mal der Code:
myheader.h:
1 | #ifndef myheader_h_
| 2 |
| 3 | #define myheader_h_
| 4 |
| 5 | extern uint8_t port;
| 6 | extern uint8_t pin;
| 7 |
| 8 |
| 9 | uint8_t setpin(uint8_t port, uint8_t pin);
| 10 |
| 11 | uint8_t clearpin(uint8_t port, uint8_t pin);
| 12 |
| 13 |
| 14 | #endif
|
myheader.c:
1 | #include <avr/io.h>
| 2 | #include "myheader.h"
| 3 |
| 4 |
| 5 | uint8_t setpin(uint8_t port, uint8_t pin)
| 6 | {
| 7 | if (port==PORTF){PORTF |= (1 << pin);
| 8 | }
| 9 | return 0;
| 10 | }
| 11 |
| 12 | uint8_t clearpin(uint8_t port, uint8_t pin)
| 13 | {
| 14 | if (port==PORTF){PORTF &= ~(1 << pin);
| 15 | }
| 16 | return 0;
| 17 | }
|
so funkioniert das ganze, möchte aber gerne auf IF oder SWITCH in der
setpin funktion verhindern, würde es gerne so schreiben:
1 | uint8_t setpin(uint8_t port, uint8_t pin)
| 2 | {
| 3 | port |= (1 << pin);
| 4 |
| 5 | return 0;
| 6 | }
|
das wäre ja einfacher und übersichtlicher, funktioniert aber leider
nicht, obwohl er das fehler- und warnungsfrei kompiliert.
in der main.c rufe ich die funktion z.b. mit
setpin(PORTF,0);
auf.
wisst ihr wie ich das Problem lösen kann? oder habt einen tipp für mich?
Vielen dank schon mal
Jan
Jan Wmann schrieb:
> setpin(PORTF,0);
Du übergibst hier den aktuellen Wert des PORTF.
Die Funktion kann zwar mit diesem Wert was machen, aber sie kann den
PORTF selber nicht verändern.
DAs ist im Grunde nichts anderes als hier 1 | int foo( int a )
| 2 | {
| 3 | a = 5;
| 4 | }
| 5 |
| 6 | int main()
| 7 | {
| 8 | int b = 8;
| 9 |
| 10 | foo( b );
| 11 | }
|
die Funktion kann mit ihrer lokalen Kopie des Wertes von b machen was
sie will, aber sie kann b so nicht verändern.
Die Lösung isr da wie dort die gleiche: Der Aufrufer übergibt einen
Pointer an die Funktion und ermöglicht ihr somit den Zugang zu ihrem
'Objekt', welches auch immer das ist.
1 | uint8_t setpin(volatile uint8_t* port, uint8_t pin)
| 2 | {
| 3 | (*port) |= (1 << pin);
| 4 |
| 5 | return 0;
| 6 | }
|
Im übrigen willst du diese Operation so eigentlich nicht haben.
Derartige Port-Setz bzw. Lösch Operationen haben einen ganz großen
Nachteil. Dadurch dass der Compiler den tatsächlichen Port und auch das
Bit nicht mehr kennt, kann er den Zugriff nicht mehr optimieren.
Daher will man so eine Lösung eher nicht als Funktion, sondern
implementiert sie als Makro direkt im Header-File
> funktioniert aber leider nicht, obwohl er das
> fehler- und warnungsfrei kompiliert.
Tja. Den Compiler interessiert die Logik dahinter nicht. Der überprüft
nur ob die Syntax stimmt. Und das tut sie.
Karl Heinz schrieb:
> Die Lösung isr da wie dort die gleiche: Der Aufrufer übergibt einen
> Pointer an die Funktion und ermöglicht ihr somit den Zugang zu ihrem
> 'Objekt', welches auch immer das ist.
> uint8_t setpin(volatile uint8_t* port, uint8_t pin)
> {
> (*port) |= (1 << pin);
>
> return 0;
> }
danke schon mal für deine Antwort,
habe das so wie oben jetzt abgeändert, es funktioniert aber leider immer
noch nicht.
Karl Heinz schrieb:
> Daher will man so eine Lösung eher nicht als Funktion, sondern
> implementiert sie als Makro direkt im Header-File
Also per #define im Header file?
Jan
Jan Wmann schrieb:
> habe das so wie oben jetzt abgeändert, es funktioniert aber leider immer
> noch nicht.
Bitte ganzen Code. Das funktioniert so. Bzw. was genau verstehst du
unter 'funktioniert nicht'.
1 | uint8_t setpin(volatile uint8_t* port, uint8_t pin)
| 2 | {
| 3 | (*port) |= (1 << pin);
| 4 |
| 5 | return 0;
| 6 | }
| 7 |
| 8 | int main()
| 9 | {
| 10 | ...
| 11 | setpin( &PORTF, 2 );
| 12 | ...
| 13 | }
|
Protoyp im Header File anpassen nicht vergessen!
>> Daher will man so eine Lösung eher nicht als Funktion, sondern
>> implementiert sie als Makro direkt im Header-File
>
>
> Also per #define im Header file?
genau
1 | #ifndef myheader_h_
| 2 | #define myheader_h_
| 3 |
| 4 | #define SET_BIT(p,b) ((p) |= (1<<(b)))
| 5 | #define CLR_BIT(p,b) ((p) &= ~(1<<(b)))
| 6 |
| 7 | #endif
|
an dieser Stelle hat dieses Makro keinen Nachteil und auch keine
versteckten Fallen. Man hätte allenfalls noch eine static inline
Funktion machen können, aber das bringt in diesem konkreten Fall nicht
wirklich was.
1 | #ifndef myheader_h_
| 2 |
| 3 | #define myheader_h_
| 4 |
| 5 |
| 6 | extern volatile uint8_t* port;
| 7 | extern uint8_t pin;
| 8 |
| 9 |
| 10 |
| 11 | uint8_t setpin(volatile uint8_t* port, uint8_t pin);
| 12 |
| 13 |
| 14 |
| 15 | #endif
|
1 | include <avr/io.h>
| 2 | #include "myheader.h"
| 3 |
| 4 |
| 5 |
| 6 | uint8_t setpin(volatile uint8_t* port, uint8_t pin)
| 7 | {
| 8 | (*port) |= (1 << pin);
| 9 |
| 10 | return 0;
| 11 | }
|
so habe ich das jetzt, und unter funktioniert nicht verstehe, dass ich
im Program die Funktion mit
SETPIN(PORTF,0);
aufrufe, der ausgang aber nicht gesetzt wird.
Das mit den Makros ist eine gute Idee, werde das auch so umsetzen.
Möchte aber trotzdem gerne verstehen, warum das oben noch nciht
funktioniert?
Jan
Jan Wmann schrieb:
> #ifndef myheader_h_
>
> #define myheader_h_
>
>
> extern volatile uint8_t* port;
> extern uint8_t pin;
wozu sollen die beiden extern Variablen hier gut sein?
Du hast ja gar keine globalen Variablen dieses Namens.
> uint8_t setpin(volatile uint8_t* port, uint8_t pin);
gut
>
> uint8_t setpin(volatile uint8_t* port, uint8_t pin)
> {
> (*port) |= (1 << pin);
>
> return 0;
> }
auch gut
> SETPIN(PORTF,0);
nicht gut.
Denn das kompiliert schon mal nicht.
Die Funktion heißt setpin und nicht SETPIN.
UNd sie will einen Pointer und keinen Integer-Wert.
Da hätte es eigentlich eine Warnung vom COmpiler geben sollen/müssen.
Irgendwas in der Richtung 'Makes pointer from integer without a cast"
Du solltest solche Warnungen ernst nehmen! Denn in den meisten Fällen
hat der COmpiler tatsächlich recht und die Codestelle ist tatsächlich
fehlerhaft.
setpin( &PORTF, 0 );
Jan Wmann schrieb:
> so habe ich das jetzt, und unter funktioniert nicht verstehe, dass ich
> im Program die Funktion mit
>
> SETPIN(PORTF,0);
>
> aufrufe, der ausgang aber nicht gesetzt wird.
SETPIN muss klein geschrieben werden ;)
Nee, Jan, lies mal gründlicher. Karl-Heinz hat's doch schon geschrieben:
Du musst die Adresse des Ports übergeben, also &PORTF!
LG, Sebastian
hatte beides klein geschrieben, also setpin, hatte das nur hier im text
groß geschrieben, dass groß- und kleinschrift unterschiedlich ist weiß
ich.
es lag an dem aufruf der funktion mit dem "&".
merkwürdig ist nur, dass der compiler, wenn keine fehler vorliegen,
nicht die warnungen anzeigt. das kann man aber bestimmt irgendwo
einstellen.
Hatte die warnung
Karl Heinz schrieb:
> Makes pointer from integer without a cast
dann gesehen, wie peinlich :-)
aber danke euch auf jeden fall, probiere mich jetzt mal daran, dass in
makros zu machen.
Jan
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|