Hallo, ich habe ein Problem mit der Repeated Start Condition am TWI. Allgemein soll eine Schreiboperation vom Master auf den Slave und im Anschluss daran eine Leseoperation vom Master an den Slave stattfinden. Das ganze funktioniert ohne Repeated Start (s. Anhang start_stop_start_stop.PNG und twi_start.txt), also nach dem Muster START_STOP_START_STOP wobei WRITE auf den Slave zwischen dem ersten START_STOP und READ zwischen dem zweiten START_STOP stattfindet. Führe ich nach dem ersten START ein Repeated Start aus um direkt ohne Verlust der Busverbindung zwischen Master Transmit auf Master Receive Mode umzuschalten, erhalte ich als Quittung nach dem SLA_R auf den Slave ein NACK (s. Anhang start_repeatedStart_stop.PNG und twi_repeated_start.txt). Der Stauts Code in TWSR ist entsprechend: 0x48 (SLA+R transmitted, NACK received). Ich hoffe jemand hat möglicherweise Erfahrung mit dem TWI und Repeated Start und kann mir erklären warum der Slave nach dem Repeated Start nicht mehr mit ACK antwortet und ohne Repeated Start schon. Danke für Hinweise! LG Markus
Markus E. schrieb: > Führe ich nach dem ersten START ein Repeated Start aus um direkt ohne > Verlust der Busverbindung zwischen Master Transmit auf Master Receive > Mode umzuschalten, erhalte ich als Quittung nach dem SLA_R auf den Slave > ein NACK Dazu müßte man den Slave-Code sehen, aber nicht als .txt, sondern als .c.
Markus E. schrieb: > ich habe ein Problem mit der Repeated Start Condition am TWI. Wenn du deinem Compiler deine Sourcen als *.txt Datei gibst dann wird das sowieso nichts. Und deine Leser die du um Hilfe bittest haben grössere Mühe überhaupt deine Sourcen zu betrachten.
Hier der Slave Code aus der Lib von Manfred Langemann, bei der ich noch die Repeated Start eingebaut habe.
Markus E. schrieb: > Ich hoffe jemand hat möglicherweise Erfahrung mit dem TWI und Repeated > Start und kann mir erklären warum der Slave nach dem Repeated Start > nicht mehr mit ACK antwortet und ohne Repeated Start schon. Weil dein Slave (den du uns verheimlichst) womöglich einen Protokoll-Verlauf verlangt der kein Repeated Start erfordert. Dum musst schon dazusagen welcher Slave und was du genau machen willst. Ein Datenblatt zum Slave wäre auch hilfreich. Das hier ist jedenfalls zu allgemein: Markus E. schrieb: > Allgemein soll eine Schreiboperation vom Master auf den Slave und im > Anschluss daran eine Leseoperation vom Master an den Slave stattfinden.
Der Slave ist ein ATMega8 (wie der Master auch). Den Slave Code habe ich angehängt. Den Ablauf der Ansteuerung habe ich in Post #1 erläutert und mehr ist es auch nicht. Nichts von wegen Protokoll etc.
:
Bearbeitet durch User
Markus E. schrieb: > Hier der Slave Code aus der Lib von Manfred Langemann, bei der ich noch > die Repeated Start eingebaut habe. Kein Wunder, daß das nicht geht. Main ist ja auskommentiert. Poste den exakten und vollständigen Code, wie er auf dem Slave ist! Mit nur ähnlichem Code kann Dir keiner helfen! Am besten schreib ein Minimalprogramm, was nur auf dem Slave eine Taste einliest und eine LED setzt, quasi einen PCF8574 emuliert. Alternativ kannst Du auch gleich einen PCF8574 als Slave nehmen, um den Mastercode zu prüfen.
:
Bearbeitet durch User
Im Anhang seht ihr nun meine TWI-Lib sowie den Master und Slave main-Code. Beide Devices (Master/Slave) sind ATMega8. Diese Codes führen zu den Bildern im Anhang aus Post #1.
:
Bearbeitet durch User
Ne, so geht das nicht. Als Slave kriegst Du nicht nur 60,A8, sondern auch viele andere States (80,88,A0,C0,C8). Du must alle I2C-States behandeln, sonst hängt sich der Slave auf. Schreib das besser als switch/case/default hin.
Ok danke für die Info. Gibt es die Möglichkeit herauszufinden mit welchem Status Code es aktuell scheitert um nur diesen erstmal zu behandeln oder müssen wirklich alle behandelt werden? Ich weiß gar nicht was ich bei den meisten davon am Slave tun müsste... Ich habe die Slave-main mal wie du meintest (außer der Behandlung aller...) umgeschrieben zu:
1 | #include <avr/io.h> |
2 | #include "TWI_LIB.h" |
3 | #include "MAX7221CNG.h" |
4 | |
5 | int main(void) |
6 | { |
7 | DDRB |= (1<<PB0); |
8 | PORTB &= ~(1<<PB0); |
9 | |
10 | twi_slave_init(11); |
11 | |
12 | MAX7221_initialization(); |
13 | writeDataBCD(123); |
14 | |
15 | uint8_t data[4]; |
16 | |
17 | while (1) |
18 | { |
19 | if (TWCR & (1<<TWINT)) |
20 | { |
21 | writeDataBCD(TWSR & 0xF8); |
22 | switch (TWSR & 0xF8) |
23 | { |
24 | case TW_SR_SLA_ACK: |
25 | twi_read_NACK(); |
26 | twi_stop_slave(); |
27 | break; |
28 | |
29 | case TW_ST_SLA_ACK: |
30 | twi_write_slave(100); |
31 | twi_stop_slave(); |
32 | break; |
33 | |
34 | default: |
35 | break; |
36 | } |
37 | } |
38 | } |
39 | } |
Wie man sieht habe ich mir den Status Code auf ein Display geschickt und anzeigen lassen. Der letzte übermittelte Status-Code ist 0x60, also Own "SLA+W has been received; ACK has been returned" vom Slave im Receiver Mode. Der Master empfängt ein 0x48 "SLA+R has been transmitted; NOT ACK has been received" was dem aktuellen Fehlverhalten entspricht. EDIT: Habe zum Test mal alle Codes des Slaves im Receiver und Transmitter Mode testweise mit aufgenommen. Die LED zu Testzwecken bleibt dunkel. Also wird kein anderer Status-Code als 0x60 am Slave mehr zur Verfügung gestellt.
1 | while (1) |
2 | { |
3 | |
4 | if (TWCR & (1<<TWINT)) |
5 | { |
6 | writeDataBCD(TWSR & 0xF8); |
7 | |
8 | switch (TWSR & 0xF8) |
9 | { |
10 | case TW_SR_SLA_ACK: |
11 | twi_read_NACK(); |
12 | twi_stop_slave(); |
13 | break; |
14 | |
15 | case TW_ST_SLA_ACK: |
16 | twi_write_slave(100); |
17 | twi_stop_slave(); |
18 | break; |
19 | |
20 | case TW_ST_ARB_LOST_SLA_ACK: |
21 | PORTB |= (1<<PB0); |
22 | break; |
23 | case TW_ST_DATA_ACK: |
24 | PORTB |= (1<<PB0); |
25 | break; |
26 | case TW_ST_DATA_NACK: |
27 | PORTB |= (1<<PB0); |
28 | break; |
29 | case TW_ST_LAST_DATA: |
30 | PORTB |= (1<<PB0); |
31 | break; |
32 | |
33 | case TW_SR_ARB_LOST_SLA_ACK: |
34 | PORTB |= (1<<PB0); |
35 | break; |
36 | case TW_SR_GCALL_ACK: |
37 | PORTB |= (1<<PB0); |
38 | break; |
39 | case TW_SR_ARB_LOST_GCALL_ACK: |
40 | PORTB |= (1<<PB0); |
41 | break; |
42 | case TW_SR_DATA_ACK: |
43 | PORTB |= (1<<PB0); |
44 | break; |
45 | case TW_SR_DATA_NACK: |
46 | PORTB |= (1<<PB0); |
47 | break; |
48 | case TW_SR_STOP: |
49 | PORTB |= (1<<PB0); |
50 | break; |
51 | case TW_NO_INFO: |
52 | PORTB |= (1<<PB0); |
53 | break; |
54 | case TW_BUS_ERROR: |
55 | PORTB |= (1<<PB0); |
56 | break; |
57 | |
58 | default: |
59 | break; |
60 | } |
61 | } |
62 | } |
:
Bearbeitet durch User
Markus E. schrieb: > Also > wird kein anderer Status-Code als 0x60 am Slave mehr zur Verfügung > gestellt. Das Problem an Deinem Code ist, daß das TWSR nur nach der ersten Aktion ausgewertet wird. Ob dazwischen irgendwas schief läuft, kriegst Du daher nicht mit. Du müßtest nach allen Stellen wo auf TWINT gewartet wird, das TWSR auswerten.
Ok, habe TWSR ausgelesen an den relevanten Stellen des Slave, also: twi_read_NACK() --> TWSR = 0xA0 (A STOP condition or repeated START condition has been received while still addressed as Slave) Ok soweit so gut, dann wollte ich gleiches bei twi_write_slave() ausführen, was mir schon gar keinen Status mehr ausgegeben hat.
1 | void twi_write_slave(uint8_t data) |
2 | { |
3 | TWDR = data; |
4 | TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); |
5 | while (!(TWCR & (1<<TWINT))); |
6 | writeDataBCD(TWSR & 0xF8); |
7 | } |
Er betritt wohl die twi_write_slave(100) in der main des Slave gar nicht mehr weil kein Status-Code 0xA8 mehr vorliegt, was wiederum heißen müsste, dass der SLA+R des Master gar nicht erst am Slave verarbeitet wird.
:
Bearbeitet durch User
Nach etlicher Recherche konnte ich mein Problem noch immer nicht lösen. Ähnliche Librarys wie von Peter Fleury nutzen selbiges Prinzip für den TWI jeodch kein wirkliches Repeated Start, da diese dann ein Stop vorher setzen. Vlt. möchte das mal jemand anders an 2 ATMegas testen? :)
:
Bearbeitet durch User
Schließ doch mal einen PCF8574 an. Damit kannst Du testen, ob der Master richtig arbeitet. Ich hab schon ewig nichts mehr mit I2C gemacht. Slave ist richtig aufwendig. Dazu braucht man eine Statemaschine im Interrupthandler. Immer nur den ersten State auszuwerten und sich dann blind weiter zu tasten, erscheint mir zu gewagt.
Ich hatte noch einen PCF8591 herumliegen und habe mal testweise ein Repeated Start abgesetzt und dieses ging normal ein und hat funktioniert. Das Problem liegt also wie du schon sagst am Slave. Na gut, dann trotzdem danke bis hierher, denn weiter weiß ich aktuell auch nicht.
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.