Forum: Compiler & IDEs Datenübergabe an Headerdatei, eigene Headerdatei schreiben


von Jan W. (gaffel-k)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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
}

von Karl H. (kbuchegg)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Jan W. (gaffel-k)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Jan W. (gaffel-k)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Sebastian W. (wangnick)


Lesenswert?

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

von Jan W. (gaffel-k)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.