EEPROM mit TWI Schnittstelle beschreiben und lesen

Gast #2020288
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

1
//eeprom_twi_tests:
2
int SLA_W = 0x85;
3
int DATA = 0xBC;
4

5
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //uC als Master definieren, START condition
6
while (!(TWCR & (1<<TWINT))); //warten und prüfen ob richtig gesendet
7
if ((TWSR & 0xF8) != TW_START); //Wenn anderer Wert als beim senden --> Error
8
  //error?
9
TWDR = SLA_W; //SLA_W sendet die Adresse
10
TWCR = (1<<TWINT) | (1<<TWEN); //Lösche TWINT bit im TWCR um das Senden der Adresse zu beginnen
11
while (!(TWCR & (1<<TWINT))); //Warten auf TWINT Flag, bedeutet SLA_W wurde gesendet und ACK/NACK wurde empfangen
12
if((TWSR & 0xF8) != TW_MT_SLA_ACK); //Prüfe TWI Status Register, wenn status anders als im MT_SLA_ACK -> Error 
13
  //error?
14
TWDR = DATA; //Data -> Daten in das TWDR Register geladen werden sollen
15
TWCR = (1<<TWINT) | (1<<TWEN); //Lösche TWINT bit in TWCR zum starten der Übertragung
16
while (!(TWCR & (1<<TWINT))); //Warte auf TWINT Flag, bedeutet DATA wurde gesendet und ACK/NACK wurde empfangen
17
uart_puts("zweiter error weiter");
18
if ((TWSR & 0xF8) != TW_MT_DATA_ACK); //Überprüfe Wert vom TWI Status Register
19
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Transmit Stop condition
#2020535
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!!!!
1
if ((TWSR & 0xF8) != TW_START) //Wenn anderer Wert als beim senden --> Error
2
  uart_puts("Keine TW-Start erhalten!");
3
....
4
if((TWSR & 0xF8) != TW_MT_SLA_ACK) //Prüfe TWI Status Register, wenn status anders als im MT_SLA_ACK -> Error 
5
  uart_puts("Keine TW_MT_SLA_ACK erhalten!");
6
....

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

Stephan
Gast #2021858
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
1
//eeprom_twi_tests:
2
char SLA_W = 0xA0;
3
char DATA0 = 0x00;
4
char DATA1 = 0x00;
5
char DATA2 = 0xAB;
6
char DATA3 = 0xAB;
7

8

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

16
TWDR = SLA_W; //SLA_W sendet die Adresse
17
TWCR = (1<<TWINT) | (1<<TWEN);
18
while (!(TWCR & (1<<TWINT)));
19
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
20
  //error?
21
uart_puts("error02");
22
}
23
  //error?
24
TWDR = DATA0; //Data -> Daten in das TWDR Register geladen werden sollen
25
TWCR = (1<<TWINT) | (1<<TWEN);
26
while (!(TWCR & (1<<TWINT)));
27
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
28
  //error?
29
uart_puts("error03");
30
}
31

32
TWDR = DATA1;
33
TWCR = (1<<TWINT) | (1<<TWEN);
34
while (!(TWCR & (1<<TWINT)));
35
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
36
  //error?
37
uart_puts("error04");
38
}
39

40
TWDR = DATA2;
41
TWCR = (1<<TWINT) | (1<<TWEN);
42
while (!(TWCR & (1<<TWINT)));
43

44
TWDR = DATA3;
45
TWCR = (1<<TWINT) | (1<<TWEN);
46
while (!(TWCR & (1<<TWINT)));
47

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

51
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/16459/m24512-w.pdf

Vielen dank für jeden Hinweis.
MFG
Gast #2021862
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
1
//eeprom_twi_tests:
2
char SLA_W = 0xA0;
3
char DATA0 = 0x00;
4
char DATA1 = 0x00;
5
char DATA2 = 0xAB;
6
char DATA3 = 0xAB;
7

8

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

16
TWDR = SLA_W; //SLA_W sendet die Adresse
17
TWCR = (1<<TWINT) | (1<<TWEN);
18
while (!(TWCR & (1<<TWINT)));
19
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
20
  //error?
21
uart_puts("error02");
22
}
23
  //error?
24
TWDR = DATA0; //Data -> Daten in das TWDR Register geladen werden sollen
25
TWCR = (1<<TWINT) | (1<<TWEN);
26
while (!(TWCR & (1<<TWINT)));
27
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
28
  //error?
29
uart_puts("error03");
30
}
31

32
TWDR = DATA1;
33
TWCR = (1<<TWINT) | (1<<TWEN);
34
while (!(TWCR & (1<<TWINT)));
35
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
36
  //error?
37
uart_puts("error04");
38
}
39

40
TWDR = DATA2;
41
TWCR = (1<<TWINT) | (1<<TWEN);
42
while (!(TWCR & (1<<TWINT)));
43

