mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik EEPROM mit TWI Schnittstelle beschreiben und lesen


Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
bekomme die TWI nicht zum Laufen. Nutze ein ATmega644P. Hab den Code aus 
dem Datenblatt. Sehe auch nichts auf dem Osci.

Bitte um Hilfe.
MFG

//eeprom_twi_tests:
int SLA_W = 0x85;
int DATA = 0xBC;

TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //uC als Master definieren, START condition
while (!(TWCR & (1<<TWINT))); //warten und prüfen ob richtig gesendet
if ((TWSR & 0xF8) != TW_START); //Wenn anderer Wert als beim senden --> Error
  //error?
TWDR = SLA_W; //SLA_W sendet die Adresse
TWCR = (1<<TWINT) | (1<<TWEN); //Lösche TWINT bit im TWCR um das Senden der Adresse zu beginnen
while (!(TWCR & (1<<TWINT))); //Warten auf TWINT Flag, bedeutet SLA_W wurde gesendet und ACK/NACK wurde empfangen
if((TWSR & 0xF8) != TW_MT_SLA_ACK); //Prüfe TWI Status Register, wenn status anders als im MT_SLA_ACK -> Error 
  //error?
TWDR = DATA; //Data -> Daten in das TWDR Register geladen werden sollen
TWCR = (1<<TWINT) | (1<<TWEN); //Lösche TWINT bit in TWCR zum starten der Übertragung
while (!(TWCR & (1<<TWINT))); //Warte auf TWINT Flag, bedeutet DATA wurde gesendet und ACK/NACK wurde empfangen
uart_puts("zweiter error weiter");
if ((TWSR & 0xF8) != TW_MT_DATA_ACK); //Überprüfe Wert vom TWI Status Register
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition

Autor: Stephan W. (sir_wedeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

den Code haste scheinbar richtig abgetippt, also muss der Fehler wo 
anders sein! Zeig mal das restliche Programm bzw. mach ein mini Prog. 
auf, damit wir es testen können.

Schaltplan wäre auch nicht schlecht, sowie der Name des EEProms das du 
ansprechen willst.

Schreibe bitte NIE LEERE! IF - Anweisungen in dein Code, das ist nicht 
gut!!!!
if ((TWSR & 0xF8) != TW_START) //Wenn anderer Wert als beim senden --> Error
  uart_puts("Keine TW-Start erhalten!");
....
if((TWSR & 0xF8) != TW_MT_SLA_ACK) //Prüfe TWI Status Register, wenn status anders als im MT_SLA_ACK -> Error 
  uart_puts("Keine TW_MT_SLA_ACK erhalten!");
....

für kleine Testprogs. ist es immer gut kleine DebugMess. zu senden! Im 
richtigen Code, werden dann aber Return-Val. verwendet!

Stephan

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
also ein Teil funktioniert jetzt. Am Osci scheint auch alles in Ordnung 
zu sein, das schreiben gibt mir KEINE Fehler aus, also alle ACK's werden 
erhalten
//eeprom_twi_tests:
char SLA_W = 0xA0;
char DATA0 = 0x00;
char DATA1 = 0x00;
char DATA2 = 0xAB;
char DATA3 = 0xAB;


TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //uC als Master definieren, START condition
while (!(TWCR & (1<<TWINT))); //warten und prüfen ob richtig gesendet
if ((TWSR & 0xF8) != TW_START){ //Wenn anderer Wert als beim senden --> Error
  //error?
uart_puts("error01");
}

TWDR = SLA_W; //SLA_W sendet die Adresse
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error02");
}
  //error?
TWDR = DATA0; //Data -> Daten in das TWDR Register geladen werden sollen
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error03");
}

TWDR = DATA1;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error04");
}

TWDR = DATA2;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));

TWDR = DATA3;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition
while (TWCR & (1<<TWINT));

PORTC &= ~(1 << DDC2);


Jetzt habe ich versucht, meine Bytes wieder auszulesen, es wird mir über 
meine USB am Terminal, der error11 und error12 ausgegeben.

Der Code sieht so aus:


SLA_W = 0xA0;
char DATA00 = 0x00;
char DATA01 = 0x00;

char SLA_R = 0xA1;

_delay_ms(2000);

TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //Start
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_START){
  //error?
uart_puts("error07");
}

TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error08");
}

TWDR = DATA00;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error09");
}

TWDR = DATA01;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error10");
}


TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //Start
while (!(TWCR & (1<<TWINT)));

if ((TWSR & 0xF8) != TW_START){
  //error?
uart_puts("error11");
}

TWDR = SLA_R;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error12");
}

TWCR = (1<<TWINT) | (1<<TWEN);

uart_puts(TWDR);

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition
uart_puts(TWDR);[/c]

Ich verwende das EEPROM ST M24512.

Datenblatt: 
http://www.st.com/stonline/products/literature/ds/...

Vielen dank für jeden Hinweis.
MFG

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
also ein Teil funktioniert jetzt. Am Osci scheint auch alles in Ordnung 
zu sein, das schreiben gibt mir KEINE Fehler aus, also alle ACK's werden 
erhalten
//eeprom_twi_tests:
char SLA_W = 0xA0;
char DATA0 = 0x00;
char DATA1 = 0x00;
char DATA2 = 0xAB;
char DATA3 = 0xAB;


TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //uC als Master definieren, START condition
while (!(TWCR & (1<<TWINT))); //warten und prüfen ob richtig gesendet
if ((TWSR & 0xF8) != TW_START){ //Wenn anderer Wert als beim senden --> Error
  //error?
uart_puts("error01");
}

TWDR = SLA_W; //SLA_W sendet die Adresse
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error02");
}
  //error?
TWDR = DATA0; //Data -> Daten in das TWDR Register geladen werden sollen
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error03");
}

TWDR = DATA1;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error04");
}

TWDR = DATA2;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));

TWDR = DATA3;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition
while (TWCR & (1<<TWINT));

PORTC &= ~(1 << DDC2);


Jetzt habe ich versucht, meine Bytes wieder auszulesen, es wird mir über 
meine USB am Terminal, der error11 und error12 ausgegeben.

Der Code sieht so aus:

SLA_W = 0xA0;
char DATA00 = 0x00;
char DATA01 = 0x00;

char SLA_R = 0xA1;

_delay_ms(2000);

TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //Start
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_START){
  //error?
uart_puts("error07");
}

TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error08");
}

TWDR = DATA00;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error09");
}

TWDR = DATA01;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error10");
}


TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //Start
while (!(TWCR & (1<<TWINT)));

if ((TWSR & 0xF8) != TW_START){
  //error?
uart_puts("error11");
}

TWDR = SLA_R;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error12");
}

TWCR = (1<<TWINT) | (1<<TWEN);

uart_puts(TWDR);

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition
uart_puts(TWDR);

Ich verwende das EEPROM ST M24512.

Datenblatt: 
http://www.st.com/stonline/products/literature/ds/...

Vielen dank für jeden Hinweis.
MFG

Autor: Stephan W. (sir_wedeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //Start
while (!(TWCR & (1<<TWINT)));

if ((TWSR & 0xF8) != TW_START){
  //error?
uart_puts("error11");
}

ändere dies zu:
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //Start
while (!(TWCR & (1<<TWINT)));

if ((TWSR & 0xF8) != TW_REP_START){
  //error?
uart_puts("error11");
}

gebe auch das Register: TWSR in den DebugMes. aus, kann helfen.

Stephan

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
//uart_puts("test");

_delay_ms(4000);
TWBR = ((14745600UL/100000)-16/2);
_delay_ms(2000);
PORTC |= (1 << DDC2);

//uart_puts("test2");

//eeprom_twi_tests:
char SLA_W = 0xA0;
int DATA0 = 0x00;
int DATA1 = 0x00;
int DATA2 = 0xAB;
int DATA3 = 0xAB;

TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //uC als Master definieren, START condition
while (!(TWCR & (1<<TWINT))); //warten und prüfen ob richtig gesendet
if ((TWSR & 0xF8) != TW_START){ //Wenn anderer Wert als beim senden --> Error
  //error?
uart_puts("error01");
}

TWDR = SLA_W; //SLA_W sendet die Adresse
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error02");
}
uart_putc(TWSR);       // DEBUG - 0x18 (alles okay)

  //error?
