Forum: Mikrocontroller und Digitale Elektronik seltsames i2c verhalten


von Richard (Gast)


Lesenswert?

Hallo

bin gerade auf einen seltsamen Fehler gestoßen den ich mir nicht ganz 
erklären kann:

bei meinem projekt muss ich über i2c die temperatur auslesen.
Bauteile:
Atmega8
TMP75

programmiere in C auf linux mit avr-gcc (brennen mit avrdude)

nun zum seltsamen (dieser Code liefert immer "i2c: nein" also kein 
acknowledge),..:
1
  lcd_clear();
2
  if(i2c_start(adr+I2C_READ))  //Temperatur-Sensor check
3
    lcd_string("i2c: nein");
4
  else
5
    lcd_string("i2c: yeah");
6
  i2c_stop();
wenn ich den return wert allerdings zwischenspeicher funktioniert das 
acknowledge (bekomme "i2c: yeah" ausgegeben):
1
  unsigned char temp;
2
  lcd_clear();
3
  temp=i2c_start(adr+I2C_READ); 
4
  if(temp)      //Temperatur-Sensor check
5
    lcd_string("i2c: nein");
6
  else
7
    lcd_string("i2c: yeah");
8
  i2c_stop();
nur soviel voraus: ich habe ein Oszilloskop dran hängen und es ist in 
beiden fällen ein acknowledge vorhanden.

laut meinen wissen sollten die beiden code varianten keinen unterschied 
machen, hat jemand eine idee?
vielen dank...

ps: zur vollständigkeit, der i2c_start() code:
1
//  return 0 = device accessible, 1= failed to access device
2
unsigned char i2c_start(unsigned char address)
3
{
4
    uint8_t   twst;
5
    // send START condition
6
    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
7
    // wait until transmission completed
8
    while(!(TWCR & (1<<TWINT)));
9
    // check value of TWI Status Register. Mask prescaler bits.
10
    twst = TW_STATUS & 0xF8;
11
    if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
12
    // send device address
13
    TWDR = address;
14
    TWCR = (1<<TWINT) | (1<<TWEN);
15
    // wail until transmission completed and ACK/NACK has been received
16
    while(!(TWCR & (1<<TWINT)));
17
    // check value of TWI Status Register. Mask prescaler bits.
18
    twst = TW_STATUS & 0xF8;
19
    if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
20
    return 0;
21
}

von Karl H. (kbuchegg)


Lesenswert?

Richard schrieb:

> programmiere in C auf linux mit avr-gcc (brennen mit avrdude)
>
> nun zum seltsamen (dieser Code liefert immer "i2c: nein" also kein
> acknowledge),..:

Kann es sein, dass du vergessen hast das Header File zu inkludieren, in 
welchem der Prototyp der Funktion steht?
(Bzw. das der Prototyp nicht mit der tatsächlichen Funktion 
übereinstimmt, bzw. das es überhaupt keinen Prototyp gibt)



> laut meinen wissen sollten die beiden code varianten keinen unterschied
> machen

eigentlich: ja

Wenn es sich nicht um einen Compilerfehler handelt (was ich bis zum 
Beweis des Gegenteils mal ausschliesse), dann ist das Problem irgendwo 
im 'Umfeld' zu suchen. Vergessenes Header File wäre eine Möglichkeit. 
Denn dann muss der Compiler annehmen, dass die Funktion einen int 
retourniert. Was sie aber nicht tut. Die Funktion liefert nur 1 Byte, 
der Compiler geht aber an der Aufrufstelle von 2 Bytes aus. Und was im 
2-ten Byte steht, ist dann zufällig. In Summe ergibt das aber so gut wie 
nie 0 (zumindest sind die Chancen gering).
Machst du die Abfrage direkt im if, wertet das if beide Bytes aus. Weist 
du vorher an einen unsigned char zu, wird das fälschliche Byte (durch 
die Byte Order) wieder weggestrippt und es bleibt tatsächlich das übrig, 
was die Funktion returniert hat.



Daher auch die Frage:
Hast du Warnungen beim Compilieren?

von cortexm3 (Gast)


Lesenswert?

Hallo,

