Hi zusammen, ich hab hier eigenartiges Phänomen, und find den Fehler nicht: zwei ATmega328P kommunizieren per i2c miteinander, einer Master einer Slave, Master frägt alle 10 msec und Slave antwortet mit einem int32_t, also vier Byte. Das ganze funktioniert soweit wunderbar, aber von Zeit zu zeit empfange ich -1 also 0xffffffff. Das problem liegt definitiv am Empfänger = Master, ich hab testweise die i2c-Routine des Slaves so modifiziert dass TWDR beim Daten senden hart auf 0x66 gesetzt wird. Ich empfange dann auch 0x66666666, aber ab und an wieder 0xffffffff. Ursache kann eigentlich nur sein, dass TWDR eben 0xff enthält. Eigenartigerweise schaut der Transfer sonst ganz normal aus, es kommen vier Bytes, kein Fehler, nächster Transfer ist dann idR auch wieder in Ordnung. Der i2c-Receiver ist interrupt-basierend, und die empfangenden Werte werden auch ausschließlich in den Stati "Data byte has been received; ACK has been returned" (erste bytes) und "Data byte has been received; NOT ACK has been returned" (letztes Byte) verarbeitet. Gibts da noch irgendein Flag das mir einen Fehler mitteilen möchte? Vielleicht ein Timeout? Aber dann hätt ich doch im TWI-Status-Register nciht absolut plausible werte stehen? Es kann doch auch nciht sein dass irgendwas mir die SDA auf low zieht, dann würde ja schon die ganze Slave-Adressierung usw. nicht funktionieren... Hat bitte bitte jemand eine idee was da faul sein könnte?
Wie kommst Du darauf, dass es definitiv am Master liegt? 0xff ist typisch für einen Slave, der SDA nicht ansteuert. Bekommst Du nach der Read Adresse immer ein ACK vom Slave?
Klaus 2m5 schrieb: > Wie kommst Du darauf, dass es definitiv am Master liegt? "definitiv" ist natürlich relativ :-) > 0xff ist typisch für einen Slave, der SDA nicht ansteuert. Bekommst Du > nach der Read Adresse immer ein ACK vom Slave? Ja, sonst würde mir die TWI-State Machine ja gar nicht erst in den lese-Teil springen.
Gast
#3148282
Code? Hast du eine I2C monitor? Oszi? Vielleicht sendet der Slave ja auch nicht? Mal auf beiden Seiten einen Zähler eingebaut und geprüft ob die gleichmäßig hoch laufen? Fehlerbehandlung und Zähler eingebaut?
Tim schrieb: > Code? Bitte gerne. > Hast du eine I2C monitor? Oszi? I2C-Monitor nicht, Billigst-Oszi schon, aber kein Speicher-oszi. Da geschätzte 99% der Übertragungen problemlos funktionieren, wirds mit meinem oszi schwierig... > Vielleicht sendet der Slave ja auch nicht? Dann würde er auch kein ACK auf das SLA+R senden? > Mal auf beiden Seiten einen Zähler eingebaut und > geprüft ob die gleichmäßig hoch laufen? Wie meinst du das? Code des Slave-Transmitters/Receivers:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
Code des Masters:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
Der Slave sendet bei Anfrage den int32_t Stepper_position. Der Master fragt 100mal in der Sekunde per i2c_get(0x66, &int32_var, sizeof(int32_var) ab.
Ich würde mir an Deiner Stelle einen Trace bauen: Die letzten 20 Statuscodes in einem Array speichern und wenn Du 0xffffffff zurückbekommst ausgeben.
Gast
#3148790
>> Hast du eine I2C monitor? Oszi? >I2C-Monitor nicht, Billigst-Oszi schon, aber kein Speicher-oszi. Hier im Forum sind ein parr I2C Monitore beschrieben. Definitiv eine Anschaffung wert. >> Vielleicht sendet der Slave ja auch nicht? >Dann würde er auch kein ACK auf das SLA+R senden? Nun wenn du alles ausschließt muss die Übertragung ja auch immer zu 100% funktionieren.... >> Mal auf beiden Seiten einen Zähler eingebaut und >> geprüft ob die gleichmäßig hoch laufen? >Wie meinst du das? Nun, nach erfolgreichem Abschluss der Übertragung auf beiden Seiten einen Zähler erhöhen. Dann weisst du wenigstens ob die Routinen der Ansicht sind das alles OK ist. Fehlerzähler sind natürlich Pflicht. Ich habe mir den Code durchgelesen aber keinen offensichtlichen Fehler finden können. Ich gehe mal davon aus das du den return wert von i2c_get auswertest. Externen Pullups hat du dran?
bin leider erst jetzt dazu gekommen, mir das genauer anzuschauen. ja, externe Pullups (je 4k7 am Master und am Slave) sind dran. Ich hab mal die idee aufgegriffen, mir die letzten 32 TWI-Stati am Master receiver zu merken, und im Fall dass ich 0xff empfange, auszugeben. Das Ergebnis hilft nciht wirklich weiter: 0x58 // Data byte has been received; NOT ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x40 // SLA+R has been transmitted; ACK has been received 0x08 // A START condition has been transmitted 0x58 // Data byte has been received; NOT ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x40 // SLA+R has been transmitted; ACK has been received 0x08 // A START condition has been transmitted 0x58 // Data byte has been received; NOT ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x50 // Data byte has been received; ACK has been returned 0x40 // SLA+R has been transmitted; ACK has been received 0x08 // A START condition has been transmitted Die hex-Werte sind Echtdaten, die "Übersetzungen" hab ich händisch hinzugefügt. Die Tabelle ist "umgedreht", neuester Eintrag ist oben. Die letzte Übertragung liefert 4x 0xff, die anderen "normale" Werte. Die Übertragungen schauen aber alle gleich aus, keine Fehler, keine Ausreisser im Status, und entsprechen genau meinen Erwartungen bzw. auch der Auflistung aus dem ATmega-Datenblatt: 1. master Receiver sendet ein "START" um den Bus zu kriegen 2. Master Receiver sendet SLA+R und adressiert damit den Slave 3. Slave antwortet mit ACK 4. Slave schickt der reihe nach die Daten, master antwortet mit ACK bzw. mit NAK beim letzten Byte Als nächstes werd ich halt versuchen sowas ähnliches am Slave zu implementieren, wird nur etwas lästiger weil ich dort keinen UART habe um die Debug-Daten auszugeben.
So, ich bin einen Schritt weiter: Das problem tritt immer dann auf, wenn am Slave der Status 0xf8 " no relevant state information available; TWINT = 0" auftritt. ich weiss leider nicht wirklich, was dieser Status bedeutet, wann und warum er auftritt, und wie ich am besten darauf reagieren soll. Aus dem Datenblatt werd ich nciht wirklich schlau... Kann mir da jemand weiterhelfen?
Michael, wenn ich mich nicht täusche, müsste der Master nach dem Empfang des abschliessenden NAK vom Sklaven ein STOP-Signal senden!? Ohne das STOP erscheint dem Sklaven das nächste START als "repeated Start-Signal". Ciao, mare_crisium
Harald M. schrieb: > wenn ich mich nicht täusche, müsste der Master nach dem Empfang des > abschliessenden NAK vom Sklaven ein STOP-Signal senden!? Ohne das STOP > erscheint dem Sklaven das nächste START als "repeated Start-Signal". Tut er doch:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
0xf8 sollte nie einen Interrupt erzeugen (TWINT=0)! Trotzdem scheint der Slave die Interrupt Routine zu durchlaufen. Hast Du vielleicht einen Interrupt enabled, der vor dem TWI Vektor liegt, aber keinen Vektor definiert? 0xf8 ist wohl eher nur ein Status, der ohne Interrupts zum Tragen kommt, wenn das Program periodisch TWSR abfragt. Auf jeden Fall ist es kein Fehlerstatus und die ISR sollte einfach nichts tun, also nicht
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
sondern
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Harald M. schrieb: > wenn ich mich nicht täusche, müsste der Master nach dem Empfang des > abschliessenden NAK vom Sklaven ein STOP-Signal senden!? Ohne das STOP > erscheint dem Sklaven das nächste START als "repeated Start-Signal". Für den Slave besteht zwischen STOP...START und repeated START kein Unterschied. STOP wird nur in einer Multimaster Umgebung gebraucht, um dem anderen Master(s) mitzuteilen, dass der Bus jetzt wieder frei ist.
Klaus 2m5 schrieb: > 0xf8 sollte nie einen Interrupt erzeugen (TWINT=0)! Trotzdem scheint der > Slave die Interrupt Routine zu durchlaufen. Hast Du vielleicht einen > Interrupt enabled, der vor dem TWI Vektor liegt, aber keinen Vektor > definiert? Nein, kein falscher/fehlender Vektor. Offensichtlich ist das schon ein Interrupt, aber ein irgendwie spezieller. Auch die Application Notes avr311 und avr315 bzw. der Beispielcode dort ist sich nciht ganz sicher wie damit umzugehen ist :-) > 0xf8 ist wohl eher nur ein Status, der ohne Interrupts zum Tragen kommt, > wenn das Program periodisch TWSR abfragt. Auf jeden Fall ist es kein > Fehlerstatus und die ISR sollte einfach nichts tun Danke, da hast du natürlich recht! Hat mein problem aber nicht gelöst... Aber ich bin guter Hoffnng den Fehler schlussendlich gefunden zu haben: der Slave ruft in der MainLoop periodisch i2c_get() auf, um auf Kommandos des masters zu reagieren. Und dabei wird am TWCR herumgespielt, was so nicht sein darf. Ich muss das jetzt überdenken, halte euch aber am laufenden!
Yep, das wars. Ich bin ein Trottel :-) in der i2c_get() vom Slave wurde generell und immer folgende zeile ausgeführt:
1 | |
und das hat natürlich eine gerade laufende Transaktion gehörig durcheinandergebracht. Die zeile ist so schon korrekt, gehört aber nur ausgeführt wenn ein Fehler aufgetreten ist (also im "if I2C_error" zweig) Danke euch allen!
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.