Forum: Mikrocontroller und Digitale Elektronik unerklärlicher Fehler - Bitte um Hilfe


von Alexander S. (knut740)


Lesenswert?

Hallo,
mich beschäftigt ein wahrscheinlich ziemlich einfacher Fehler in einem 
Arduino-Code, den ich mir nicht erklären kann.
Ich habe jedes Beiwerk weggelassen und poste nur die wichtigste Stelle:
1
// i2c_eeprom_buch_1
2
#include <Wire.h>
3
// #include <twi.h>
4
#define i2cadresse 0x57 ;     // I2C-Adresse des EEPROMS
5
                              // Achtung: wahrscheinlich darf es nicht 
6
                              // heißen eeprom 
7
                              // gibt sonst Fehlermeldung bei Serial.begin(9600)
8
void setup()
9
  {
10
        Wire.begin();        // join i2c bus (address optional for master)
11
        Serial.begin(9600);  // start serial for output
12
        unsigned int speicheradresse = 7;
13
        byte wert = 7;
14
        schreibEEPROM(i2cadresse, speicheradresse, wert);
15
        Serial.println(liesEEPROM(i2cadresse, speicheradresse) HEX);
16
  }   
17
18
void loop ()
19
  {}

Die Fehlermeldung lautet:

i2c_eeprom_buch_1.ino: In function 'void setup()':
i2c_eeprom_buch_1:13: error: expected `)' before ';' token
i2c_eeprom_buch_1:13: error: expected primary-expression before ',' 
token
i2c_eeprom_buch_1:13: error: expected `;' before ')' token
i2c_eeprom_buch_1:14: error: expected `)' before ';' token
i2c_eeprom_buch_1:14: error: expected primary-expression before ',' 
token
i2c_eeprom_buch_1:14: error: expected `;' before ')' token

Der Fehler geschieht also, wie es aussieht, in der Zeile mit
byte wert = 7;.
Der Abschluß dieser Instruktion kommt mir ganz normal vor. Ob da 
irgendwelche nicht lesbaren Sonderzeichen im Spiel sind?
Ich sollte vielleicht erwähnen, daß ich bei der Fehlersuche immer weiter 
rückwärts geschritten bin und schließlich bei der vorliegenden Version 
gelandet bin, die eine wörtliche Abschrift aus einem Buch von Erik 
Bartmann ist.

Vielen Dank schon mal
Alexander

von Roland .. (rowland)


Lesenswert?

Alexander Schmeil schrieb:
> Serial.println(liesEEPROM(i2cadresse, speicheradresse) HEX);

Beistrich fehlt.
Serial.println(liesEEPROM(i2cadresse, speicheradresse), HEX);

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

Anstelle dieses:
1
#define i2cadresse 0x57 ;

das hier:
1
#define i2cadresse 0x57

Was willst Du denn? Ist doch ganz leicht erklärbär :-)

von Alexander S. (knut740)


Lesenswert?

Danke - es hat etwas geholfen.
Ich hatte Semikolon und Komma auch schon gestrichen und wieder 
eingesetzt- mit mäßigen Erfolg
Ich weiß zwar, daß da kein Semikolon hingehört, aber die Variation 
Semikolon / kein Semikolon ist nicht überzeugend:

Fehlermeldung  m i t  Semikolon:
i2c_eeprom_buch_1:10: error: expected ',' or '...' before numeric 
constant
i2c_eeprom_buch_1:10: error: expected `)' before ';' token
i2c_eeprom_buch_1:10: error: expected unqualified-id before ',' token
i2c_eeprom_buch_1:10: error: expected unqualified-id before 'unsigned'
i2c_eeprom_buch_1:22: error: expected ',' or '...' before numeric 
constant
i2c_eeprom_buch_1:22: error: expected `)' before ';' token
i2c_eeprom_buch_1:22: error: expected unqualified-id before ',' token
i2c_eeprom_buch_1:22: error: expected unqualified-id before 'unsigned'

Fehlermeldung  o h n e  Semikolon:
i2c_eeprom_buch_1:10: error: expected ',' or '...' before numeric 
constant
i2c_eeprom_buch_1:22: error: expected ',' or '...' before numeric 
constant

Ohne Semikolon ist's natürlich besser, aber immer noch nicht lauffähig 
und (für mich)  noch unerklärlich.

Gruß
A

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

> ... ist nicht überzeugend:

Nun ja. Es geht hier nicht darum ob Du Joghurt mit Erdbeergeschmack oder 
Pfirsich bevorzugst. :-) Auch sollst nicht DU "überzeugt" werden, 
sondern der Compiler. :-)

Es gibt eindeutige Regeln, wie C-Programme geformt sein müssen. Die 
sogenannte Syntax.

Glaub' mir. Da gehört kein Semikolon hin. Und ich hoffe der Kommentar 
danach war hier nur zur Erklärung.

Der Code muss jetzt so aussehen:
1
// i2c_eeprom_buch_1
2
#include <Wire.h>
3
// #include <twi.h>
4
#define I2CADRESSE 0x57     
5
                              // I2C-Adresse des EEPROMS
