kein ACK bei TWI/I2C

Gast #3622687
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
}
#3622960
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
Gast #3623525
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

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