Hallo! Ich stehe im moment auf dem Schlauch. ich möchte gerne mit Keil5
den USart2 meines STM3210C-EVAL Boards (STM32F107VC) einrichten. Habe
mit dem Run-Time Environment Manager alles eingerichtet und das Projekt
erstellt. In der .c Datei "UART_STM32F10x.c" stehen alle Methoden, die
ich im Moment brauche (Uart_configuration zum einstellen der Baudrate
etc und UART_Write zum Senden eines Zeichens). Ich habe mir eine main
geschrieben, in der ich nun Zugriff auf diese Methoden haben möchte.
Normalerweise binde ich die dazugehörige .h Datei ein, und es passt.
Hier existiert aber keine .h Datei. Wenn ich die UART_STM32F10x.c
einbinde (also tatsächlich
#include "UART_STM32F10x.c" in der Main benutze) kommt ein "multible
define error: unter anderem (insgesamt 9 Fehler) zum Beispiel:
.\ComNew.axf: Error: L6200E: Symbol os_mutex_cb_USART2_Mutex_read
multiply defined (by uart_stm32f10x.o and main.o).)
Nun meine Frage: Muss ich mir eine eigene .h Datei schreiben, oder gibt
es da einen Trick den ich nicht verstehe? Wie euch vielleicht
aufgefallen ist habe ich noch nicht sehr viel Ahnung von c und
Mikrocontroller ^^
Hier die wichtigsten Codes:
Einmal die UART_STM3210x.c (erstellt von Keil):
--siehe Anhang--
Und hier noch meine Main (selbst geschrieben):
1
2
/* Includes ------------------------------------------------------------------*/
Irgendwie scheinen in deinem UART_STM32F10x.c quasi alle Funktionen
static zu sein und nur über eine Struktur von Funktionspointern je nach
URAT-Kanal übergeben zu werden.
stm32f10x.h wird natürlich doppelt eingebunden wenn du die .c Datei
direkt includest und schewint nicht doppeleinbindfest geschrieben zu
sein.
UART_WriteData ist nicht vorgesehen, von woanders aufgerufen zu werden.
Selbst UART1_WriteData nicht. Sondern eher ARM_DRIVER_UART
Driver_UART1[6](TxBuffer1, 1); allerdings wohl über eine
Treiberschnittstelle mit der die UART-Nummer ausgewählt wird.
Wobei Einzelzeichenübertragung natürlich so oder so suboptimal ist.
Eine .c mit entsprechendem Inhalt einzubinden ist schlimmstes,
unterirdisches Rumgefummel und zeugt von massiven Wissenslücken in der
C-Programmierung. Schreib dir eine .h wenn du eine brauchst. Ansonsten
wäre noch der intensive Blick in ein gutes C-Lehrbuch angesagt (nicht
irgendein im Internet zusammengegoogelter Scheiß).
Danke für die schnelle Antwort. Wenn ich in der main.c jedoch nur die
"UART_STM32F10x.c" ohne der "stm32f10x.h" einbinde, kommt trotzdem der
multible bind fehler. Ich muss nochmal durch das gesamte Programm
schauen, es existieren ja nicht nur diese zwei Klassen, sondern noch x
andere. Meiner Meinung jedoch wird bei "include" der gesamte Code der
inkludierten Datei eingefügt. Also bei mir in die main.c. Also sollte es
doch theoretisch funktionieren oder? Ich werde später nochmal schreiben,
muss mir wie gesagt jetzt alles noch mal durchschauen und deine Antwort
mit Einbeziehen.
> Meiner Meinung jedoch wird bei "include" der gesamte Code der> inkludierten Datei eingefügt.
Ja. Und wenn Du diese eine Datei in mehreren *.c Dateien einbindest,
dann erhälst Du doppelten Code.
Danke dass mit der Wissenslücke weiß ich auch selber. Deshalb frage ich.
Deine Antwort ist so sinnlos dass es mir fast graut darauf zu antworten
jedoch trotzdem:
- Da mir Keil die Datei automaisch einfügt und darin alle benötigten
Funktionen sind, muss es ja einen Weg geben diese einzubinden oder?
Leider existiert keine .h Datei, und da die .c schreibgeschützt ist ist
es wohl von Keil auch nicht vorgesehen, eine zu schreiben.
- nein...ein C-Buch? Wirklich? Was meinst was grade vor mir liegt? Das
hilft mir aber leider auch nicht weiter. kannst mir gern eins empfehlen
in dem speziell Mikrocontroller Programmierung verständlich erklärt
wird. Also mit allem drum und dran wie Clocks, Pins etc einrichten.
Joppe schrieb:> Leider existiert keine .h Datei, und da die .c schreibgeschützt ist ist> es wohl von Keil auch nicht vorgesehen, eine zu schreiben.
Was ist das für eine Logik?
Ganz einfach: Ich gehe davon aus, dass es eine simple Methode gibt, mit
dir ich Zugriff auf dieses .c File bekomme. Mir ist klar dass mein
Problem gelöst ist wenn ich eine .h anlege, jedoch würds mich
interessieren obs auch anders geht.
Joppe schrieb:> Ganz einfach: Ich gehe davon aus, dass es eine simple Methode> gibt, mit> dir ich Zugriff auf dieses .c File bekomme. Mir ist klar dass mein> Problem gelöst ist wenn ich eine .h anlege, jedoch würds mich> interessieren obs auch anders geht.
Ausserdem legt Keil das .c File schreibgeschützt an, ich kann es also
nicht verändern. Klar - ich copy paste das ganze in ein neues File,
dann kann ichs auch verändern. Aber wieso macht es Keil dann so?
Was meinst Du mit "Zugriff auf das C-File bekommen"?
Wenn Du aus einem anderen C-File auf Funktionen im ominösen C-File
zugreifen willst, dann brauchst Du Funktionsprototypen für diese
Funktionen, und gegebenenfalls auch die Typdefinitionen für von diesen
Funktionsprototypen verwendete Datentypen.
Die packt man üblicherweise in eine Headerdatei, die man idealerweise
genauso nennt wie das korrespondierende C-File.
Wo aber kommt das C-Sourcefile her, das Du da verwenden willst?
Woher weißt Du eigentlich, welche Funktionen daraus Du verwenden
möchtest?
Rufus Τ. Firefly schrieb:> Wo aber kommt das C-Sourcefile her, das Du da verwenden willst?
Aus dem Run-Time Environment Manager von keil5. Zur erklärung: Hier kann
man Treiber etc auswählen, die dann automatisch ins Projekt eingefügt
werden. Im Anhang ist ein bild dazu. Auf dem Bild seht ihr auch dass
unter "Drivers" eine UART_STM32F10x.c eingefügt wurde (von eben jenem
RTE Manager). Woher ich weiss dass sie Methoden beinhaltet die ich
brauche? Ich habs mir angesehen, und habe bemerkt dass die UART_WRITE
und UART_CONFIGURATION da drin steht. Gemeinsam mit der richtigen GPIO
Konfiguration dachte ich sei das Programm dann lauffähig.
Läubi .. schrieb:> Also ich würde mal sagen das wird über RTE_Device.h oder so> konfiguriert, und die c datei dann einfach mit kompiliert und gelinkt...
Ja, sieht deutlich so aus
http://www.keil.com/download/files/softwarecomponents.pdf
also ob akademische Hilfsprogrammierer bei Keil
mal wieder ein unheimlich flexibles und unverständliches Konzept
als angeblich programmierfreundlich anpreisen
so daß Kunden von Keil wie Joppe totel verloren sind.
RTE_Device.h wird der Header zu uart_stm32f10x.c sein.
Auch wenn dein Vorgehen vermutlich völlig abstrus ist, die Lösung ist
trotzdem einfach:
Wie Jörg schon schrieb, muß in den C-File, daß die Methoden bzw. Klassen
benutzt, deren Definition bekannt sein. Also schreib dir entweder ein
passendes .h-File mit den Definitionen selber, oder schreib die
Definitionen gleich mi in dein main.c
Mit Copy/Paste aus UART_STM32F10x.c ist das doch schnell gemacht.
Oliver
Oliver schrieb:> Wie Jörg schon schrieb, muß in den C-File, daß die Methoden bzw. Klassen> benutzt, deren Definition bekannt sein. Also schreib dir entweder ein> passendes .h-File mit den Definitionen selber, oder schreib die> Definitionen gleich mi in dein main.c
Nein, das ist nicht erforderlich:
> RTE_Device.h wird der Header zu uart_stm32f10x.c sein.
Und um auf Nummer Sicher zu gehen:
Einfach mal nach dem Namen einer Funktion aus dem ominösen C-File in
allen mitgelieferten Headerdateien suchen.
Wozu bieten die meisten IDEs eine Funktion à la "find in files", wozu
gibt es auf der Kommandozeile grep und findstr?
MaWin schrieb:> so daß Kunden von Keil wie Joppe totel verloren sind.
Ich hab bisher noch nie mit Keil gearbeitet, mir aber die "Arbeit"
gemacht, einfach mal den Kommentar zu der "includeten" Datei zu lesen,
da steht es nun nicht explizit drinn das es die Datei ist, aber man kann
es sich denken das sie im Zusammenhang steht.
Das Problem ist eher, das die "Kunden" keine oder wenig Ahnung von den
Grundlagen haben aber alles machen wollen ohne mal die Doku zu bemühen.
Joppe schrieb:> Hallo! Ich stehe im moment auf dem Schlauch.
Das glaube ich dir, nachdem ich ein Stück deines Quelltextes gesehen
habe. Oh Mann!!
Such dir mal in der Codesammlung die "Lernbetty" und lies in deren
Quellen, wie man sowas macht - sowohl mit dem Keil als auch mit dem GCC.
Kurzum, lerne zu allererst einmal, mit deinen Tools richtig umzugehen.
Und dann lerne, mit C-Quellen und Headerdateien richtig umzugehen.
Merke:
Zu jeder .c Datei schreibt man sich eine .h Datei, wo alles an
Deklarationen drinsteht, was die anderen Programmteile brauchen, um
die in der .c Datei enthaltene Funktionalität benutzen zu können. Und
NUR diese .h Datei wird woanders per #include eingebunden.
Alles, was nur innerhalb der besagten .c Datei von Interesse ist,
kommt NICHT in die .h Datei - eben weil es Zeugs ist, was all die
anderen Programmteile nix angeht.
Das tatsächliche Einbinden in den finalen Code erledigt der Linker -
entweder per Kommandozeile oder per Linkerscript, Linker-steuerdatei
oder wie man das gern nennen will.
W.S.
Eine .c Datei enthält Code, der nur für diese eine Datei interessant
ist.
Alles was andere davon interessieren könnte, kommt in die .h Datei.
Im Idealfall sieht man die .c Datei als Blackbox mit vielen Tasten und
Reglern an der Frontplatte. In der .h Datei steht die Beschriftung
dafür. Was in der Box genau passiert, sollte uninteressant sein. Sind
Nebeneffekte vorhanden (zB: Timer werden benutzt), so schreibt man das
als Kommentar in die .h Datei.
Die .h Datei ist also die Schnittstellenbeschreibung. Hier steht kein
Code drin.
Eine .c Datei steht immer für sich alleine. Sie wird nirgendwo per
Include eingebunden.
Zusammenfassen tut nur der Linker, niemand sonst.