Hallo, ich schreib grad die Routinen für ein E2PROM bzw 2 Stück als Bank aber mein ACK Polling funzt nicht, was ich mühsam aufgetüfelt habe und was bei anderen funktionierte. Das sind Atmel E2PROMS und normalerweise polle ich nach einem Schreibzyklus solange mit Write Zugriffen, bis der Stein mit "ACK" antwortet. Dann ist der Zyklus beendet. Es heisst ja auch "Acknowledge Polling". Nur bei dem Teil läuft die Routine in den Timeout :-( Wie ist denn das gemeint, was da steht? Auf dem Bus tut sich nichts wenn ich das Polling laufen lasse. Ich polle auf das Event 6 beim STM32F103. Ersetze ich das Polling durch DelayMs(5) ist alles ok, der Wert steht drin, wird auch ausgelesen aber das ist es ja nicht, Ziel ist ja maximaler Durchsatz. Gruss, Christian
Christian J. schrieb: > Auf dem Bus tut sich nichts wenn ich das Polling > laufen lasse. Dann ist da was kaputt: Da sollte immer die Adresse mit NACK kommen.
So etwa? Bei einem PROM von Microchip 24Lc1025 ist da nämlich anders beschrieben in dem Manual. Allerdings haben die auch "Bank Bits", nur 2 Adressleitungen usw. Hier mal meine Polling Routine, die bei denen von MC funktionierte. Die Schleife rödelt solange bis das E2PROM sich bequemt mit einem ACK zu antworten, d.h. der interne Zyklus ist beendet. So war es bisher immer. Nur was meinen die mit "EEPROM will respond with a 0". Das Teil kann ja nur eine Null senden, wenn der Master weiter clocked. Und das ist bei einer Statemachine wie im Cortex nicht ganz trivial, die hält sich stur an den I2C Stndard. Zum Vergleich mal das Datenblatt eines Microchip Steins gleicher Größe, 512 kBit.
1 | // ---------------------------------------------------------------
|
2 | // Warte bis Schreibzyklus beendet ist (ACK Polling)
|
3 | // ---------------------------------------------------------------
|
4 | static uint8_t e2p_WaitForWriteReady() { |
5 | |
6 | // Warte bis Byte weggeschrieben wurde (Slave sendet solange kein ACK)
|
7 | uint32_t timeout = I2C_TIMEOUT_MAX; |
8 | do{ |
9 | if (--timeout == 0) |
10 | return ERROR; |
11 | /* Erzeuge Schreibzugriff */
|
12 | I2C_GenerateSTART(I2C1, ENABLE); |
13 | while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); |
14 | /* Sende die Write Adresse */
|
15 | I2C_Send7bitAddress(I2C1, E1_WR_ADR, I2C_Direction_Transmitter); |
16 | } while(I2C_WaitForEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); |
17 | |
18 | // Sequenz abschliessen
|
19 | I2C_GenerateSTOP(I2C1, ENABLE); |
20 | |
21 | return SUCCESS; |
22 | }
|
Ok, es klappt .... zumindest die Hardware. Aber meine Auswertung nicht. Bin aber zu müde das heute noch zu ergründen. Die I2C Hardware des STM32 ist ein Brief mit vielen Siegeln bzw ein tiefes Tal der Tränen :-(
Ich verstehe es nicht ! Was kann daran noch falsch sein? Auf dem LA sehe ich eindeutig, dass das EEPROM nach einer Weile von NAK auf ACK wechselt aber die letzte Schleife wird einfach nicht verlassen, obwohl sie das müsste. Es ist nicht möglich die Busy Abfrage vor einem Schreibzugriff zu machen, da die I2C Statemachine des STM32F103 klare Vorgaben erwartet, was sie senden soll und was darauf zurück kommt. Die Events werden nur ausgelöst, wenn die erwartete Antwort kommt. Wenn ein ACK erwartet wurde aber ein NAK kommt wird das Event einfach nicht ausgelöst. Ist da schonmal jemand in die Tiefen dieses I2C Interfaces eingestiegen? Menno...
1 | /* Schreibt ein Byte in eine einzelne Adresse */
|
2 | uint8_t EE_WriteByte(uint16_t adr, uint8_t data) |
3 | {
|
4 | uint8_t lower_addr, upper_addr; |
5 | |
6 | lower_addr = (uint8_t)((0x00FF) & adr); |
7 | adr = adr>>8; |
8 | upper_addr = (uint8_t)((0x00FF) & adr); |
9 | |
10 | // Wait until I2C1 is not busy anymore
|
11 | //while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
|
12 | |
13 | // ACK ein
|
14 | I2C_AcknowledgeConfig(I2C1, ENABLE); |
15 | |
16 | /* Erzeuge START Bedingung */
|
17 | I2C_GenerateSTART(I2C1, ENABLE); |
18 | if (I2C_WaitForEvent(I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS) |
19 | return ERROR; |
20 | |
21 | // Adressiere das E2PROM
|
22 | I2C_Send7bitAddress(I2C1, E1_WR_ADR, I2C_Direction_Transmitter); |
23 | if (I2C_WaitForEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS) |
24 | return ERROR; |
25 | |
26 | // Adresse als 2 x 8 Bit senden
|
27 | I2C_SendData(I2C1,upper_addr); |
28 | if (I2C_WaitForEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS) |
29 | return ERROR; |
30 | |
31 | I2C_SendData(I2C1, lower_addr); |
32 | if (I2C_WaitForEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS) |
33 | return ERROR; |
34 | |
35 | // Sende Datum
|
36 | I2C_SendData(I2C1, data); |
37 | while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)!= SUCCESS); |
38 | |
39 | // Sende I2C3 STOP Condition
|
40 | I2C_GenerateSTOP(I2C1, ENABLE); |
41 | while (I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF)); |
42 | |
43 | /* Warte bis Schreibzyklus beendet wurde */
|
44 | do{ |
45 | /* Erzeuge Schreibzugriff */
|
46 | I2C_GenerateSTART(I2C1, ENABLE); |
47 | while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); |
48 | /* Sende die Write Adresse */
|
49 | I2C_Send7bitAddress(I2C1, E1_WR_ADR, I2C_Direction_Transmitter); |
50 | } while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS); |
51 | |
52 | // Sequenz abschliessen
|
53 | I2C_GenerateSTOP(I2C1, ENABLE); |
54 | |
55 | |
56 | return SUCCESS; |
57 | |
58 | }
|
Ich habs am Laufen! Es stellt sich aber die Frage, ob man bei EEPROM Funktionen den Riesenaufwand treiben sollte allen möglichen Fehler ab zu fangen? Gerade bei dem STM32Fxxxx Controllern gibt es unzählige Fehlerflags usw. Wenn das EEPROM nicht reagiert wie gewünscht bleibt die CPU komplett hängen in den Schleifen und wird erst durch den WDT wieder rausgerissen. Ich glaube das ist für Hobbyanwendungen etwas zu viel da jede Form von Diagnose zu nutzen, da das den Programmcode ganz schön aufbläht.
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.