Forum: Mikrocontroller und Digitale Elektronik Wie binde ich .h - und .c Dateien in ein Projekt richtig ein?


von M. G. (ixil96)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte eine fertige h- und c-Datei eines Feuchtesensors (HTU21D) in 
mein Projekt einbinden. Als IDE verwende ich Atollic Truestudio.

Dazu habe ich die C-Datei htu21d.c in meinen Src-Ordner und die 
zugehörige Headerdatei htu21.h in den Inc-Ordner verschoben (wie im Bild 
dargestellt).
Danach habe ich ein Rebuild Project durchgeführt.

In main.c habe ich mit #include "htu21d.h" die Headerdatei eingebunden.

Beim Build bekomme ich die Fehlermeldung "..\Src\htu21d.c:44:17: fatal 
error: i2c.h: No such file or directory"

von Harry L. (mysth)


Lesenswert?

M. G. schrieb:
> Beim Build bekomme ich die Fehlermeldung "..\Src\htu21d.c:44:17: fatal
> error: i2c.h: No such file or directory"

Die gibt es in deinem Projekt ja auch (noch) nicht.
Du musst im CubeMX die I2C-Schnittstelle aktivieren.
Dann erzeugt CubeMX auch die nötige Header-Datei.

von M. G. (ixil96)


Lesenswert?

Das habe ich gemachten. In meinem ganzen Projektordner gibt es keine 
i2c.h Datei. Es gibt aber eine stm32l4xx_hal_i2c.h und die zugehörige .c 
Datei.

von Harry L. (mysth)


Lesenswert?

Du musst im CubeMX im Project-Manager unter Code-Generator den Haken bei 
"Generate peripherial initialization as a pair of c/h files" setzen und 
anschließend den Code neu generieren.

von M. G. (ixil96)


Lesenswert?

ok, dass hat mich einen Schritt weiter gebracht. Aber ich erhalte 
trotzdem Fehlermeldungen. Hier ein kleiner Ausschnitt davon...

