Forum: Mikrocontroller und Digitale Elektronik Sehr sehr komisches Verhalten.


von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

ich habe folgendes Problem, ich habe ein Programm für einen RTC 
geschrieben, alles hat funktioniert. Dann habe ich an einem Tag die 
ganzen Verbindungen herausgenommen und alles mit nach Hause genommen und 
zu Hause wieder aufgebaut und aufeinmal ging nichts mehr. Seitdem geht 
gar nichts mehr.

Ich habe:
*) mit anderem STK500 getestet
*) mit anderem atmega32 getestet
*) mit anderem RTC getestet
*) mit anderen Widerständen getestet
*) mit anderen Quarz getestet
*) mit anderem Steckboard getestet
*) mit anderen Drahtverbindungen getestet


Das Programm lief schon einmal und ich hätte auch keine Ahnung wo da 
drinnen ein Fehler liegen sollte. Den Sourcecode habe ich samt 
Beschaltungsplan angehängt. (im Beschaltungsplan ist ein kleiner Fehler, 
Chip Select von Messchip und SD-Karte gehören getrennt, aber das ist ja 
ersteinmal egal. Die Schaltung ist genau so wie im Schaltplan aufgebaut, 
Vcc greife ich allerdings von STK500 ab.

Wenn ich das Programm starte, bleibe ich immer in der Funktion: 
I2C_get_time() hängen. (genauer gesagt ruft get_time die Funtkion 
I2C_get() auf und bleibt dort in der While schleife hängen, da nie TWINT 
gesetzt wird.)
Ich habe auch schon mit einem Oszilloskop an SCL und SDA gemessen, der 
atmega sendet schon seine Signale...

Hat irgendjemand noch eine Idee, was daran schuld sein kann bzw. wie ich 
den Fehler eingrenzen kann? Ich bin wirklich am Ende von meinem Latein!

von FloriJ (Gast)


Lesenswert?

Wenns kein .rar wär sondern z.B. .zip hätte ich mal draufgeschaut......

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hier nochmal als zip!
RTC ist übrigens ein CS5463

Würdest mir echt einen rießend Gefallen machen!

von Skua (Gast)


Lesenswert?

>Ich habe:
>*) mit anderem STK500 getestet
>*) mit anderem atmega32 getestet
>*) mit anderem RTC getestet
>*) mit anderen Widerständen getestet
>*) mit anderen Quarz getestet
>*) mit anderem Steckboard getestet
>*) mit anderen Drahtverbindungen getestet

Aber anderer PC mit evtl. anderen Einstellungen.

von Michael (Gast)


Lesenswert?

Haben es natürlich auch mit 2 Laptops ausprobiert. Kann das ganze auch 
weiterspinnen 2 verschiedene OS( Windows, Linux).
Außerdem habe ich gleiche Fuse-Bits + Jumper Einstellungen wie damals 
als es Funktioniert hat. Habe von allem Bilder gemacht und genau so 
eingestellt. Es geht trotzdem nicht.

Ich habe schon alles ausgetauscht was geht und das Programm lief so 
schon mal. Deshalb bin ich auch so verwirrt.

von Michael (Gast)


Lesenswert?

Hat sonst wirklich niemand eine Idee? Wie groß ist den bitte die 
Wahrscheinlichlichkeit, dass z.b. genau beide RTCs zur selben Zeit 
kaputt gehen oO

von Robert (Gast)


Lesenswert?

Nun, nachdem du ja schon erfolgreich zu diesem Zeitpunkt
2 mal I2C_start und einen I2C_send hinter dich gebracht hast
würde ich zur Zeit davon ausgehen, dass der RTC Baustein nicht kaputt 
ist.
In welchem I2C_get bleibt es denn hängen?
Schon beim ersten?

Hmmm, der CS5463 ist kein RTC und hat auch kein I2C Interface sondern 
SPI.

Und im Schaltplan ist keine Bezeichnung deines 8poligen I2C-Zwergs

Mach mal dazu bitte die richtigen Angaben

von Robert (Gast)


Lesenswert?

Aufgrund der Tatsache dass du den RTC mit Adresse 0xD0 ansprichst gehe 
ich mal davon aus, dass es sich um einen DS1307 handeln könnte.

Den hab ich hier in einer single/multimasterumgebung ohne Probleme am 
laufen.
Was mir dabei auffällt ist, dass du immer das gleiche I2C_get benutzt.
Im Datenblatt steht: "The DS1307/DS1308 must receive a Not Acknowledge 
to end
a read."
die Abfolge sollte so aussehen

I2C_start(Writeadresse);
I2C_send(00)  setzen des Adresszeigers auf gewünschte Adresse
I2C_repstart(Readadresse);
I2C_readack() byte lesen mit ACK falls noch weitere bytes gelesen werden
...
I2C_readnack() letztes gwünschtes byte lesen und mit NACK quittieren.
I2C_stop()