44
TWDR = DATA3;
45
TWCR = (1<<TWINT) | (1<<TWEN);
46
while (!(TWCR & (1<<TWINT)));
47

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

51
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:

1
SLA_W = 0xA0;
2
char DATA00 = 0x00;
3
char DATA01 = 0x00;
4

5
char SLA_R = 0xA1;
6

7
_delay_ms(2000);
8

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

16
TWDR = SLA_W;
17
TWCR = (1<<TWINT) | (1<<TWEN);
18
while (!(TWCR & (1<<TWINT)));
19
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
20
  //error?
21
uart_puts("error08");
22
}
23

24
TWDR = DATA00;
25
TWCR = (1<<TWINT) | (1<<TWEN);
26
while (!(TWCR & (1<<TWINT)));
27
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
28
  //error?
29
uart_puts("error09");
30
}
31

32
TWDR = DATA01;
33
TWCR = (1<<TWINT) | (1<<TWEN);
34
while (!(TWCR & (1<<TWINT)));
35
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
36
  //error?
37
uart_puts("error10");
38
}
39

40

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

44
if ((TWSR & 0xF8) != TW_START){
45
  //error?
46
uart_puts("error11");
47
}
48

49
TWDR = SLA_R;
50
TWCR = (1<<TWINT) | (1<<TWEN);
51
while (!(TWCR & (1<<TWINT)));
52
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
53
  //error?
54
uart_puts("error12");
55
}
56

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

59
uart_puts(TWDR);
60

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

Ich verwende das EEPROM ST M24512.

Datenblatt: 
http://www.st.com/stonline/products/literature/ds/16459/m24512-w.pdf

Vielen dank für jeden Hinweis.
MFG
#2021923
Lesenswert?

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

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

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

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

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

Stephan
Gast #2021999
Lesenswert?

1
//uart_puts("test");
2

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

8
//uart_puts("test2");
9

10
//eeprom_twi_tests:
11
char SLA_W = 0xA0;
12
int DATA0 = 0x00;
13
int DATA1 = 0x00;
14
int DATA2 = 0xAB;
15
int DATA3 = 0xAB;
16

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

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

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

43
TWDR = DATA1;
44
TWCR = (1<<TWINT) | (1<<TWEN);
45
while (!(TWCR & (1<<TWINT)));
46
if ((TWSR & 0xF8) != TW_MT_DATA_ACK){
47
  //error?
48
uart_puts("error04");
49
}
50
uart_putc(TWSR);       // DEBUG - 0x28 (alles okay)
51

52
TWDR = DATA2;
53
TWCR = (1<<TWINT) | (1<<TWEN);
54
while (!(TWCR & (1<<TWINT)));
55

56
TWDR = DATA3;
57
TWCR = (1<<TWINT) | (1<<TWEN);
58
while (!(TWCR & (1<<TWINT)));
59

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

63
PORTC &= ~(1 << DDC2);
64

65

66

67

68

69

70

71

72

73

74
SLA_W = 0xA0;
75
char DATA00 = 0x00;
76
char DATA01 = 0x00;
77

78
char SLA_R = 0xA1;
79

80
_delay_ms(2000);
81

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

89
TWDR = SLA_W;
90
TWCR = (1<<TWINT) | (1<<TWEN);
91
while (!(TWCR & (1<<TWINT)));
92
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
93
  //error?
94
uart_puts("error08");
95
}
96

97
TWDR = DATA00;
98
TWCR = (1<<TWINT) | (1<<TWEN);
99
while (!(TWCR & (1<<TWINT)));
100
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
101
  //error?
102
uart_puts("error09");
103
}
104

105
TWDR = DATA01;
106
TWCR = (1<<TWINT) | (1<<TWEN);
107
while (!(TWCR & (1<<TWINT)));
108
if((TWSR & 0xF8) != TW_MT_DATA_ACK){
109
  //error?
110
uart_puts("error10");
111
}
112

113

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

117
if ((TWSR & 0xF8) != TW_REP_START){
118
  //error?
119
uart_puts("error11");
120
}
121

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

124
TWDR = SLA_R;
125
TWCR = (1<<TWINT) | (1<<TWEN);
126
while (!(TWCR & (1<<TWINT)));
127
if((TWSR & 0xF8) != TW_MT_SLA_ACK){
128
  //error?
129
uart_puts("error12");
130
}
131

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

134
uart_putc(TWDR);
135

136
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
Gast #2022128
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:
1
TWCR = (1<<TWINT) | (1<<TWEN);
2
while (!(TWCR & (1<<TWINT)));
3

4
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.
#2022152
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
Gast #2022184
Lesenswert?

Geht jetzt, man sollte nur
1
PORTC |=(1<<DDC2);

zu beginn, mit dem hier ersetzen
1
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
#2022228
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren