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