Forum: Mikrocontroller und Digitale Elektronik kein ACK bei TWI/I2C


von JS (Gast)


Lesenswert?

Schönen guten Tag,
ich versuche gerade ein TWI/I2C Verbindung zwischen zwei Atmega8 (16Mhz) 
aufzubauen. Die erfolgreiche Übertragung überprüfe ich durch eine LED. 
Die TWI_Select_Write Funktion wird korrekt ausgeführt. Jedoch erhalte 
ich kein ACK bei der TWI_Write
Funktion.

Schon mal vorab danke.

Master Code:
1
#define I2CADDRESS_SLAVE 0x42
2
3
uint8_t TWI_Start(void)
4
{
5
  TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //Start
6
  while (!(TWCR & (1<<TWINT))); //Warten
7
  return (((TWSR & 0xF8)==0x08) || ((TWSR & 0xF8)==0x10));
8
}
9
10
uint8_t TWI_Select_Read(uint8_t Addr)
11
{
12
  TWDR = (Addr<<1) | 0x01; // Letztes BIt=1
13
  TWCR = (1<<TWINT) | (1<<TWEN); // Senden starten
14
  while (!(TWCR & (1<<TWINT))); //Warten
15
  return((TWSR & 0xF8) == 0x40); // wenn 1 = ok
16
}
17
18
uint8_t TWI_Select_Write(uint8_t Addr)
19
{
20
  TWDR = Addr << 1;
21
  TWCR = (1<< TWINT) | (1<< TWEN); // Senden starten
22
  while(!(TWCR & (1<<TWINT))); //Warten
23
  return((TWSR & 0xF8) == 0x18); //1 wenn ok
24
}
25
26
uint8_t TWI_Write(uint8_t data[], uint8_t length)
27
{
28
  while(length > 0) 
29
  {
30
    length--;
31
    TWDR = *data;
32
    data++;
33
    TWCR = (1<<TWINT) | (1<<TWEN); // Beginne Übertragung
34
     while(!(TWCR & (1<< TWINT))); // Warten 
35
     if((TWSR & 0xF8) != 0x28) 
36
     { 
37
       return (0); // Abbruch
38
     }
39
  }
40
  // ACK empfangen
41
  return (1);
42
}
43
44
void TWI_stop(void)
45
{
46
  TWCR = (1<<TWINT) | (1<< TWEN) | (1<<TWSTO); // STOP
47
}
48
49
int main(void)
50
{
51
// Master  
52
// Ic2 // TWI
53
TWBR=0x0C; // 12
54
TWSR=0x00; // 4^0 TWI
55
// scl= 16.000.000 Hz / (16+2* TWBR * TWI)
56
57
uint8_t Data[10];
58
  
59
  DDRD = (1<< 4);  
60
  
61
    while(1)
62
    {
63
    
64
    TWI_Start();
65
    TWI_Select_Write(I2CADDRESS_SLAVE);
66
        
67
    Data[0]=0x05;
68
    if(TWI_Write(Data,1))
69
    {
70
       PORTD |= (1<<PD4);
71
    }
72
    
73
    
74
    TWI_stop();
75
        
76
    }
77
}

Slave Code
1
int main(void)
2
{
3
// Slave
4
TWAR = (I2CADDRESS_SLAVE<<1);
5
TWCR = (1<< TWINT) | (1<< TWEA) | (1<<TWEN); // Start
6
    
7
  
8
    while(1)
9
    {
10
    
11
    
12
    }
13
}

von D. V. (mazze69)


Lesenswert?

JS schrieb:
> Jedoch erhalte
> ich kein ACK bei der TWI_Write

Warum?

von JS (Gast)


Lesenswert?

@mazze69

Bei der Funktion TWI_Write kriege ich den Rückgabewert 0.
Ich versuche rauszufinden warum.
Ist im code ein Fehler oder habe ich etwas vergessen?
Schöne Grüße,

von Georg G. (df2au)


Lesenswert?

Was sagt denn dein Logik Analysator? Kommt ein ACK und wird nicht 
erkannt?

von Rainer B. (katastrophenheinz)


Lesenswert?

Hi,

alternativ oder zusätzlich zum LSA bitte folgendes prüfen/ausprobieren
1) Gerne vergessen: Pullups an SDA und SCL vorhanden?
2) TWI-Baudrate runtersetzen.
3) Debug-Output einbauen: Sowohl bei Master als auch Slave kompletten 
Inhalt des TWSR ausgeben lassen, und zwar nach jeder Übertragung.

Mit deinen bisherigen Angaben ist lediglich bekannt, daß das TWSR des 
Masters nach dem ersten Datenbyte nicht 0x28 ist. Das ist keine 
ausreichende Grundlage für erfolgreiches Bugfixing.

Gruss, Rainer

von JS (Gast)


Lesenswert?

Danke für den Tipp,
ich habe viele neue Erkenntnisse.
Habe dem Slave einen integer übergeben und dieser ist auch angekommen.
Überprüft durch
1
    *data =TWDR;
2
    if(data[0]==0x05)
3
    {
4
      PORTD |= (1<<PD4);
5
    }

Habe auch eine genauere Fehler Betrachtung durchgeführt. Ok bedeutet, 
dass auf diesen Fall positiv getestet wurde
Beispielsweise:
1
    if((TWSR & 0xF8) == 0x28)
2
    {
3
      PORTD |= (1<<PD4);
4
    }
A START condition has been
transmitted
0x08 = ok


A repeated START condition
has been transmitted
0x10 = ok

SLA+W has been transmitted;
ACK has been received
0x18 = ok

SLA+W has been transmitted;
NOT ACK has been received
0x20 = ok

Data byte has been transmitted;
ACK has been received
0x28 = false

Data byte has been transmitted;
NOT ACK has been received
0x30 = ok

Arbitration lost in SLA+W or data
bytes
0x38 = false

Ich weiß immer noch nicht warum ich kein ACK bekomme, aber es verwundert 
mich das bei SLA+W sowohl ein ACK als auch kein ACK ausgegeben wird.
Schöne Grüße

von Rainer B. (katastrophenheinz)


Lesenswert?

Poste bitte mal den Quelltext, mit dem du jetzt gerade testest ( Master 
und Slave ) Und setzt du denn im Slave überhaupt mal das TWINT-Flag 
zurück (indem du dort eine 1 reinschreibst)?
Guckst du bitte mal AppNote zum Twi-Slave:
http://www.atmel.com/Images/doc2565.pdf

Gruss, Rainer

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
Noch kein Account? Hier anmelden.