Forum: Mikrocontroller und Digitale Elektronik Einbindung einer .c ohne .h


von Joppe (Gast)


Angehängte Dateien:

Lesenswert?

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 ------------------------------------------------------------------*/   
3
              // Device header
4
   
5
#include "stm32f10x.h"                  // Device header
6
7
#include "UART_STM32F10x.c"
8
9
10
       
11
    /* Private variables ---------------------------------------------------------*/   
12
    //USART_InitTypeDef USART_InitStructure;   
13
    u8 TxBuffer1[] = "Hello World";   
14
   
15
     
16
       
17
    /* Private function prototypes -----------------------------------------------*/   
18
      
19
 
20
         
21
    /* Private functions ---------------------------------------------------------*/   
22
       
23
    /*******************************************************************************  
24
    * Function Name  : main  
25
    * Description    : Main program  
26
    * Input          : None  
27
    * Output         : None  
28
    * Return         : None  
29
    *******************************************************************************/   
30
    int main(void)   
31
    {   
32
   
33
      __DRIVER_UART_H;
34
       UART_Configure(8,1,ARM_UART_PARITY_NONE,ARM_UART_STOP_BITS_1,ARM_UART_FLOW_CONTROL_NONE,ptr_UART[1]);
35
   
36
       
37
      while(1)   
38
      {   
39
        /* Wait until end of transmit */   
40
    
41
    UART_WriteData(TxBuffer1, 1, ptr_UART[1]);
42
              
43
      }   
44
         
45
 
46
  
47
    }

von MaWin (Gast)


Lesenswert?

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.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

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

von Joppe (Gast)


Lesenswert?

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.

von Stefanus (Gast)


Lesenswert?

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

von Joppe (Gast)


Lesenswert?

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.

von Joppe (Gast)


Lesenswert?

@ Stefanus (Gast)

Na klar - logisch. Ich muss nochmal drüber schauen. Danke euch!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?

von Joppe (Gast)


Lesenswert?

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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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

von Joppe (Gast)


Lesenswert?

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?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?

von Joppe (Gast)


Lesenswert?

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.

von Joppe (Gast)


Angehängte Dateien:

Lesenswert?

Entschuldigung, vergessen das Bild anzuhängen

von MaWin (Gast)


Lesenswert?

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.

von Oliver (Gast)


Lesenswert?

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

von Joppe (Gast)


Lesenswert?

ich bin gerade dabei. Meld mich wenn ich mehr weiss. Danke derweil!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

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.

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.