Forum: Compiler & IDEs IR-Audiomultiplexer Code Error (AVR, C-Code)


von Kai Block (Gast)


Angehängte Dateien:

Lesenswert?

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

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

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

von Kai Block (Gast)


Lesenswert?

Hallo Frank,

danke für deine Antwort.
Leider ist das Ergebnis unverändert.
Dieselben Fehler tauchen wieder auf.

Gruß
Kai

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Welchen Prozessor hast Du im Studio festgelegt?

Gruß
Frank

von Kai Block (Gast)


Lesenswert?

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

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Das passt... ich schaue mir das gleich mal am Notebook an und melde mich

Gruß
Frank

von Frank L. (Firma: Flk Consulting UG) (flk)


Angehängte Dateien:

Lesenswert?

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

von Kai Block (Gast)


Lesenswert?

Super!
Jetzt kann ich in die Testphase gehen.
Vielen vielen Dank :)

Gruß Kai

von Frank L. (Firma: Flk Consulting UG) (flk)


Lesenswert?

Nicht für.

Viel Spaß!

Gruß
Frank

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Kai Block (Gast)


Lesenswert?

Danke für den Tipp!
Werde ich machen.
Wusste gar nicht, dass man die nicht braucht.

Gruß
Kai

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Kai Block (Gast)


Lesenswert?

> 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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Kai Block (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.