6
                              // Achtung: wahrscheinlich darf es nicht 
7
                              // heißen eeprom 
8
                              // gibt sonst Fehlermeldung bei Serial.begin(9600)
9
void setup()
10
  {
11
        Wire.begin();        // join i2c bus (address optional for master)
12
        Serial.begin(9600);  // start serial for output
13
        unsigned int speicheradresse = 7;
14
        byte wert = 7;
15
        schreibEEPROM(I2CADRESSE, speicheradresse, wert);
16
        Serial.println(liesEEPROM(I2CADRESSE, speicheradresse), HEX);
17
  }   
18
19
void loop ()
20
  {}

von isnah (Gast)


Lesenswert?

Der Fehler muss nicht unbedingt in dem von dir geposteten Codeabschnitt 
liegen. Es kann auch sein, dass du weiter oben eine Klammer geöffnet, 
aber nicht wieder geschlossen hast. Oder aber du hast vorher ein 
Semikolon vergessen.

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

Zugegeben, die Fehlermeldungen sind manchmal nicht ganz einfach zu 
verstehen.
Aber das ist eine Übungssache. Fast immer ist die erste Meldung, so 
seltsam sie erscheinen mag, die relevante.

Wenn ich einmal Deinen obigen Code nehme und Präprozessor spiele dann 
kommt folgendes heraus:
1
  schreibEEPROM(i2cadresse 0x57 ;     // I2C-Adresse des EEPROMS, speicheradresse, wert);
2
  Serial.println(liesEEPROM(i2cadresse 0x57 ;     // I2C-Adresse des EEPROMS, speicheradresse) HEX);
3
  }

Du siehst wahrscheinlich selbst, dass das Semikolon und der Kommentar 
überhaupt keinen Sinn machen.

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

Ooops. Schon spät.

Es muss natürlich sein:
1
  schreibEEPROM(0x57 ;     // I2C-Adresse des EEPROMS, speicheradresse, wert);
2
  Serial.println(liesEEPROM(0x57 ;     // I2C-Adresse des EEPROMS, speicheradresse) HEX);

Ändert aber nichts daran, dass kein syntaktisch korrektes Programm ist.

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

Noch zur Erklärung:

Die Kommentarzeichen "//" bzw. "/*" und "*/" sind Elemente der 
C-Sprache. NICHT aber des Präprozessors. In der Präprozessorsprache gibt 
es keine Kommentare.

Die Syntax-Definition des Präprozessor-Befehls "#define" in der 
verwendeten Form (ohne Parameter) ist:

"#define" <identifier> <token-sequence>

Die Bedeutung ist folgende:
"Ersetze im folgenden Programmtext jedes Auftreten von <identifier> 
durch die <token-sequence>
Wobei die <token-sequence> (abgesehen von einem Detail in Bezug auf 
Leerzeichen) die Zeichen sind die nach <identifier> folgen. Egal, was 
das für Zeichen sind!

Lies mal in einem guten C-Buch nach! Das ist sehr wichtig!

von PittyJ (Gast)


Lesenswert?

lass die #defines einfach weg. Je weniger, desto besser.

nimmt ein
const int i2cadresse= 0x57 ;

Dann gibt es keine bizarren Textersetzungen, die Anfänger überfordern.
Und der Compiler sollte den gleichen Code erzeugen.

von Mitleser (Gast)


Lesenswert?

deine Deklarationen der Variablen dürfen bei einem C-Compiler nicht 
mitten in der Funktion stehen, sondern immer am Anfang. Nur bei C++ ist 
dies erlaubt.
Daher kann es durchaus sein, dass der abgeschriebene Code bei dem Autor 
funktioniert, wenn dieser ein C++ Compiler verwendet, bei dir geht das 
aber in die Hose wenn du einen C Compiler verwendest.
1
void setup()
2
  {
3
        unsigned int speicheradresse;
4
        byte wert;
5
6
        Wire.begin();        // join i2c bus (address optional for master)
7
        Serial.begin(9600);  // start serial for output
8
        speicheradresse = 7;
9
        wert = 7;
10
        schreibEEPROM(i2cadresse, speicheradresse, wert);
11
        Serial.println(liesEEPROM(i2cadresse, speicheradresse) HEX);
12
  }

von Seano L. (Gast)


Lesenswert?

ConvertsQuestionsToAnswers schrieb:
> Die Kommentarzeichen "//" bzw. "/*" und "*/" sind Elemente der
> C-Sprache. NICHT aber des Präprozessors. In der Präprozessorsprache gibt
> es keine Kommentare.
Das war vor 100 Jahren mal ein Problem, alle heutigen Compiler haben 
damit keine Probleme, iirc ist das mitlerweile sogar Standardkonform, 
das C-Comment // machte noch nie Probleme, das C++ Comment /* */ 
vielleicht noch bei Asbachuraltcompilern.

von Seano L. (Gast)


Lesenswert?

Mitleser schrieb:
> deine Deklarationen der Variablen dürfen bei einem C-Compiler nicht
> mitten in der Funktion stehen, sondern immer am Anfang. Nur bei C++ ist
> dies erlaubt.
Für C99 gilt das nicht mehr, da kannste wie in C++ deklarieren wo du 
willst.
Zudem war das bei C89 auch kein Problem, man hat einfach einen neuen 
Scope mit einem neuen Block erzeugt, nat. musste man aufpassen wegen der 
Sichtbarkeit, i.d.R sind das eh meistens Hilfsvariablen innerhalb von 
Blöcken von if else ...
Der Übersichtlichkeit wegen deklariert man seine Variablen trozdem am 
Anfang einer Funktion, ausser vielleicht Zählvaribalen für for-schleifen 
wenn man sie sonst nicht mehr braucht.

von PittyJ (Gast)


Lesenswert?

Mitleser schrieb:
> deine Deklarationen der Variablen dürfen bei einem C-Compiler
> nicht
> mitten in der Funktion stehen, sondern immer am Anfang. Nur bei C++ ist
> dies erlaubt.

Es ging hier um Arduino. Dahinter steht ein C++ Compiler. Sollte also 
kein Problem sein.

von ConvertsQuestionsToAnswers (Gast)


Lesenswert?

@  Schwen Gel (sean_l)

> ... ist das mitlerweile sogar Standardkonform,

Ja richtig. Ich vergaß das.
An sich sollten nach C99 Kommentare durch ein Whitespace ersetzt werden, 
bevor die Ersetzung erfolgt. Allerdings haben viele C-Compiler das 
nicht richtig implementiert, so daß ich mir das wieder abgewöhnt habe. 
Formal hast Du recht.

Jedoch: // ist der C++-Kommentar und /* */ der C-Kommentar. :-)

Letztlich sollte man bei Problemen, bei denen der Präprozessor beteiligt 
sein könnte, die Präprozessor-Ausgabe anschauen.

von Alexander S. (knut740)


Lesenswert?

isnah schrieb:
> Der Fehler muss nicht unbedingt in dem von dir geposteten Codeabschnitt
> liegen. Es kann auch sein, dass du weiter oben eine Klammer geöffnet,
> aber nicht wieder geschlossen hast. Oder aber du hast vorher ein
> Semikolon vergessen.

Das hatte ich auch immer gemeint. Mein Programmschnipsel ist der oberste 
Teil, darüber gibt es nichts mehr, es kann also nicht die sattsam 
bekannten Probleme mit weiter oben vergessenen Kommata oder Klammern 
geben.

ABER: Was mich sehr wundert ist, folgendes: Ich habe die Version von 
ConvertsQuestionsToAnswers in ein neues Blatt kopiert und es dem 
Compiler ausgesetzt, der erwartungsgemäß nicht zu maulen fand.
Dann habe ich unten einige angefangene Instruktionen zugefügt und prompt 
kam die Fehlermeldung wieder.

Kommt mir sehr merkwürdig vor.

Programmschnipsel (erweiterte Version von ConvertsQuestionsToAnswers):
1
// i2c_eeprom_forum
2
#include <Wire.h>
3
// #include <twi.h>
4
#define I2CADRESSE 0x57           // wird beanstandet, wenn liesEEPROM... nicht auskommentiert ist
5
//const int I2CADRESSE = 0x57;    // läßt sich unbeanstandet kompilieren
6
                             
7
void setup()
8
  {
9
        Wire.begin();        // join i2c bus (address optional for master)
10
        Serial.begin(9600);  // start serial for output
11
        unsigned int speicheradresse = 7;
12
        byte wert = 7;
13
//        schreibEEPROM(I2CADRESSE, speicheradresse, wert);
14
//       Serial.println(liesEEPROM(I2CADRESSE, speicheradresse), HEX);
15
  }   
16
17
void loop ()
18
  {}
19
  
20
   
21
 byte liesEEPROM(int I2CADRESSE, unsigned int speicheradresse)   // byte datenbyte=0xFF)
22
  {
23
  Wire.beginTransmission(I2CADRESSE);
24
 }
25
26
//void schreibEEPROM(int I2CADRESSE, unsigned int speicheradresse, byte wert)
27
//{}

Die Fehlermeldung:
i2c_eeprom_forum:10: error: expected ',' or '...' before numeric 
constant
i2c_eeprom_forum:21: error: expected ',' or '...' before numeric 
constant


Ich weiß, der Compiler hat immer recht, deshalb werde ich nach dem 
Vorschlag von PittyJ verfahren. Verstehen würde ich aber trotzdem gern, 
was da schief läuft.

Gruß
Alexander
Ich werde

: Bearbeitet durch User
von Dumdi D. (dumdidum)


Lesenswert?

Alexander Schmeil schrieb:
> byte liesEEPROM(int I2CADRESSE, unsigned int speicheradresse)   //

Das sollte nicht gehen. Überleg Dir mal was '#define' macht: er ersetzt 
den Text. Und was sollte

byte liesEEPROM(int 0x57, unsigned int speicheradresse)

dann bedeuten?

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.