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!
Wenns kein .rar wär sondern z.B. .zip hätte ich mal draufgeschaut......
Hier nochmal als zip! RTC ist übrigens ein CS5463 Würdest mir echt einen rießend Gefallen machen!
>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.
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.
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
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
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()
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!
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 :/
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.
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 ????
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?
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?
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.
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
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.