..\Src\htu21d.c:530:18: note: (near initialization for 'read_transfer')
..\Src\htu21d.c:527:27: error: storage size of 'read_transfer' isn't 
known
  struct i2c_master_packet read_transfer = {
                           ^~~~~~~~~~~~~
..\Src\htu21d.c:540:20: error: 'STATUS_ERR_OVERFLOW' undeclared (first 
use in this function)
  if( i2c_status == STATUS_ERR_OVERFLOW )
                    ^~~~~~~~~~~~~~~~~~~
..\Src\htu21d.c:542:20: error: 'STATUS_OK' undeclared (first use in this 
function)
  if( i2c_status != STATUS_OK)
                    ^~~~~~~~~
..\Src\htu21d.c:527:27: warning: unused variable 'read_transfer' 
[-Wunused-variable]
  struct i2c_master_packet read_transfer = {


in main.c befinden sich folgende includes:
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "htu21d.h"

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

M. G. schrieb:
> in main.c befinden sich folgende includes:

Die sind alle nicht von Bedeutung, wenn es um die Übersetzung von 
"htu21d.c" geht, worauf die Fehlermeldungen schließen lassen.

In "htu21d.c" musst Du die Headerdatei einbinden, in der "struct 
i2c_master_packet" deklariert ist.

von Stefan F. (Gast)


Lesenswert?

Bist du denn sicher, dass deine HTU21D Library überhaupt für diese HAL 
geschrieben wurde?

Eine Datei mit Namen "i2c.h" gibt es sicher auch in vielen anderen 
Varianten.

von M. G. (ixil96)


Angehängte Dateien:

Lesenswert?

Ich habe nun die folgenden Programmzeilen in i2c.h eingebunden:
1
 enum i2c_transfer_direction
2
 {
3
   I2C_TRANSFER_WRITE = 0,
4
   I2C_TRANSFER_READ  = 1,
5
 };
6
7
 enum status_code
8
 {
9
   STATUS_OK           = 0x00,
10
   STATUS_ERR_OVERFLOW  = 0x01,
11
   STATUS_ERR_TIMEOUT  = 0x02,
12
 };
13
14
 struct i2c_master_packet
15
 {
16
   // Address to slave device
17
   uint16_t address;
18
    // Length of data array
19
    uint16_t data_length;
20
    // Data array containing all data to be transferred
21
    uint8_t *data;
22
 };
23
24
 void i2c_master_init(void);
25
 enum status_code i2c_master_read_packet_wait(struct i2c_master_packet *const packet);
26
 enum status_code i2c_master_write_packet_wait(struct i2c_master_packet *const packet);
27
 enum status_code i2c_master_write_packet_wait_no_stop(struct i2c_master_packet *const packet);

damit funktioniert zumindest die Kompilierung.

Wenn ich aber nun in main.c den Status über die in htu21.c 
bereitgestellte Funktion
1
bool htu21_is_connected(void)
2
{
3
  enum status_code i2c_status;
4
  
5
  struct i2c_master_packet transfer = {
6
    .address     = HTU21_ADDR,
7
    .data_length = 0,
8
    .data        = NULL,
9
  };
10
  /* Do the transfer */
11
  i2c_status = i2c_master_write_packet_wait(&transfer);
12
  if( i2c_status != STATUS_OK)
13
    return false;
14
  
15
  return true;
16
}

abrufen möchte, erhalte ich ein undefined reference to 
"i2c_master_write_packet_wait"

Ich habe mein Projekt als zip-Datei angehängt.

von Stefan F. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Bist du denn sicher, dass deine HTU21D Library überhaupt für diese HAL
> geschrieben wurde?

von M. G. (ixil96)


Lesenswert?


von Stefan F. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Bist du denn sicher, dass deine HTU21D Library überhaupt für diese HAL
> geschrieben wurde?

Du hast meine Frage nicht beantwortet.

> Es handelt sich hierbei um diese lib: 
https://github.com/TEConnectivity/HTU21D_Generic_C_Driver/

Diese Info hätte in den Eröffnungsbeitrag gehört!

In der README steht:
"This driver is intended to provide an implementation example of the 
sensor communication protocol, in order to be usable you have to 
implement a proper I2C layer for your target platform."

Wie hast du diesen Schritt umgesetzt? Ich vermute: gar nicht. Deswegen 
funktioniert es nicht. Die Library ist genersich, dass heißt, sie wurde 
eben nicht speziell für die Cube HAL geschrieben. Du musst sie selbst 
anpassen oder einen Kompatibilitätslayer zwischen diese Library und Cube 
HAL bauen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

M. G. schrieb:
> erhalte ich ein undefined reference to "i2c_master_write_packet_wait"

Das ist ein Linkerfehler. Das bedeutet, daß die Definition der Funktion 
"i2c_master_write_packet_wait" nicht existiert. Mit der Deklaration in 
"i2c.h" hast Du nur mitgeteilt, daß es diese Funktion irgendwo gibt.

Sofern Du in einer *.c-Datei diese Funktion implementiert hast, wird 
diese Datei nicht zu Deinem Programm gelinkt.

Und wenn man sich ansieht, was auf der Github-Seite steht, fällt das 
hier ins Auge:
1
  * The header "i2c.h" has to be implemented for your own platform to 
2
  * conform the following protocol :

Das bedeutet, daß Du diese Funktionen zur Verfügung stellen musst. Der 
Code auf github geht davon aus, daß es diese Funktionen gibt, Du musst 
sie für Deinen Controller schreiben/anpassen.


Im übrigen ist das keine "Lib" und auch keine "Library", dann nämlich 
wäre es nur eine Binärdatei *.a bzw. *.lib.

von M. G. (ixil96)


Lesenswert?

Ok, alles klar!
Danke für die Info!

Dann werde ich mal schauen ob es für meinen STM32L4xx eine Lib gibt bzw. 
programmiere die I2C Schnittstelle von Grund auf neu.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Rufus Τ. F. schrieb:
> Im übrigen ist das keine "Lib" und auch keine "Library"

Arduino hat diesbezüglich zu eine Reformation der Sprache bewirkt. Auch 
ein "Shield" ist plötzlich etwas ganz anderes.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefanus F. schrieb:
> Arduino hat diesbezüglich zu eine Reformation der Sprache bewirkt.

Das kann man ja, wenn man Arduino-Projekte bespricht, so beibehalten. 
Hier aber geht es um C, auch nicht um C++ (wo das Librarykonzept auch 
schon aufgeweicht wurde, ganz ohne Mitarbeit der Arduino-Leute).

von test (Gast)


Lesenswert?

Und wie nennt man das in c nun richtig? "Modul"?

von Stefan F. (Gast)


Lesenswert?

test schrieb:
> Und wie nennt man das in c nun richtig?

Quelltext

von test (Gast)


Lesenswert?

Stefanus F. schrieb:
> test schrieb:
> Und wie nennt man das in c nun richtig?
>
> Quelltext

OK, nochmal anders ;-)

Wie nennt man in c einen Typ von Quellcode den man z.B. in Pascal Unit 
und in Python Module nennt?

Muss es ja irgendeinen Namen für geben.

von Stefan F. (Gast)


Lesenswert?

test schrieb:
> Muss es ja irgendeinen Namen für geben.

Ich glaube, dafür gibt es (in C) keinen speziellen Namen.

von Oliver S. (oliverso)


Lesenswert?

Das Konzept „Modul“ gibt es in C nicht, daher gibts dafür auch keinen 
Namen.

Oliver
P.S. jetzt kommt bestimmt gleich das l-Wort ;)

von nfet (Gast)


Lesenswert?

Oliver S. schrieb:
> Das Konzept „Modul“ gibt es in C nicht, daher gibts dafür auch keinen
> Namen.
>
> Oliver
> P.S. jetzt kommt bestimmt gleich das l-Wort ;)

