Hallo liebe AVR-Community, ich arbeite derzeit an einem Projekt, bei dem ich per verschiedener Infrarotsignale zwischen Audioquellen umschalten möchte (Erweiterungen zu einem späteren Zeitpunkt). Nun habe ich mir einen Attiny44 sowie einen USBasp Programmer zugelegt und auch schon erste Testprogramme darauf laufen lassen. Programmiert habe ich mit dem Atmel Studio 7 und mit AVR-Brenner dann die .hex geflasht. Zur Funktion: Ich möchte von vorerst 3 verschiedenen Fernbedienungen die Power-On Signale empfangen und an einen Audio-Multiplexer (per Anlegen eines BCD-Codes) auf die entsprechende Audioquelle umschalten. Ausgelesen habe ich die IR-Signale bereits über die Soundkarte (mittels IR-Empfänger). Diesen habe ich nun an den Pin für INT0 angelötet und möchte nun per externem Interrupt die Zeiten der high's bzw. low's mit dem Timer0 zählen und mit den ausgelesenen IR-Codes vergleichen (und ggf. umschalten). Jedoch scheitere ich im Moment noch am erfolgreichen Build. Folgende Fehler und Warnungen treten auf: - main is normally a non-static function [-Wmain] (warning) - expected declaration or statement at end of input (error) - previous declaration of '_vector_1'was here (message) - recipe for target main.o failed (error) - static declaration of '_vector_1' follows non-static declaration (error) Nachdem ich nun schon mehrfach den kompletten Code auf fehlende } Klammern untersucht habe und ich auch keine Erklärung für das Rot-Unterstreichen von manchen Funktionen aus meiner .h Datei habe, möchte ich mich nun an euch wenden und um Rat fragen. Es wäre super, wenn ihr mir weiterhelfen könntet. Vielen Dank schon mal im Voraus für die Mühe! Grüße Kai
Hallo, Schmeiß zuerst mal die Zeile raus #include "C:\Program Files (x86)\ Dann einer neuer Biuld. Wenn dann noch Fehler auftreten bitte posten. Gruß Frank
Hallo Frank, danke für deine Antwort. Leider ist das Ergebnis unverändert. Dieselben Fehler tauchen wieder auf. Gruß Kai
Welchen Prozessor hast Du im Studio festgelegt? Gruß Frank
Unter Device habe ich den Attiny44 ausgewählt, falls du das meinst. Ansonsten müsstest du mir erklären wo ich das nachschauen kann. Gruß Kai
Das passt... ich schaue mir das gleich mal am Notebook an und melde mich Gruß Frank
Okay, Drei Fehler gefunden. 1. Der Name des Interruptvektors passt nicht. 2. Abschließende Klammer bei channel vergessen 3. //enum {off=0, mute=0, stop=0, run=1, on=2}; entfernt und stop im enum systemstatus{on, off, stop}; ergänzt. Jetzt compliert das Ganze. Ob das jetzt gut oder schlecht war, musst Du selber beurteilen. Dann habe ich noch alle Funktionen aus dem Header entfernt. Funktionen haben nichts im Header verloren. Wenn Du sie wiederverwenden willst pack sie in eine eigene c Datei mit einem passenden Header File. Gruß Frank
Super! Jetzt kann ich in die Testphase gehen. Vielen vielen Dank :) Gruß Kai
Du solltest Dir die total überflüssigen geschweiften Klammern in all' Deinen switch/case-Statements schleunigst abgewöhnen. Die waren auch schon die Ursache für Deinen ersten Fehler.
Danke für den Tipp! Werde ich machen. Wusste gar nicht, dass man die nicht braucht. Gruß Kai
Kai Block schrieb: > Wusste gar nicht, dass man die nicht braucht. Nun, genau ein Paar braucht man:
1 | switch (bla) |
2 | { // <--- diese Klammer ist zwingend nötig |
3 | case 1: |
4 | machwas(); |
5 | break; |
6 | |
7 | case 2: |
8 | lasswas(); |
9 | // hier habe ich eine kleine Spezialität untergebracht
|
10 | case 3: |
11 | case 4: // und hier eine andere |
12 | wasdenn(); |
13 | break; |
14 | } // <--- und diese Klammer ist auch zwingend nötig |
Es kann natürlich auch einen Sinn haben, einen neuen Block anzufangen, wenn man vorübergehend Variablen benötigt, die nur innerhalb dieses Blocks von Bedeutung sind:
1 | switch (bla) |
2 | {
|
3 | case 1: |
4 | {
|
5 | int i; |
6 | for (i = 0; i < 36; i++) |
7 | machwas(i); |
8 | }
|
9 | break; |
10 | |
11 | etc. |
Der nächste Punkt, an dem Du arbeiten solltest: Deine irfunctions.h enthält nicht die Deklarationen, sondern die Definitionen der Funktionen, d.h. den Code selbst. Das ist Murks; wenn Du in einem Projekt diese Datei an zwei verschiedenen Stellen per #include einbindest, wird der enthaltene Code zweimal in Dein Programm eingebunden, was mindestens zu einer Linkerfehlermeldung führt. Verlagere die Funktionen in eine Datei namens irfunctions.c und lass' in der irfunctions.h nur die Funktionsdeklarationen, d.h. die Prototypen drin. Und lerne, wie Du Deinem Entwicklungssystem beibringst, ein Programm aus mehreren *.c-Dateien zu generieren.
> switch (bla) > { // <--- diese Klammer ist zwingend nötig > case 1: > machwas(); > break; > > case 2: > lasswas(); > // hier habe ich eine kleine Spezialität untergebracht > case 3: > case 4: // und hier eine andere > wasdenn(); > break; > } // <--- und diese Klammer ist auch zwingend nötig > Ja, logisch die braucht man, sonst weiß man ja nicht wann die switch-Fkt endet. Die 1. Spezialität: bedeutet das, dass ich kein "break;" anhängen muss, sobald ich eine Leerzeile lasse? :-O Die 2. Spezialität lässt mich für case 3 und 4 die gleichen Anweisungen durchführen, sehe ich das richtig? > switch (bla) > { > case 1: > { > int i; > for (i = 0; i < 36; i++) > machwas(i); > } > break; > > etc. In diesem Beispiel würde ich die Klammern prinzipiell nicht benötigen, da die switch-Fkt danach ohnehin beendet wäre, oder? Rufus Τ. F. schrieb: > Und lerne, wie Du Deinem Entwicklungssystem beibringst, ein Programm aus > mehreren *.c-Dateien zu generieren. Ja, das hatte Frank bereits erwähnt, ich weiß auch nicht warum ich das einfach vergessen habe... Angenommen ich hätte mehrere *.h und *.c files, habe ich es so gelernt, dass ich dann eine weitere all_h.h file mache, in die ich alle *.h include und in jede *.c das entsprechende *.h file mit den Funktionsdeklarationen. In mein main.c file würde ich dann nur die all_h.h includen. Ist dieses Vorgehen richtig? Und falls ja, woher weiß die main.c dann wie die Funktionen funktionieren, wenn die zugehörigen *.c files gar nicht includiert sind, sondern nur deren header? Danke fürs daraufhinweisen! Gruß Kai
Kai Block schrieb: > Die 1. Spezialität: bedeutet das, dass ich kein "break;" anhängen muss, > sobald ich eine Leerzeile lasse? :-O O nein. Das nennt sich "fall-through" (man könnte es wenig poetisch mit "Durchfall" übersetzen) und bedeutet, daß auf "lasswas()" die Ausführung von "wasdenn()" folgt. Sieh Dir mal das hier an:
1 | int i = 0; |
2 | |
3 | switch (x) |
4 | {
|
5 | case 0 : |
6 | i++; |
7 | case 1 : |
8 | i++; |
9 | case 2 : |
10 | i++; |
11 | case 3 : |
12 | i++; |
13 | case 4 : |
14 | i++; |
15 | }
|
Welchen Wert hat i, wenn x 0 ist? > Die 2. Spezialität lässt mich für case 3 und 4 die gleichen Anweisungen > durchführen, sehe ich das richtig? Genau. Das ist ein Sonderfall des "fall-through". > In diesem Beispiel würde ich die Klammern prinzipiell nicht benötigen, > da die switch-Fkt danach ohnehin beendet wäre, oder? Nun, Du könntest in einem anderen case-Zweig ebenfalls ein "i" verwenden, das aber beispielsweise einen anderen Typ hat, oder außerhalb des switch/case gibt es schon ein "i", das aber nicht verändert werden soll. Dann kann es einen Sinn haben, in einem Block {} eine temporäre Variable zu verwenden. > habe ich es so gelernt, dass ich dann eine weitere all_h.h file mache, > in die ich alle *.h include Nein, das ist wenig sinnvoll. Du musst in die jeweiligen *.c-Dateien nur die *.h-Dateien einbinden, die Dinge beschreiben, die Du in der *.c-Datei auch tatsächlich nutzt. Angenommen, Du hast eine *.c-Datei, in der keine der Funktionen aufgerufen wird, die in Deiner "irfunctions.h" deklariert wird. Dann gibt es auch keinen Grund, in dieser *.c-Datei die "irfunctions.h" einzubinden. > Und falls ja, woher weiß die main.c dann wie die Funktionen > funktionieren, wenn die zugehörigen *.c files gar nicht includiert sind, > sondern nur deren header? Die main.c muss das nicht wissen. Zum Übersetzen muss der Compiler nur wissen, welche Argumente die Funktionen benötigen und was sie zurückgeben. Um den Rest kümmert sich der Linker, der packt die einzeln übersetzten *.c-Dateien zu einem lauffähigen Programm zusammen.
> int i = 0; > > switch (x) > { > case 0 : > i++; > case 1 : > i++; > case 2 : > i++; > case 3 : > i++; > case 4 : > i++; > } i wäre für den case 0 Fall am Ende der switch-Fkt 5. "fall-through" ist mir damit dann auch klar; echt eine clevere Sache. Und mit dem Linker macht jetzt auch das Includieren Sinn. Zu den *.h und *.c: So meinte ich es auch (h1 in c1, h2 in c2 und h1,h2,h3 in c3 wenn dort alle Funktionen verwendet werden. Die all_h.h kann man sich dann auch sparen, wenn man in main.c alle (h1,h2,h3) header includiert. (Fand ich zur Übersichtlichkeit nur ganz gut, wenn man noch für die main.c die Standard-Libs etc. einbindet und dann noch Definitionen hat. Dann hat man das auch alles gesammelt in einer *.h und die jeweiligen h1,h2,h3 enthalten dann ausschließlich die Funktionsdeklarationen für die entsprechenden *.c files.) Danke dir! Gruß Kai
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.