von Michael (Gast)


Lesenswert?

Ah tut mir leid, ich habe vorher den Messchip geschrieben....
Ich benutze den DS1340 RTC. Und dort steht nichts von nack drin, 
zumindest habe ich nichts gefunden. Danke schonmal und sorry nochmal, 
wegen der falschen Angabe!

von Michael (Gast)


Lesenswert?

Nocheinmal kurz ein Gedanke dazu:
es bleibt beim ersten get hängen.

Ich habe zwar vorher erfolgreich start gesendet und auch schon send, 
aber bei all diesen Befehlen, musste doch der RTC nichts machen oder? 
Ich hätte das ganze doch auch erfolgreich senden können, wenn nichts 
angesteckt gewesen wäre oder?
Beim get() Befehl muss zum ersten mal der RTC etwas machen und genau 
hier funktioniert nichts mehr. Deshalb war meine idee, dass der RTC bzw. 
Quarz kaputt ist. Allerdings das Austauschen hat nicht geholfen :/

von Robert (Gast)


Lesenswert?

Nun das Datenblatt des DS1340 enthält auf Page 12 folgende Info

Data transfer from a slave transmitter to a master
receiver. The master transmits the first byte (the
slave address). The slave then returns an acknowledge
bit. Next follows a number of data bytes transmitted
by the slave to the master. The master
returns an acknowledge bit after all received bytes
other than the last byte. At the end of the last
received byte, a not acknowledge is returned.

sowie:
The DS1340 must receive a not acknowledge to end a read.


Dies besagt dass auch hier das Ende des Transfers durch ein NACK beim 
letzten Read erfolgen soll.

Bis auf den unterschiedlichen Aufbau der DS1307 und DS1340 register ist 
das alles auf jeden Fall gleich.

mein code schaut so aus;
void twi_read_ds1307(void)
{
  uint8_t dr;
  // check if we have something at address 0xd0 around
  if(twi_probe(0xd0)) {
    return;
  }
  if(twi_start(0xd0,TWI_WRITE)) {return;}
  twi_write(0);
  if(twi_start(0xd0,TWI_READ)) {return;}
  dr=twi_readack();
  clock.sec=((dr >> 4) & 0x07)*10 + (dr & 0x0f);
  dr=twi_readack();
  clock.min=((dr >> 4) & 0x07)*10 + (dr & 0x0f);
  dr=twi_readack();
  if(dr & 0x40) {
    clock.hrs=((dr >> 4) & 0x01)*10 + (dr & 0x0f);
    if(clock.hrs == 12) {
      clock.hrs=0;
    }
    if(dr & 0x20) {
      clock.hrs += 12;
    }
  } else {
    clock.hrs=((dr >> 4) & 0x03)*10 + (dr & 0x0f);
  }
  dr=twi_readack(); // weekday -> skipped, because we calc it for 
ourself
  dr=twi_readack(); // day
  clock.day=((dr >> 4) & 0x03)*10 + (dr & 0x0f);
  dr=twi_readack(); // month
  clock.mon=((dr >> 4) & 0x01)*10 + (dr & 0x0f);
  dr=twi_readack(); // year
  clock.year=((dr >> 4) & 0x0f)*10 + (dr & 0x0f);
  dr=twi_readack(); // control register -> skip
->dr=twi_readnack(); // century from 1. SRAM location
  twi_stop();
  clock.year += ((dr >> 4) & 0x0f)*1000 + (dr & 0x0f)*100;
  calc_dpm(0,0); // get the day per month
  calc_weekday(); // get the current weekday
}

Der einzige Unterschied ist dass ich gleich alles von BCD umkonvertiere
um nicht später immer wieder das Gleiche zu machen. Ich führe diese 
Routine auch nur einmal beim Start aus um meine interne Uhr zu setzen
die ansonsten mit einem 1000Hz Interrupt weitergeführt wird.
habe das letzte read mit einem "->" markiert, dass dann mit NACK 
quittiert.

von Robert (Gast)


Lesenswert?

Nun wenn du I2C_start mit der Adresse des RTC machst, muss dieser 
quittieren,
ausserdem sendest du auf jeden Fall ein byte, nämlich den Addresszeiger.
dann schaltest du um auf Read, nur warum es dann hängt ????

von Robert (Gast)


Lesenswert?

Allerdings liest du den RTC in jedem Schleifendurchgang immer wieder neu 
aus, könnte es sein, das das ganze nicht beim 1. Mal, sondern erst beim 
2. Mal hängt?

von Michael (Gast)


Lesenswert?

