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!
>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 getestetAber 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.
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.