Forum: Mikrocontroller und Digitale Elektronik STM32 Prüfen ob I2C Slave am Bus hängt


von af (Gast)


Lesenswert?

Wie prüft man richtig, ob ein angesprochener Slave die vom Master 
ausgehende Adressierung mit ACK oder NACK quittiert hat?

Hintergrund ist ein EEPROM, der sich vom Bus komplett trennt, wenn er 
Daten empfangen hat. Eine Feste Wartezeit zwischen den Zugriffen möchte 
ich vermeiden.

>Minimizing System Delays by Polling On ACK
>During the internal Write cycle, the device
> discon-nects itself from the bus, and writes a copy of the
>data from its internal latches to the memory cells.
1
void 
2
eeprom_wait_for_ready (void) {
3
    do
4
    {
5
      /* While the bus is busy */
6
    while(I2C_GetFlagStatus(I2C_SELECTED, I2C_FLAG_BUSY));
7
8
    /* Send START condition */
9
    I2C_GenerateSTART(I2C_SELECTED, ENABLE);
10
    printf("generate start");
11
    /* Test on EV5 and clear it */
12
    while(!I2C_CheckEvent(I2C_SELECTED, I2C_EVENT_MASTER_MODE_SELECT));
13
14
    /* Sent slave address for write */
15
    I2C_Send7bitAddress(I2C_SELECTED, EEPROM_I2C_ADDR, I2C_Direction_Receiver);
16
    printf("send address..");
17
18
19
    } while(!I2C_CheckEvent(I2C_SELECTED, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
20
}

Vielen Dank für jede Anregung.
von af (Gast)


Lesenswert?

Ist noch nie jemand mit dem Problem konfrontiert worden, einen Slave 
erst auf das "Vorhandensein" prüfen zu müssen? Beim AVR geht es noch 
auch, da hat es gereicht nach dem Senden der Adresse auf ACK zu 
prüfen...
von Jan H. (jan_h74) Flattr this


Lesenswert?

Ich habe so etwas ahnlich geschrieben. Wichtig : die pull-up 
Wiederstande mussen functionieren, oder er bleibt irgendwo hangen 
Program. Das ist hier wirklich "quick und dirty" Slave_Read() sendet 
eine 7 bit adresse, wen ACK komt wird das in eine variabele gesetzt, LED 
leuchtet. GPIO und Clocks mussen naturlich auch noch configuriert 
werden. An pin C9 hangt die LED (Discovery VL board).
1
 /* I2C2 configuration ------------------------------------------------------*/
2
 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
3
 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
4
 I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS7;
5
 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
6
 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
7
 I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
8
 I2C_Init(I2C2, &I2C_InitStructure);
9
  /* Enable I2C2  ----------------------------------------------------*/
10
 I2C_Cmd(I2C2, ENABLE);
11
/*Now some very simple code that test a Slave adresses. If the slave answer, the adress is written in a global variable */
12
13
 void Slave_Read (uint8_t Slave)
14
 {
15
 I2C_GenerateSTART(I2C2, ENABLE);// Send START condition 
16
 while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));//Test on EV5 and clear it   
17
 I2C_Send7bitAddress(I2C2,Slave, I2C_Direction_Transmitter);// Send Slave address for write
18
 delay(2); //wait for ack from slave
19
 if(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//Test on EV6 and clear it
20
 {GPIOC->BSRR = 1<<9 ;Data[6]=(Slave-1);}// Disable Acknowledgement
21
 else  {GPIOC->BSRR = 1<<25 ; } 
22
 I2C_GenerateSTOP(I2C2, ENABLE);// Send STOP condition    
23
 }
von Heinz (Gast)


Lesenswert?

af schrieb:
> Wie prüft man richtig, ob ein angesprochener Slave die vom Master
> ausgehende Adressierung mit ACK oder NACK quittiert hat?
Mit einem Logic Analyzer???
von af (Gast)


Lesenswert?

@ Heinz
danke, aber mir geht's um die Softwarerealisierung.

@ Jan H.
und das tut mein STM32 eben nicht. Auf dem STM3210C Eval Board sind 4k7 
Pullups dran. EEprom trennt sich dem Datenblatt nach vom Bus, wenn er 
die gepufferten Daten schreibt. Also kann der die Leitungen nicht auf 
Low halten. Demnach muss man beim nächsten Zugriff auf EEProm die 
Adresse senden ung gucken, ob ein ACK kommt oder nicht. Beim Atmega war 
das ganz einfach sowas wie:

do {

} while (!i2c_start(0xA0))

Und diese Zeilen verursachen halt eine endlose Schleife, wenn der Slave 
nicht mit ACk antwortet:
1
I2C_Send7bitAddress(I2C_SELECTED, EEPROM_I2C_ADDR, I2C_Direction_Receiver);
2
while (!I2C_CheckEvent(I2C_SELECTED,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
von (prx) A. K. (prx)


Lesenswert?

Nu gibts im Register extra ein Bit um genau das anzuzeigen und dass du 
das Bit nicht kennst ist angesichts deines Nics geradezu komisch. ;-)
von af (Gast)


Lesenswert?

Habe es mir angeschaut und ausprobiert. Lief positiv ab, jetzt aber 
plötzlich gibt es Probleme mit dem EEPROM zu kommunizieren. Hat der STM 
irgendwelche Register, sodass nach dem DeInit und Stromreset die Werte 
beibehalten werden? Irgendwie läuft der Code was zuvor funktioniert hat 
gar nicht mehr....
von af (Gast)


Angehängte Dateien:

Lesenswert?

Könnte vielleicht jemand die angehängte Funktionen auf einem STM3210C 
Board ausprobieren?
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.