Du kannst natürlich sagen wikipedia ist dumm 
(https://de.wikipedia.org/wiki/Programmbibliothek#Bibliotheken_in_verschiedenen_Programmiersprachen) 
oder die Existenz der Standardlibrary in C leugnen, aber du musst damit 
rechnen ziemlich allein mit deiner Meinung dazustehen.

von nfet (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Im übrigen ist das keine "Lib" und auch keine "Library", dann nämlich
> wäre es nur eine Binärdatei *.a bzw. *.lib.

Wieso sollten nur objekt datein libraries sein? Auch du dürftest mit 
dieser Meinung (abseits vom Forum hier vielleicht ziemlich alleine 
dastehen.

von test (Gast)


Lesenswert?

Oliver S. schrieb:
> Das Konzept „Modul“ gibt es in C nicht, daher gibts dafür auch keinen
> Namen.

Naja, im Arduino Bereich sind Module sehr beliebt und verbreitet ;-)

Wobei man jetzt argumentieren könnte das es tatsächlich ganz normale 
libs sind. Weil wo ist der Unterschied zwischen normalen libs und das 
was Arduino macht? Die libs bei Arduino werden doch auch über das *.h 
eingebunden und dann am Ende dazugelinkt, oder?

von Stefan F. (Gast)


Lesenswert?

test schrieb:
> Weil wo ist der Unterschied zwischen normalen libs und das
> was Arduino macht?

Normale Libraries liegen in Binärform als *.a, *.o oder *.dll (Windows, 
nicht µC) vor. Dazu kommt die *.h Datei, um deren Außenschnittstelle zu 
beschreiben.

Bei Mikrocontrollern (auch Arduino) werden Bibliotheken aber meistens 
als Quelltext vertrieben, also als *.c bzw. *.cpp Datei(en). Ob sie dann 
noch "Library" heißen sollten/dürfen, da bin ich unsicher. Ich tendiere 
zu: ja.

von test (Gast)


Lesenswert?

Stefanus F. schrieb:
> Normale Libraries liegen in Binärform als *.a, *.o oder *.dll (Windows,
> nicht µC) vor. Dazu kommt die *.h Datei, um deren Außenschnittstelle zu
> beschreiben.

Das meinte ich ja, auch bei Arduino bindet man die *.h ein. Und der 
Compiler linkt dann die *.a (die vorher ggf. noch schnell aus den 
Quellcode erstellt wird) statisch dazu.
Oder habe ich da die Arduino IDE falsch verstanden? So genau hatte ich 
mir die noch nicht angeschaut.

von Stefan F. (Gast)


Lesenswert?

> Oder habe ich da die Arduino IDE falsch verstanden?

Hast du nicht, das stimmt schon so, wie du es beschrieben hast.

von Harry L. (mysth)


Lesenswert?

M. G. schrieb:
> Ich habe nun die folgenden Programmzeilen in i2c.h eingebunden:

Die i2c.h sollte man i.d.R. nicht antasten.
Deine Definitionen gehören da nicht rein.

M. G. schrieb:
> Dann werde ich mal schauen ob es für meinen STM32L4xx eine Lib gibt bzw.
> programmiere die I2C Schnittstelle von Grund auf neu.

Wen du schon an HAL scheiterst, wird das zu Fuß garantiert nix.
Gerade die i2c-Funktionen sind mit HAL absolut trivial.

von Stefan F. (Gast)


Lesenswert?

Harry L. schrieb:
> Gerade die i2c-Funktionen sind mit HAL absolut trivial.

Wirklich? ich habe sie mir noch nicht angeschaut. Die Hardware selbst 
ist da ja alles andere als trivial zu programmieren. Dein Satz klingt 
für mich nach einem dicken Lob zwischen den Zeilen.

von Harry L. (mysth)


Lesenswert?

Stefanus F. schrieb:
> Wirklich? ich habe sie mir noch nicht angeschaut.

Ja, wirklich!
Zumindest, wenn es nur darum geht, ein paar Bytes an ein I2c-Device zu 
senden.
Um die Initialisierung muß man sich nicht kümmern, und das eigentliche 
Senden ist genau 1 Zeile

Bsp.:
HAL_I2C_Master_Transmit(hlcdp, PCF8574_ADR(LCD_ADR), cmd, 2, 2);

Sendet 2 Byte (cmd) und wartet max. 2ms bevor ein Timeout eintritt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

nfet schrieb:
> Wieso sollten nur objekt datein libraries sein? Auch du dürftest mit
> dieser Meinung (abseits vom Forum hier vielleicht ziemlich alleine
> dastehen.

Objektdateien (*.o bzw. *.obj) sind Objektdateien und keine Libraries. 
Libraries (*.a bzw. *.lib) werden vom Linker bzw. Archiv-Tool aus 
mehreren Objektdateien zusammengestellt.

Ich stehe mit dieser Ansicht nicht alleine da; das ist /seit weit über 
30 Jahren/ der etablierte Sprachgebrauch, wenn es um C-Toolchains geht.

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.