Also eine LCD Ausgabe dauert zeitlich her immer sehr lang überhaupt wenn 
es eine mit hd44780 Chip is wegen ganzen delays usw.
Ich würde meinen das du lieber die returnwerte buffern solltest und die 
i2c Prozedur in einem durchlaufen lässt ohne dazwischen noch 
debugmessages auszugeben!
Mfg betrunken!

von Richard (Gast)


Lesenswert?

volltreffer,....

vielen dank, das war's tatsächlich, verwende noch keine header datei und 
habe den prototypen in der main.c datei nicht definiert gehabt (nur in 
twi.c),deshalb auch keine fehlermeldung.
vielen dank für die schnelle antwort, wieder was gelernt!

lg richard

von Karl H. (kbuchegg)


Lesenswert?

Richard schrieb:
> volltreffer,....
>
> vielen dank, das war's tatsächlich, verwende noch keine header datei und
> habe den prototypen in der main.c datei nicht definiert gehabt (nur in
> twi.c),deshalb auch keine fehlermeldung.

Doch.
Eigentlich hätte das eine Warnung geben sollen (keinen Error, soweit ist 
das richtig). Wenn du diese Warnung nicht gekriegt hast, dann dreh, IN 
DEINEM EIGENEN INTERESSE, den Warning-Level hoch!

Warnungen sind manchmal harmlos. Oft aber sind sie tatsächlich vital und 
der Compiler trifft mit seiner Warnung voll ins Schwarze. Im 
industriellen Umfeld gilt oft die Devise: Code MUSS mit dem höchsten 
Warning-Level (oder einer Stufe zuvor) völlig ohne Warnungen 
kompilieren. Sonst wird er nicht abgenommen.
Und das kann bei einem Compiler-Upgrade dann schon mal in Arbeit 
ausarten :-)

von Karl H. (kbuchegg)


Lesenswert?

> verwende noch keine header datei

Warum nicht?
So ein Header File ist doch schnell gemacht.
Im C-File die Zeile mit dem Funktionskopf ins Clipboard kopieren, 
welchseln zum Header File, einfügen, Strichpunkt dahinter.
Nächste Funktion. Copy - Paste - ;
Nächste Funktion. Copy - Paste - ;
etc. etc.

Ist eine Sache auf wenige Sekunden.

Jetzt hast du ja gesehen, was da alles passieren kann, wenn man keine 
Protoypen hat und die Default Regeln, die der Compiler answendet, nicht 
kennt  :-). Denn wenn du i2c_start als int-Funktion gemacht hättest
int i2c_start(int address)
wär gar nichts passiert, weil sich das mit den Default-Annahmen des 
Compilers deckt.

von Karl H. (kbuchegg)


Lesenswert?

Das Header File IMMER auch ins C-File inkludieren, in dem die bewussten 
Funktionen stehen! Das ermöglicht dem Compiler die Kontrolle, ob 
Prototyp und Implementierung übereinstimmen.

von Richard (Gast)


Lesenswert?

> Wenn du diese Warnung nicht gekriegt hast, dann dreh, IN
> DEINEM EIGENEN INTERESSE, den Warning-Level hoch!

super danke, habe das voll vergessen,... habe ich gerade "aktiviert"

>> verwende noch keine header datei

>Warum nicht?
>So ein Header File ist doch schnell gemacht

war nur ein ganz schneller test (ich weiß ist kaum arbeit), habe gerade 
eine headerdatei erstellt.

> Das Header File IMMER auch ins C-File inkludieren, in dem die bewussten
> Funktionen stehen! Das ermöglicht dem Compiler die Kontrolle, ob
> Prototyp und Implementierung übereinstimmen.

mach ich

ok vielen dank karl,
warst mir ein große hilfe,...

lg richard

von Karl H. (kbuchegg)


Lesenswert?

Richard schrieb:


>>So ein Header File ist doch schnell gemacht
>
> war nur ein ganz schneller test

:-)
Du hast sicher schon mal den Ausdruck gehört "berühmte letzte Worte"

Ja ich weiß.
Da muss jeder ein paar mal auf die Schnauze fallen bis er einsieht, dass 
es sich in Summe zeitmässig nicht lohnt, solche 'Krücken', und sei es 
nur zu Testzwecken, zu akzeptieren. Die eine Fehlersuche bringt die 
Zeit-Einsparbilanz komplett zum Kippen.
:-)

Been there, done that.
Just like millions of other programmers before.

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.