Forum: Mikrocontroller und Digitale Elektronik Wieder eine "I2C-Device-Detect"-Frage


von Dimitri M. (dimitri)


Lesenswert?

Hallo Leute,

der I2C-Bus hat es in sich. Waehrend man z.B. ueber SPI unbestraft Daten 
ins Leere schicken kann, kommt es bei I2C schnell zum Haenger, wenn eine 
Adresse angesprochen wird, wo nichts dahinten ist.

Gibt es eine Methode fuer den Master zuerst abzuchecken, welche 
I2C-Adressen ansprechbar sind, sprich dran haengt auch was? Geht das 
auch ohne Timeout?

Gruss
Dimitri

von Dieter W. (dds5)


Lesenswert?

Wenn man ein I2C Slave ansprechen will, muss ja nach dem START als 
erstes die (7 oder 10 Bit) Slaveadresse kommen. Wenn dabei kein ACK 
empfangen wird, ist halt kein Slave vorhanden um zu antworten - da 
braucht's kein Timeout.

Wichtig ist, dass dann der Master ein STOP ausgibt, da sonst andere 
Bausteine am Bus verwirrt werden könnten.

von Andreas Lang (Gast)


Lesenswert?

Moin,

wenn ein slave-device da ist, gibt es brav einen ACK zurück. Da ein 
slave, wenn es ihn nicht gibt, kein clockstretching machen kann, braucht 
man eigentlich mit sinnvoller taktfrequenz eine startsequenz mit 
nachfolgender busadresse (im read-mode) auf den bus zu setzen. Wenn sich 
dann im ACK-Clock nix rührt, ist da auch nix angeschlossen. Sowas wie 
"warten auf Ack" muss  man dann natürlich deaktivieren.

Wenn man es geschickt anstellt kann man mit passenden tests sogar die 
größe zB eines angeschlossenen EEPROMs bestimmen (hab das schonmal 
irgendwo gebraucht).

sah bei mir damals (mit software I²C) so aus (sollte aber eigentlich 
klar sein):
1
uint8_t i2c_ispresent(uint8_t address)
2
        {
3
        uint8_t retval=0;
4
        i2c_status=I2C_START; //start condition senden
5
        while(i2c_status); //warten bis START fertig
6
        i2c_data=address;
7
        i2c_status=I2C_SEND; //adresse senden
8
        while(i2c_status); //warten bis fertig
9
        i2c_data=0;
10
        i2c_status=I2C_ISACK; //ACK auswerten
11
        while(i2c_status); //warten bis ack-takt vorbei
12
        retval= i2c_data;
13
        i2c_status=I2C_STOP; //stop-condition
14
        while(i2c_status); //warten
15
        return retval;
16
}

Der Software-I2C hatte kein warten auf ACK, nur clockstretching war 
vorgesehen.

von Dimitri M. (dimitri)


Lesenswert?

Dieter Werner wrote:
> Wenn man ein I2C Slave ansprechen will, muss ja nach dem START als
> erstes die (7 oder 10 Bit) Slaveadresse kommen. Wenn dabei kein ACK
> empfangen wird, ist halt kein Slave vorhanden um zu antworten - da
> braucht's kein Timeout.
>
> Wichtig ist, dass dann der Master ein STOP ausgibt, da sonst andere
> Bausteine am Bus verwirrt werden könnten.

Das klingt gut.

Im Falle 24C04 braucht es 2 Bytes, um das EEPROM anzusprechen. Die 
Device-Adresse ist so ueber beide Byte verteilt. Soll das nun heissen, 
dass ich nach dem 1. Byte nichts zu erwarten habe und dass ein ACK erst 
kommt, wenn die ganze Adresse vom Slave geschluckt ist?

Dieser Code laeuft so weit:
1
unsigned char ReadExtEEPROMByte(unsigned int address) // 24L04
2
{
3
   unsigned char data, temp_control, control, responce;
4
   
5
   control = 0b10100000;
6
   temp_control = (control & 0xF1) | ((address >> 7) & 0x0E);
7
   
8
   Send_start();
9
   Send_byte(temp_control);
10
   Send_byte((unsigned char)address);
11
   Send_start();
12
   Send_byte(temp_control | 0x01);
13
   Get_b_NACK();
14
   data = TWDR;
15
   Send_stop();
16
   return data;  
17
}

Auch ein Dankeschoen an Andreas Lang.

/Dimitri

von Peter D. (peda)


Lesenswert?

Dimitri M. wrote:
> der I2C-Bus hat es in sich. Waehrend man z.B. ueber SPI unbestraft Daten
> ins Leere schicken kann, kommt es bei I2C schnell zum Haenger, wenn eine
> Adresse angesprochen wird, wo nichts dahinten ist.

Das muß dann an Deinen komischen I2C-Routinen liegen.
Beim I2C hängt nichts, wenn kein Slave adressiert wird, Du kriegst nur 
ein NACK zurück.


Peter

von Dimitri M. (dimitri)


Lesenswert?

Peter Dannegger wrote:
>
> Das muß dann an Deinen komischen I2C-Routinen liegen.
> Beim I2C hängt nichts, wenn kein Slave adressiert wird, Du kriegst nur
> ein NACK zurück.
>
>
> Peter

Absolut! Ich sehe nun ein, dass ich nach jedem I2C-Befehl, der von mir 
zum EEPROM geschickt wird, den TWSR-Register checken soll. Es ist immer 
noch die "geerbte" Software, die es bitter noetig hat, ausgemistet zu 
werden.

von Dimitri M. (dimitri)


Lesenswert?

Ich danke allen, die geholfen haben. So geht's fuer Addr = 0x00
1
#define  MTX_ADR_ACK    0x18
2
void CheckEEPROM(void)
3
{
4
  Send_start();
5
  if(Send_byte(0b10100000) == MTX_ADR_ACK) UARTPutString("EEPROM found\r\n");;
6
  Send_stop();
7
}

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.