TWDR = DATA0; //Data -> Daten in das TWDR Register geladen werden sollen
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error03");
}
uart_putc(TWSR);       // DEBUG - 0x28 (alles okay)

TWDR = DATA1;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error04");
}
uart_putc(TWSR);       // DEBUG - 0x28 (alles okay)

TWDR = DATA2;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));

TWDR = DATA3;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition
while (TWCR & (1<<TWINT));

PORTC &= ~(1 << DDC2);










SLA_W = 0xA0;
char DATA00 = 0x00;
char DATA01 = 0x00;

char SLA_R = 0xA1;

_delay_ms(2000);

TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //Start
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_START){
  //error?
uart_puts("error07");
}

TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error08");
}

TWDR = DATA00;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error09");
}

TWDR = DATA01;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
  //error?
uart_puts("error10");
}


TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //ReStart
while (!(TWCR & (1<<TWINT)));

if ((TWSR & 0xF8) != TW_REP_START){
  //error?
uart_puts("error11");
}

uart_putc(TWSR);       // DEBUG - 0x10 (A repeatet START condition has been transmitted)

TWDR = SLA_R;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
  //error?
uart_puts("error12");
}

uart_putc(TWSR);      // Mega seltsamer 0x00 Wert

uart_putc(TWDR);

TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition



Hab nochmal geschaunt, wenn man ein erneutes START con senden will, muss 
da ein TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //ReStart rein
TWSTA, das funktioniert schonmal, doch error12 bleibt und er gibt bei 
TWSR nur ein komisches 0x00 raus, was im Datenblatt nicht verzeichnet 
ist.

Vielen Dank für deine Hilfe.
MFG

Autor: Stephan W. (sir_wedeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
ich sehe zwar den Fehler gerade nicht, aber es kann kein "TW_MT_SLA_ACK" 
raus kommen!!!

Das MT steht für MasterTransmit!

ich würde diese hier erwarten:
TW_MR_SLA_ACK
TW_MR_SLA_NACK oder
TW_MR_ARB_LOST

in den seltenen Fällen auch
TW_BUS_ERROR

schau noch mal nach.

Stephan

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
TW_MR_SLA_ACK

damit erhalte ich kein error mehr,

um jetzt weiter zu clken und die Daten erhalten zu wollen, muss ich doch 
folgendes eingeben:
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));

uart_putc(TWDR);

Ist das richtig so? Bekomm da nämlich noch nicht das was ich sende, also 
das 0xAB

Vielen herzlichen Dank für deine Hilfe.

Autor: Stephan W. (sir_wedeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>damit erhalte ich kein error mehr,
also war der Status doch nicht NULL!
Wenn dein Terminal-Programm nur ASCII-Daten anzeigt, dann musst du deine 
DebugMess. ändern!!!!

>Ist das richtig so?
Ja, fast! Schau dir nochmal die Abfolge im DB deines EEProms an!
Da steht was zu ACK und NACK von Datenbytes.

mögliche Statuscodes vom MC überprüfen <- als TIP
TW_SR_DATA_ACK
TW_SR_DATA_NACK

Stephan

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Er hatte zumindest Null angezeigt. Kann sein das ich was verpeilt hatte, 
muss wohl so sein :)

Autor: Jack (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht jetzt, man sollte nur
PORTC |=(1<<DDC2);

zu beginn, mit dem hier ersetzen
PORTC &=~(1<<DDC2);

Falls es jemand jemals brauchen sollte.


Vielen Dank nochmal. Warst mir eine große Hilfe.

Eine Frage habe ich noch, wenn das eeprom "voll" ist, beginnt er von 
vorn richtig? Gibt es eine Art Belegt-Status oder muss man beim 
programmieren "mitrechnen"?

Mfg

Autor: Stephan W. (sir_wedeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Eine Frage habe ich noch, wenn das eeprom "voll" ist, beginnt er von
>vorn richtig? Gibt es eine Art Belegt-Status oder muss man beim
>programmieren "mitrechnen"?
ja, im EEProm wird der Adresszeiger wieder auf Null gesetzt wenn du über 
das Ende schreibst(ließt).
Einen Belegstatus gibs nicht!

so dann noch viel Spaß damit.

Stephan

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.