ich beschäftige mich im moment mit funktionen in c. nun wollte ich das
auch mal ausprobieren und wenn ich dieses programm dann kompiliere,
kommt immer folgender fehler:
C:\Users\Benedikt\Documents\default/../test2.c:15: undefined reference
to `funktion'
make: *** [test2.elf] Error 1
Build failed with 1 errors and 0 warnings...
zeile 15 ist da wo die funktion mit dem namen "funktion" aufgerufen
wird.
1
#include<avr/io.h>
2
3
voidfunktion();
4
5
intmain(void)
6
{
7
8
while(1)
9
{
10
11
DDRD=0xff;
12
13
PORTD=0xff;
14
15
funktion();
16
17
PORTD=0x00;
18
}
19
20
voidfunktion()
21
{
22
PORTD&=~(1<<PA0);
23
}
24
25
}
was mache ich da falsch?
wo liegt hier der fehler?
Hallo pille1990,
wenn Du Prototyping machst, muss die entsprechende Funktion im gleichen
Gültigkeitsbereich liegen, d.h. außerhalb von main().
Wenn Du funktion() vor main() einfügst, brauchts Du nicht einmal das
Prototyping.
Außerdem würde ich void funktion(void) schreiben. Ahnliches gilt für int
main(void). Hier fehlt der Rückgabewert oder Du schreibst void main
(void).
Mit diesem Hinweisen kannst Du das Programm fehlerfrei übersetzen.
Wobei ich aber den Sinn des Programms nicht sehen kann.
PS: Falls Du den Port D immer als Ausgang nutzen möchtest, genügt es die
Datenrichtungsbits einmal vor der Hauptschleife zu beschreiben.
PPS: Wie lange bleibt Port D 0xff bzw. 0x00?
cu
Georg
das programm war einfach nur zum testen wie das mit den funktionen
funktioniert....
jetzt habe ich aber ein sinnvolleres programm geschrieben...bei dem ich
aber schon wieder ein problem habe.
ich will einen zähler realisieren, der die tastendrücke eines tasters
zählt und diese dann auf einem port ausgibt.
dazu frage ich einfach den taster ab
1
#include<avr/io.h>
2
3
#define TASTER PC0
4
#define EINGANG PINC
5
#define AUSGANG PORTD
6
7
voidpress()
8
{
9
10
while(!EINGANG&(1<<TASTER));//solange in der while schleife laufen, bis der taster gedrückt ist
11
i++;
12
AUSGANG=i;
13
}
14
15
voidrelease()
16
{
17
while(EINGANG&(1<<TASTER));//solange in der while schleife laufen, bis der taster wieder losgelassen wird
18
}
19
20
voidmain(void)
21
{
22
DDRC=0x00;
23
DDRD=0xff;
24
25
26
27
while(1)
28
{
29
30
inti;
31
i=0;
32
33
press();
34
35
release();
36
}
37
38
}
nun zum problem:
da ich ja die variable "i" in der main funktion deklariert habe, ist sie
in der press funktion nicht verfügbar.
ich will aber nun, dass die variable auch in der press funktion
verfügbar ist ohne dort die folgenden programmzeilen zu schreiben:
1
inti;
2
i=0;
da gibt es doch für die funktionen diese parameter...aber irgendwie
verstehe ich nicht wie man diese hier einsetzt.
noch eine frage:
warum bekomme ich vom compiler einen fehler wenn ich die funktion
"press" und "release" nach der main funktion deklariere?
pille1990 wrote:
> nun zum problem:> da ich ja die variable "i" in der main funktion deklariert habe, ist sie> in der press funktion nicht verfügbar.> ich will aber nun, dass die variable auch in der press funktion> verfügbar ist ohne dort die folgenden programmzeilen zu schreiben:
Stichwort: Globale Variable. Dazu schreibst du das int i = 0; einfach
außerhalb der Funktionen, sinnvollerweise über die erste Funktion und
unter die includes. Dort findet man globale definitionen am einfachsten
wieder. Irgendwo im AVR Tutorial werden globale Variablen sicherlich
erklärt.
Edit (Der Ordnung halber): Mit Übergabewerten (Parametern) an Funktionen
hat das nichts zu tun.
> noch eine frage:> warum bekomme ich vom compiler einen fehler wenn ich die funktion> "press" und "release" nach der main funktion deklariere?
Weil: Dein compiler geht das von oben nach unten durch. Wenn er in einer
funktion, bei dir die main, einen aufruf sieht, den er noch nicht kennt
(weil eben weiter unten definiert), macht er n warning, weil er den
aufruf nicht kennt. Ausführen lässt sich das ganze trotzdem, weil der
Compiler wahrscheinlich mehrere durchgänge macht (zwecks optimierung),
daher auch nur eine Warning und kein Error. Er möchte dich quasi sanft
darauf hinweisen, dass dein Programmierstil da noch Nachbesserung
vertragen könnte :) Daher also: Wenn du aufrufe machst auf funktionen,
die später erst definiert werden, macht man oben (unter includes, über
die erste funktion) einen Prototyp der noch kommenden funktionen. In
deinem Fall: void press (void);
while(!EINGANG&(1<<TASTER));//solange in der while schleife laufen, bis der taster gedrückt ist
9
i++;
10
AUSGANG=i;
11
}
12
13
...
14
15
voidmain(void)
16
{
17
DDRC=0x00;
18
DDRD=0xff;
19
20
while(1)
21
{
22
23
inti;
24
i=0;
25
26
press(i);
27
release();
28
}
29
30
}
Funktioniern wird das aber auch nicht, da bei jedem Durchlauf der
while-Schleife i auf 0 gesetze wird. D.h. für i gilt das selbe wie für
DDRD,
1
#include<avr/io.h>
2
3
...
4
5
voidmain(void)
6
{
7
inti;
8
i=0;
9
10
DDRC=0x00;
11
DDRD=0xff;
12
13
while(1)
14
{
15
16
press(i);
17
release();
18
}
19
20
}
Du wirst aber Probleme bekommen weil der Ausgabeport 8 Bit "breit" ist,
du aber einen 16 Bit Integer zuweist.
Um solche Knackpunkte zu vermeiden werden in der stdint.h die Datentypen
mit der Bitbreite definiert:
typedef signed char int8_t
typedef unsigned char uint8_t
typedef signed int int16_t
typedef unsigned int uint16_t
typedef signed long int int32_t
typedef unsigned long int uint32_t
typedef signed long long int int64_t
typedef unsigned long long int uint64_t
Wenn Du i als uint8_t deklarierst, läufst Du hier nicht in ein
Überlaufproblem hinein.
cu
Georg
@Sven,
stimmt. Achse auf mein Haupt.
Das kommt davon, wenn man Tips nicht ausprobiert.
Beim Compilieren kommt ja auch eine entsprechende Warnung.
Somit sollte es dann heißen int main (void) und am Ende nach der while
Schleife noch ein return (0) z.B.
cu
Georg
Georg Werner wrote:
> @Sven,>> stimmt. Achse auf mein Haupt.
Aber ne schwere Achse, damit es richtig weh tut ;-)
> Somit sollte es dann heißen int main (void) und am Ende nach der while> Schleife noch ein return (0) z.B.
Erstens ist das return am Ende überflüssig, da main, wenn es auf einem
µC ohne OS läuft, nirgendwohin etwas zurückgeben kann. Zweitens steht
das return hinter einer Endlosschleife und wird sowieso nie erreicht
(weshalb manch ein Compiler dabei sogar eine Warnung ausspuckt, dass da
Code steht, der nie erreicht wird). Drittens ist return keine
Funktion, was ein Grund dafür ist, dass sein Argument nicht in
Klammern eingeschlossen wird. OK, es funktioniert auch mit Klammern,
aber die korrekte Schreibweise ist einfach "return ausdruck;"
Johannes M. wrote:
> Erstens ist das return am Ende überflüssig, da main, wenn es auf einem> µC ohne OS läuft, nirgendwohin etwas zurückgeben kann. Zweitens steht> das return hinter einer Endlosschleife und wird sowieso nie erreicht> (weshalb manch ein Compiler dabei sogar eine Warnung ausspuckt, dass da> Code steht, der nie erreicht wird). Drittens ist return keine> Funktion, was ein Grund dafür ist, dass sein Argument nicht in> Klammern eingeschlossen wird. OK, es funktioniert auch mit Klammern,> aber die korrekte Schreibweise ist einfach "return ausdruck;"
und viertens ist main die grosse Ausnahme.
Auch wenn main einen Returntyp von int hat, ist es zulässig das return
am Ende wegzulassen. Der Compiler muss sich selbst ein
return 0;
dazudenken