www.mikrocontroller.net

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


Autor: Dimitri M. (dimitri)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dieter Werner (dds5)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas Lang (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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):
uint8_t i2c_ispresent(uint8_t address)
        {
        uint8_t retval=0;
        i2c_status=I2C_START; //start condition senden
        while(i2c_status); //warten bis START fertig
        i2c_data=address;
        i2c_status=I2C_SEND; //adresse senden
        while(i2c_status); //warten bis fertig
        i2c_data=0;
        i2c_status=I2C_ISACK; //ACK auswerten
        while(i2c_status); //warten bis ack-takt vorbei
        retval= i2c_data;
        i2c_status=I2C_STOP; //stop-condition
        while(i2c_status); //warten
        return retval;
}

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

Autor: Dimitri M. (dimitri)
Datum:

Bewertung
0 lesenswert
nicht 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:
unsigned char ReadExtEEPROMByte(unsigned int address) // 24L04
{
   unsigned char data, temp_control, control, responce;
   
   control = 0b10100000;
   temp_control = (control & 0xF1) | ((address >> 7) & 0x0E);
   
   Send_start();
   Send_byte(temp_control);
   Send_byte((unsigned char)address);
   Send_start();
   Send_byte(temp_control | 0x01);
   Get_b_NACK();
   data = TWDR;
   Send_stop();
   return data;  
}

Auch ein Dankeschoen an Andreas Lang.

/Dimitri

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dimitri M. (dimitri)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dimitri M. (dimitri)
Datum:

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


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.