Danke Robert, ich werde das sobald ich wieder Zeit habe gleich testen 
und werde dann heute noch schreiben, ob es funktioniert.

Das Programm bleibt beim 1 Schleifendurchlauf stecken! (erkennt man 
indem man über UART davor und danach daten sendet und dann stk500 
neustartet.)

Was mich nur wundert. Warum hat das Programm 3 Monate lang funktioniert, 
wenn ich es doch falsch programmiert habe (so wie es Robert erklärt hat) 
oO?

von Michael (Gast)


Lesenswert?

Robert, kannst du mir vielleicht auch noch deine funktionen:

twi_readack();
und
twi_readnack();
zeigen?

Wäre dir wirklich dankbar.
Mich wundert es nur, dass ich damals nie irgendwas mit ACK eingebaut 
habe oO Und dabei steht das doch eh ziemlich eindeutig dort... oO Danke 
aufjedenfall schonmal.

von Robert (Gast)


Lesenswert?

bitte sehr,

int twi_readack (void)
{
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);

  while (!(TWCR & (1<<TWINT)));

  return TWDR;
}

int twi_readnack (void)
{
  TWCR = (1<<TWINT)|(1<<TWEN);
  while(!(TWCR & (1<<TWINT)));

  return TWDR;
}

habe ich allerdings inzwischen in eine funktion mit argument gewandelt
int twi_read (uint8_t flags)
{
  TWCR = (1<<TWINT)|(1<<TWEN)|(flags&TWI_NACK)?0:(1<<TWEA);

  while (!(TWCR & (1<<TWINT)));

  return TWDR;
}
wenn als flag TWI_NACK angegeben wird dann wird TWEA nicht gesetzt

von Michael (Gast)


Lesenswert?

Soooo bin heute endlich zum austesten gekommen und habe folgendes 
bemerkt:

*) Der Fehler liegt viel weiter vorne, aber trotzdem danke, habe den 
anderen Fehler auch ausgebessert und das Programm ein bisschen 
überarbeitet (schöner geschrieben)

*) Ich habe einen ziemlich dummen Fehler, nämlich bei USART_send() 
überprüfe ich ob ich ein ACK zuürckbekommen, allerdings wenn es keines 
ist, gehe ich in eine Error Routine, die nichts macht => Es war schon 
die ganze Zeit hier vorne ein Fehler, nur habe ich das nie bemerkt!
Ich bekomme andauernt Not ACKs vom RTC zurück! Sprich 0x20, dann 8 mal 
0x30 , einmal 0x20 und wieder 0x30 und 0x48! Sprich für SLA+W immer NACK 
und für Data NACK usw.

Was ich kann ich jetzt daraus schließen? Wo soll ich weiter den Fehler 
suchen? (ist der RTC vielleicht doch nicht mehr in ordnung?) Bitte helft 
mir.

von Michael (Gast)


Lesenswert?

Robert, ich weiß es ist eine sehr große bitte, aber könntest du mir vll. 
dein Programm raufladen? Dann könnte ich wenigstens weiter den Fehler 
eingrenzen, du würdest mir wirklich einen rießen Gefallen machen.

von Robert (Gast)


Lesenswert?

Hi,

mein ganzes Programm würde den Rahmen doch sehr sprengen, da es zur Zeit 
nicht in ein 32k flash passt.
Es handelt sich hierbei um einen kompletten Kommandointerpreter um 
Manipulationen und Monitoring an und im uC durchzuführen ohne jedes Mal
sofort flashen zu müssen.
Das ganze ist auch immer noch work-in-progress da ich schritt für 
schritt alle Komponenten unterstütze derer ich habhaft werde.
Das ganze hat als Kern einen 1000Hz Interrupt, der zur Zeit als 
Hauptanwendung eine interne Uhr bedient.
Sowie Kommandos die über serielle Schnittstelle empfangen werden und 
dann
interpretiert werden mittels einer Stateengine.
Zusätzliche Hardware die bislang unterstützt wird:
LCD mit 4-bit Schnittstelle an einem uC Port
LCD mit 4-bit Schnittstelle via I2C
RTC via I2C
Temperatursensor via I2C

Ich kann höchstens mal die I2C Routinen isolieren und mit einem 
separaten
main.c kombinieren, um nur dein Problem nachzustellen. Es geht ja im 
Prinzip nur um das Lesen der Register des RTC, was ich als separate 
Routine für meinen DS1307 habe. Soweit sollten die RTC's sich gleich 
verhalten.

Bei den Zugriffen die du beschreibst achte ich auch gar nicht auf NACK 
oder ACK vom Slave.

Die I2C Routinen die ich bislang implementiert habe werden auch noch 
nicht
von einer ISR bedient, was ich aber auf jeden Fall implementieren 
möchte.

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.