Hey,
ich würde gerne mit einem Atmega328P per UART mit einem USB-TTL Adapter
kommunizieren. Hierbei stocke ich etwas bei folgendem Problem:
Ich möchte gerne in der main.c meine CPU Frequenz und Baudrate mit
1
#define F_CPU 8000000UL
2
#define UART_BAUD_RATE 19200
definieren. Danach folgt u.a.
1
#include<util/delay.h>
2
#include"uart.h"
In der uart.h wird das Baudregister entsprechend Datenblatt mit
1
#define MYUBRR F_CPU/16/UART_BAUD_RATE-1
berechnet.
Beim Kompilieren tritt ein Fehler auf, weil die uart.h weder F_CPU noch
UART_BAUD_RATE kennt. Offenbar stört sich die ebenfalls inkludierte
delay.h daran nicht, weil eine in der main.c blinkende LED problemlos
mit der korrekten Verzögerung blinkt.
Wieso ist der delay.h meine defines bekannt, der uart.h aber nicht?
Danke schön!
Deswegen stellt an solche Defines, die Datei-Übergreifend bekannt sein
sollen, besser im Makefile oder Projekt als Kommandozeilen-Option für
den Compiler ein. Dann spielt es keine Rolle, in welcher Beziehung die
Dateien zueinander stehen und in welcher Reihenfolge der Compiler sie
lädt.
gcc -D F_CPU=8000000 -DBAUD=38400
Die Werte für die Baudraten-Register berechnet man besser nicht selbst,
sondern überlässt es den bewährten Algorithmen in der C Bibliothek
setbaud.h.
mitlesa schrieb:> Mit welcher Entwicklungsumgebung arbeitest du?
Microchip Studio.
Stefan ⛄ F. schrieb:> gcc -D F_CPU=8000000 -DBAUD=38400
Wo soll ich das denn eingeben/definieren?
Sef C. schrieb:>> gcc -D F_CPU=8000000 -DBAUD=38400> Wo soll ich das denn eingeben/definieren?
Ich bin mit deiner IDE nicht vertraut. Irgendwo wird es ein
Dialogfenster geben, wo man die Parameter zum Compiler eingeben kann.
Eventuell sogar grafisch aufbereitet unter dem Stichwort "Preprocessor"
oder "Definitions".
Bei meiner IDE sieht das so aus, wie im Anhang gezeigt.
Stefan ⛄ F. schrieb:> Sef C. schrieb:>>> gcc -D F_CPU=8000000 -DBAUD=38400>> Wo soll ich das denn eingeben/definieren?>> Ich bin mit deiner IDE nicht vertraut. Irgendwo wird es ein> Dialogfenster geben, wo man die Parameter zum Compiler eingeben kann.> Eventuell sogar grafisch aufbereitet unter dem Stichwort "Preprocessor"> oder "Definitions".>> Bei meiner IDE sieht das so aus, wie im Anhang gezeigt.
Eine Möglichkeit das im Quellcode zu machen gibt es nicht sinnvoll? Ich
wechsele ständig den uC und die Taktfrequenz :(
Danke dir für den Tipp mit setbaud.h, habe ich direkt so in meine uart.h
integriert :)
Sef C. schrieb:> Ich möchte gerne in der main.c meine CPU Frequenz und Baudrate> ...> definieren.
Nö, lieber nicht. Sowas sollte man im zugehörigen Lowlevel-Treiber für
den UART erledigen und nicht in main.c tun müssen.
Aber das klärt noch nicht dein momentanes Problem. Das besteht wohl
darin, daß dein uart.c die zwei Zeilen mit F_CPU und UART_BAUD_RATE
nicht kennt. Nun rate mal, woran das liegen mag, wenn du das lediglich
in main.c geschrieben hast.
W.S.
Sef C. schrieb:> Eine Möglichkeit das im Quellcode zu machen gibt es nicht sinnvoll? Ich> wechsele ständig den uC und die Taktfrequenz
Dann musst du das in den Project Settings sowieso machen.
Hier sind die richtigen Orte für Einstellungen.
Sef C. schrieb:> Ich wechsele ständig den uC und die Taktfrequenz
Dazu legt man sich praktischerweise mehrere Projekte im
gleichen Arbeitsverzeichnis an und benutzt immer die gleichen
Sources. Das erzeugt im Studio keinen Widerspruch. So
"schaltet" man mit dem einfachen Laden eines anderen Projekts
schnell auf eine andere Konfiguration um ohne sein gedankliches
Sourcen-Gefüge ändern zu müssen.
Neues Anlegen eines Projekts ist nur einmal nötig, die
(veränderten) Projekteinstellungen erzeugt man indem man eine
Kopie der Projektdatei (*.cproj) erzeugt und diese Kopie dann
geeignet einstellt.
W.S. schrieb:> Aber das klärt noch nicht dein momentanes Problem. Das besteht wohl> darin, daß dein uart.c die zwei Zeilen mit F_CPU und UART_BAUD_RATE> nicht kennt. Nun rate mal, woran das liegen mag, wenn du das lediglich> in main.c geschrieben hast.
Und wieso kennt die delay.h die korrekte F_CPU (8 MHz)?
Das merke ich daran das eine LED in der main.c mit _delay_ms(1000)
korrekt blinkt sowie der folgende Code keine Warning wirft:
1
#ifndef F_CPU
2
/* prevent compiler error by supplying a default */
3
# warning "F_CPU not defined for <util/delay.h>"
4
/** \ingroup util_delay
5
\def F_CPU
6
\brief CPU frequency in Hz
7
8
The macro F_CPU specifies the CPU frequency to be considered by
9
the delay macros. This macro is normally supplied by the
10
environment (e.g. from within a project header, or the project's
11
Makefile). The value 1 MHz here is only provided as a "vanilla"
12
fallback if no such user-provided definition could be found.
13
14
In terms of the delay functions, the CPU frequency can be given as
15
a floating-point constant (e.g. 3.6864E6 for 3.6864 MHz).
16
However, the macros in <util/setbaud.h> require it to be an
W.S. schrieb:> Sef C. schrieb:>> Ich möchte gerne in der main.c meine CPU Frequenz und Baudrate>> ...>> definieren.>> Nö, lieber nicht. Sowas sollte man im zugehörigen Lowlevel-Treiber für> den UART erledigen und nicht in main.c tun müssen.
Du willst nicht wirklich in allen verwendeten Lowlevel-Treibern
rumfummeln, nur weil du einen anderen Quarz in den Taktgenerator des µC
gesteckt hast.
Wolfgang schrieb:> Du willst nicht wirklich in allen verwendeten Lowlevel-Treibern> rumfummeln, nur weil du einen anderen Quarz in den Taktgenerator des µC> gesteckt hast.
Doch, Betonköpfe, die sich das einmal so eingerichtet haben,
wollen das so. Da hilft auch nichts mehr zu beschreiben wie
man es wirklich richtig macht.
Sef C. schrieb:> Eine Möglichkeit das im Quellcode zu machen gibt es nicht sinnvoll? Ich> wechsele ständig den uC und die Taktfrequenz :(
Gerade dann solltest du besser Makefiles benutzen, damit du an einer
zentralen Stelle alle relevanten Parameter konfigurieren kannst. So löst
du dich auch von der Abhängigkeit zu einer bestimmten IDE.
Jede anständige IDE kann Makefile-Projekte öffnen.
Wo ich arbeite, steht jedem Entwickler frei, irgendeine IDE (oder gar
keine) zu benutzen. Jeder soll verwenden, womit er am besten klar kommt.
Aber jedes Projekt muss ein Makefile (oder etwas äquivalentes) haben, so
dass es unabhängig von jeder IDE compiliert werden kann. Wir haben auch
eine gewisse Unabhängigkeit vom Desktop Betriebssystem etabliert. Die
Entwickler dürfen Linux, Windows oder Mac OS benutzen.
Ich müsste lügen wenn ich sagen würde dass das völlig ohne Probleme
klappen würde. Aber diese waren bisher alle gut lösbar und die Vorteile
überwiegen.
Das ist ein völlig unnötiger, beleidigender Kommentar der die hier
gestellten Fragen nicht beantwortet:
mitlesa schrieb:> Doch, Betonköpfe, die sich das einmal so eingerichtet haben,> wollen das so. Da hilft auch nichts mehr zu beschreiben wie> man es wirklich richtig macht.
Das ist ein sinnvoller, freundlicher und erklärender Kommentar der die
hier gestellten Fragen sachlich beantwortet, sodass es auch anderen die
über das selbe Problem stolpern weiter hilft:
Stefan ⛄ F. schrieb:> Gerade dann solltest du besser Makefiles benutzen, damit du an einer> zentralen Stelle alle relevanten Parameter konfigurieren kannst. So löst> du dich auch von der Abhängigkeit zu einer bestimmten IDE.>> Jede anständige IDE kann Makefile-Projekte öffnen.>> Wo ich arbeite, steht jedem Entwickler frei, irgendeine IDE (oder gar> keine) zu benutzen. Jeder soll verwenden, womit er am besten klar kommt.> Aber jedes Projekt muss ein Makefile (oder etwas äquivalentes) haben, so> dass es unabhängig von jeder IDE compiliert werden kann. Wir haben auch> eine gewisse Unabhängigkeit vom Desktop Betriebssystem etabliert. Die> Entwickler dürfen Linux, Windows oder Mac OS benutzen.>> Ich müsste lügen wenn ich sagen würde dass das völlig ohne Probleme> klappen würde. Aber diese waren bisher alle gut lösbar und die Vorteile> überwiegen.
Danke dir, tolle Erklärung die ich Betonkopf jetzt in Zukunft so
umsetzen werden.
Nur so am Rande:
Defines sollte man in Header-Files schreiben, damit sie auch für andere
Programmteile "global" verfügbar sind (, weil nur diese
Quellcode-Dateien inkludiert werden sollten).
Schreibt man sie in die .c-Datei, ist das wie mit lokalen Dateien: Sie
sind nur innerhalb der Datei verfügbar (kollidieren aber mit
gleichnamigen Defines, die von "außerhalb" kommen.)
mitlesa schrieb:> Dann musst du das in den Project Settings sowieso machen.> Hier sind die richtigen Orte für Einstellungen.Sef C. schrieb:> Und wieso kennt die delay.h die korrekte F_CPU (8 MHz)?Sef C. schrieb:> Eine Möglichkeit das im Quellcode zu machen gibt es nicht sinnvoll? Ich> wechsele ständig den uC und die Taktfrequenz :(
Hmm... zuviele Mißverständnisse auf einem Haufen.
Also:
1. wenn man ständig den µC-Typ wechselt, dann darf man auch damit
rechnen, daß unterschiedliche Hersteller/Produktreihen auch diverse
Unterschiede in den Peripherie-Cores haben. Also ist einem mit nur einem
UART-Treiber nicht wirklich gedient, da müssen an die jeweilige Hardware
angepaßte Lowlevel-Treiber her. Das einzige, was für alle gleich sein
sollte, ist der Inhalt der zugehörigen uart.h, damit all die höheren
Programmschichten sich nicht um die jeweiligen Befindlichkeiten der
Peripherie kümmern müssen. Das schließt auch die Berechnung von
Teilerverhältnissen in main.c aus. Diese Berechnung gehört in den
Lowlevel-Treiber. Allerdings ist es sinnvoll, die UART-Initialisierung
mit der gewünschten Baudrate als Argument aufzurufen.
Beispiel:
[c]
Uart0_init(9600);
{/c]
Und zur Frage, wo die betreffende uart0.c die Information über die
aktuelle Taktfrequenz herkriegt: Diese Information sollte von dem
Treiber kommen, der das Taktsystem aufsetzt. Das ist wiederum nicht
main.c, sondern eine separate Quelle, die chipabhängig ist und deshalb
bei Chipwechsel ebenfalls neu zu schreiben wäre. Und: mal bedenken, daß
es durchaus sein kann, daß UART0 an einem anderen Peripherie-Bus sitzt
als UART1, und die diversen Peripherie-Busse auch verschiedene Taktraten
haben können.
2. Eine Header-Datei (xxx.h) soll nur zum Bekanntgeben von Dingen
herhalten, die in der zugehörigen xxx.c vorhanden sind. So eine
Headerdatei enthält zumeist selber keinen Code, sondern wird nur wie
ein gewöhnliches Textstück in die inkludierende Datei aufgenommen. Eine
Datei 'delay.h' kennt also keinerlei Taktfrequenz. Das ist Angelegenheit
der Datei, wo die Inklude-Anweisung steht.
3. Irgendwelche programmrelevanten Einstellungen in der Projektdatei
irgendeiner IDE oder in einem Makefile zu machen, ist eine drastische
Einschränkung, denn dann kann das betreffende Projekt NUR mit genau
dieser IDE bzw. diesem Make überhaupt übersetzt werden.
Also:
Alles, was für die zu erzeugende Firmware nötig ist, gehört auch in die
Quelldateien dieser Firmware und nicht irgendwo anders hin. Wenn man das
nicht genau so beachtet und es anders hält, dann nagelt man sich selbst
auf eine bestimmte IDE bzw. Make fest.
W.S.
W.S. schrieb:> 3. Irgendwelche programmrelevanten Einstellungen in der Projektdatei> irgendeiner IDE oder in einem Makefile zu machen, ist eine drastische> Einschränkung, denn dann kann das betreffende Projekt NUR mit genau> dieser IDE bzw. diesem Make überhaupt übersetzt werden.
Was die IDE angeht stimme ich dir zu. Aber Makefiles sind seit Anbeginn
der Programmiersprache bis heute Standard.
Was meinst du mit "NUR mit genau diesem Make"?
Wer ganz sicher gehen will, alte Quelltexte auch in Zukunft übersetzen
zu können, sollte alle am Build beteiligten Programme samt
Betriebssystem gut aufbewahren. make ist da allerdings meine geringste
sorge. Ich musste noch nie ein Makefile an eine andere Version von Make
anpassen.
Stefan ⛄ F. schrieb:> Was meinst du mit "NUR mit genau diesem Make"?
Versuche mal, auf einem Windows PC, wo diverse Toolchains drauf sind,
irgend etwas per Make zu machen. Das wird nix, weil es da diverse
verschiedene make.exe gibt, die jeweils NUR ihr toolchainspezifisches
Zeugs kennen und man folglich ein babylonisches Sprachproblem auf dem PC
hat.
W.S.
W.S. schrieb:> Versuche mal, auf einem Windows PC, wo diverse Toolchains drauf sind,> irgend etwas per Make zu machen. Das wird nix, weil es da diverse> verschiedene make.exe gibt, die jeweils NUR ihr toolchainspezifisches> Zeugs kennen und man folglich ein babylonisches Sprachproblem auf dem PC> hat.
Hm. Wenn sich das Programm „make.exe“ nennt, dann ist die dortige
Versionsvielfalt dann doch sehr überschaubar. Und vor allem lässt sich
das in den meisten Fällen auf eine einzige Version vereinfachen.
Spielt aber alles keine Rolle, ein makefile ist natürlich Teil des
Quelltextes, und gehört mit in die Versionsverwaltung, und später
archiviert.
Oliver
W.S. schrieb:> Das wird nix, weil es da diverse> verschiedene make.exe gibt, die jeweils NUR ihr toolchainspezifisches> Zeugs kennen und man folglich ein babylonisches Sprachproblem auf dem PC> hat.
Mal wieder keine Ahnung, aber sinnlos rumkrakelen?
Mit der selben make.exe kann ich makefiles für x64, AVR, ARM und MIPS
durchnudeln. (Was ich eben so nutze, es kann eben alles was im makefile
steht)
Man merkt, dass du echt von NICHTS auch nur die geringste Ahnung hast!
Alles außer deinem heißgeliebten Keil is zu hoch für dich ;)
Tröste dich: hier hat genau genommen keiner Ahnung, weil niemand die
Quelltexte kennt.
Da kann man nur wilrd spekulieren.
Kann es sein, daß die uart.h direkt oder indirekt schon vor dem #define
mal verwendet wird?
Ansonsten halt mal die Quelltexte zeigen, sonst kann man nichts sagen
(was viele aber nicht abhält).
Klaus W. schrieb:> Kann es sein, daß die uart.h direkt oder indirekt schon vor dem #define> mal verwendet wird?
Spielt keine Rolle. Was in main.c definiert wurde, ist in uart.c
höchstwahrscheinlich nicht bekannt. Deshalb geht blinky aber das
Projekt mit uart.c geht nicht. Und der TO wundert sich darüber: "Und
wieso kennt die delay.h die korrekte F_CPU (8 MHz)?"
W.S.
Oliver S. schrieb:> Hm. Wenn sich das Programm „make.exe“ nennt,...
Stell dir vor, du hast 3 oder mehr Dateien auf der Platte, die sich alle
make.exe nennen, aber zu herzlich unterschiedlichen Programmiersystemen
gehören. Selbst hier auf diesem Notebook findet sich ein make.exe, was
aber zu Lazarus gehört und mit C rein garnix zu tun hat.
Also, wer sich wirklich niemals aus dem C-Gefilde heraus begibt und
womöglich nur den GCC benutzt, der kommt nicht in die Verlegenheit, das
verkehrte make zu benutzen, so daß er das Problem nicht kennt.
Das kann man aber nicht immer als gegeben annehmen. Deshalb sage ich:
IDE-Projektdateien und Makefiles (also Make-Projektdateien) sind nicht
die geeeigneten Orte, wo firmwarespezifisches Zeugs definiert werden
soll. Diese Dateien sollen lediglich zum Übersetzen der zum Projekt
gehörigen Dateien dienen, aber nicht (wie vorgeschlagen wurde)
Festlegungen enthalten, ob der UART nun auf 9600 Baud oder einer anderen
Rate laufen soll.
W.S.
Ich denke es macht keinen Sinn mit W.S. über Programmierstil zu
diskutieren. Der hat seinen eigenen Stil und kommt mit anderen Meinungen
nicht klar. Selbst wo es technisch notwendig ist lästert er lieber über
betroffene Produkte ab, anstatt die harten Fakten hin zu nehmen. Das
hatten wir hier schon oft genug.
Stefan ⛄ F. schrieb:> Ich denke es macht keinen Sinn mit W.S. über Programmierstil zu> diskutieren.
Nicht nur beim Programmierstil ist das so.
Es fehlt auch immerwieder an Grundlagenwissen.
Haste ja eben gelesen, er lästert über make ab und aus seinem Geschwafel
wird schnell klar, dass er absolut keine Ahnung vom Thema hat.
Sef C. schrieb:> weil die uart.h weder F_CPU noch> UART_BAUD_RATE kennt
Muß sie auch nicht. Erst an der Stelle, wo das Macro expandiert wird,
müssen alle verwendeten Defines bekannt sein.
W.S. schrieb:> Aber das klärt noch nicht dein momentanes Problem. Das besteht wohl> darin, daß dein uart.c die zwei Zeilen mit F_CPU und UART_BAUD_RATE> nicht kennt. Nun rate mal, woran das liegen mag, wenn du das lediglich> in main.c geschrieben hast.W.S. schrieb:> Spielt keine Rolle. Was in main.c definiert wurde, ist in uart.c> höchstwahrscheinlich nicht bekannt. Deshalb geht blinky aber das> Projekt mit uart.c geht nicht. Und der TO wundert sich darüber: "Und> wieso kennt die delay.h die korrekte F_CPU (8 MHz)?">> W.S.
Mir kommt es so vor, als würdest du einfach nicht verstehen was ich hier
beschreibe.
Hier meine main.c:
Ich definiere vor den #includes die CPU Frequenz. Dieses #define ist der
delay.h beim kompilieren bekannt. Das merkt man daran, dass sich die
delay.h nicht mit der Warning "F_CPU not defined" beschwert und meine
STATUS_LED korrekt blinkt.
Die uart.h beschwert sich aber darüber, dass sie F_CPU nicht kennt wenn
ich es nicht zusätzlich dort reinschreiben.
Meine Frage ist einzig und alleine: Ein #define und darunter zwei
inkludierte Files. Die eine inkludierte Datei kennt das #definde, die
andere nicht. Wieso?
Sef C. schrieb:> Wieso?
Weil es deine uart.h einen Scheiss interessiert,was du irgendwo
definiert hast. Die einzigen, die das interessiert, sind die Funktionen
in uart.c. Die werden aber von der Information verschont, da die defines
dafür in der uart.h drinstehen müssen und nicht irgendwo davor. Es sei
denn, die Informationen stehen in den Projekteinstellungen. Das wurde
hier aber auch schon mehrfach erwähnt.
Dyson schrieb:> Weil es deine uart.h einen Scheiss interessiert,was du irgendwo> definiert hast. Die einzigen, die das interessiert, sind die Funktionen> in uart.c. Die werden aber von der Information verschont, da die defines> dafür in der uart.h drinstehen müssen und nicht irgendwo davor. Es sei> denn, die Informationen stehen in den Projekteinstellungen. Das wurde> hier aber auch schon mehrfach erwähnt.
...und der Nächste der nicht erklärt, wieso der delay.h die in der
main.c definierte CPU Frequenz bekannt ist...
Bei delay ist das anders, weil der Quelltext der Funktion ausnahmsweise
in der header Datei steht.
https://github.com/vancegroup-mirrors/avr-libc/blob/master/avr-libc/include/util/delay.h.in
Zeile 142.
Wärend der Compiler diesen Code übersetzt ist F_CPU bekannt. Denn die
Datei wird ausschließlich in main.c inkludiert nachdem dort F_CPU
definiert wurde.
Bei der uart.h ist das anders. Die wird nicht nur von main.c inkludiert
(wo es kein Problem gibt) sondern auch von uart.c. Wenn der Compiler die
uart.c compiliert, ist F_CPU undefiniert.
Bedenke: Der Compiler wird für jede *.c Datei einzeln aufgerufen, um
eine gleichnamige *.o Datei zu erzeugen. Die main.c wird als letzte
compiliert. Erst danach kombiniert der Linker die vielen *.o Dateien zu
einem ausführbaren Programm.
Stefan ⛄ F. schrieb:> Bei delay ist das anders, weil der Quelltext der Funktion ausnahmsweise> in der header Datei steht.>> https://github.com/vancegroup-mirrors/avr-libc/blob/master/avr-libc/include/util/delay.h.in>> Zeile 142.>> Wärend der Compiler diesen Code übersetzt ist F_CPU bekannt. Denn die> Datei wird ausschließlich in main.c inkludiert nachdem dort F_CPU> definiert wurde.>> Bei der uart.h ist das anders. Die wird nicht nur von main.c inkludiert> (wo es kein Problem gibt) sondern auch von uart.c. Wenn der Compiler die> uart.c compiliert, ist F_CPU undefiniert.
Genau diesen Unterschied habe ich auch bemerkt und deswegen den Code aus
der uart.c in die uart.h kopiert (und in der .c gelöscht) und es klappte
trotzdem nicht. Wenigstens hast du meine Frage verstanden :)
Sef C. schrieb:> ...und der Nächste der nicht erklärt, wieso der delay.h die in der> main.c definierte CPU Frequenz bekannt ist...
weil der gesamte delay-Kram in der delay.h drinsteht. Für delay gibt es
keine delay.c. Die delay-Funktion, genau genommen ein Makro, steht in
der delay.h. Die Texte von Header-Dateien werden da, wo sie inkludiert,
welch ein Wort, werden, praktisch komplett hingeschrieben und stehen
somit im Kontext dieser Datei. Deshalb wirft das delay-Makro keinen
Fehler oder eine Warnung. Die uart.c, die die Funktionen enthält, kann
das aber nicht sehen. Die kann nur in die uart.h gucken, da steht es
aber nicht drin, sondern davor. Capito?
Keine Ahnung wie "sauber" das ist, im Geschäft machen wir das einfach
so, dass wir für jedes Gerät eine "device.h" haben und beispielsweise
auch eine "typedef.h" in der wir genau solche spezifischen Sachen wie
Clock-Frequenz oder auch Typen (bei kleinen Controllern wird ein float
als float32 definiert, wenn eine Double Precision Einheit drauf ist
entsprechend als Double) definiert werden.
So kann man Bibliotheken über alle Familien hinweg nutzen.
Sef C. schrieb:> ...und der Nächste der nicht erklärt, wieso...
Das wurde dir bereits mehrfach erklärt. Der Fehler liegt also bei dir
selber, der du nicht hast zuhören wollen.
Also:
Das in die Maschinensprache zu übersetzende Zeugs (Code,Konstanten usw.)
wird normalerweise in Dateien geschrieben, die hier auf .c enden. Das
mit der Endung ist bei anderen Programmiersprachen anders. Der Zweck von
Dateien, die auf .h enden, ist üblicherweise, daß man dort all das Zeug
hineinschreibt, was andere Quellen über die auf .c endende zugehörige
Datei wissen müssen. Das wären mal ganz grob: Funktionsköpfe,
Typdefinitionen und Verweise auf Variablen und Konstanten. Man muß dabei
als Attribut das Wort 'extern' vor Variablen und Konstanten schreiben,
bei Funktionsköpfen braucht man das nicht, aber man kann das. Ich wäre
für ein generelles 'extern' in Headerdateien, dem menschlichen Verstehen
zuliebe.
Hier ein paar Beispiele:
in der Datei emil.c
1
intottokar;
2
charcharlotte(void)
3
{...
4
}
und in der zugehörigen Datei emil.h
1
externintottokar;
2
charcharlotte(void);
Ich hoffe, daß dir das nun klar geworden ist und du selber merkst, was
du bislang verkehrt gedacht hast.
W.S.
Du hast mindestens zwei *.c Dateien in deinem Projekt, also wird der gcc
mindestens zweimal aufgerufen.
> gcc -o main.o main.c
main.c definiert die benötigten Werte.
main.c inkludiert delay.h -> alles OK
main.c inkludiert uart.h -> auch OK
> gcc -o uart.o uart.c
uart.c inkludiert uart.h -> Werte fehlen
Ich hoffe jetzt macht es "Klick", sonst weiss ich nämlich auch nicht,
wie man es sonst noch erklären kann.