TWI Repeated Start Probleme

OP #6071316
Lesenswert?

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
Angehängte Dateien:
Gast #6071427
Lesenswert?

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.
#6071896
Lesenswert?

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.
OP #6072296
Lesenswert?

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
    }
OP #6072517
Lesenswert?

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.
OP #6075831
Lesenswert?

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? :)
#6076185
Lesenswert?

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.

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