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"
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.
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.
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.
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"
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.
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.
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.
Stefanus F. schrieb: > Bist du denn sicher, dass deine HTU21D Library überhaupt für diese HAL > geschrieben wurde?
Es handelt sich hierbei um diese lib... https://github.com/TEConnectivity/HTU21D_Generic_C_Driver/blob/master/htu21d.c
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.
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.
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.
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.
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).
Und wie nennt man das in c nun richtig? "Modul"?
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.
test schrieb: > Muss es ja irgendeinen Namen für geben. Ich glaube, dafür gibt es (in C) keinen speziellen Namen.
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 ;)
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.
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.
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?
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.
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.
> Oder habe ich da die Arduino IDE falsch verstanden?
Hast du nicht, das stimmt schon so, wie du es beschrieben hast.
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.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.
