Hallo,
ich habe mich nun 3 Abende lang in die I2C eingearbeitet um sie wirklich
zzu verstehen, da sie erheblich komplexer ist als zb die eines AVR oder
PIC.
Dabei ist es nachfolgende wichtig zu erwähnen, dass ich mit der
StdPeriphLib arbeite, also nicht auf Registerebene, da ich das
unleserlich finde.
Folgende Code habe ich geschrieben bzw aus einer Vorlage umgeschrieben,
der auch funktioniert. Jetzt gilt es zu klären WARUM er funktioniert und
WIE, da einiges eher nach Trial & Error ablief.
Die Routine adressiert ein E2PROM 24LC512 und liest dort genau ein Byte
aus.
Es geht um die Zeilen hier:
1 | // NACK einstellen E2PROM anzuzeigen, dass keine weiteren Daten angefordert sind
|
2 | I2C_AcknowledgeConfig(I2C3, DISABLE);
|
3 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_BYTE_RECEIVED)!=0)
|
4 | return 0xff;
|
5 |
|
6 | // Stop Bedingung erzeugen NACH dem nächsten Lesezugriff
|
7 | I2C_GenerateSTOP(I2C3, ENABLE);
|
8 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_BYTE_RECEIVED)!=0)
|
9 | return 0xff;
|
10 |
|
11 | // Datenbyte auslesen
|
12 | Data = I2C_ReceiveData(I2C3);
|
Das sieht erstmal falsch aus, denn die Reihenfolge ist ja wie im Bild
sichtbar anders. Wieso liest man das Datenbyte aus, NACHDEM man NACK und
STOP gesendet hat? Ich vermute, dass es so ist, dass man die
Statemachine im STM32 so konfiguriert, dass er diese Dinge beim NÄCHSTEN
Buszugriff ausführt, da das Timing ja stimmen muss, die Ereignisse
laufen ja nicht synchron mit der Software ab, sondern werden durch die
Hardware gesteuert.
Jetzt frage ich mich allerdings, wieso die Zeile
if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_BYTE_RECEIVED)!=0)
return 0xff;
da rein muss und nach welchem der Befehle oben wirklich der Buszugriff
ausgeführt wird. D.h. was ist Konfiguration und was ist der Zugriff? Das
Auslesen des datenbytes ist bloss das Lesen eines Registers, das Byte
ist also schon eingetroffen. Aber bei welchem Befehl oben ist das
passiert?
Ich weiss, dass viele nur fertige Libs verwenden, die ja auch
funktionieren aber ich möchte eben genau verstehen wie das so abläuft
:-)
gruss,
Christian
1 | // Hilfsroutine fuer Eventabfrage
|
2 | static uint8_t I2C_WaitForByteTransmitted(uint32_t event)
|
3 | {
|
4 | uint32_t timeout = I2C_TIMEOUT_MAX;
|
5 |
|
6 | while(!I2C_CheckEvent(I2C3, event)) {
|
7 | if ((timeout--) == 0) return 0xFF;
|
8 | }
|
9 | return 0;
|
10 | }
|
11 |
|
12 | // Adresse aus E2PROM lesen
|
13 | uint8_t Read_E2PROM(uint16_t Addr)
|
14 | {
|
15 | uint8_t Data = 0;
|
16 | uint8_t upper_addr,lower_addr;
|
17 |
|
18 | lower_addr = (uint8_t)((0x00FF) & Addr);
|
19 | Addr = Addr>>8;
|
20 | upper_addr = (uint8_t)((0x00FF) & Addr);
|
21 |
|
22 | /* -------- E2PROM Adresszeiger auf Zieladresse setzen ------ */
|
23 |
|
24 | // Erzeuge START Bedingung
|
25 | I2C_GenerateSTART(I2C3, ENABLE);
|
26 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_MODE_SELECT)!=0)
|
27 | return 0xff;
|
28 |
|
29 | // Adressiere das E2PROM
|
30 | I2C_Send7bitAddress(I2C3, MEM_DEVICE_WRITE_ADDR, I2C_Direction_Transmitter);
|
31 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=0)
|
32 | return 0xff;
|
33 |
|
34 | // Adresse als 2 x 8 Bit senden
|
35 | I2C_SendData(I2C3,upper_addr);
|
36 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=0)
|
37 | return 0xff;
|
38 |
|
39 | I2C_SendData(I2C3, lower_addr);
|
40 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=0)
|
41 | return 0xff;
|
42 |
|
43 | // AF Flag evtl löschen
|
44 | I2C3->SR1 |= (uint16_t)0x0400;
|
45 |
|
46 | /* -------- E2PROM Lesemodus (MASTER Receiver Mode)------ */
|
47 |
|
48 | // Erzeuge START Bedingung
|
49 | I2C_GenerateSTART(I2C3, ENABLE);
|
50 | if (I2C_WaitForByteTransmitted( I2C_EVENT_MASTER_MODE_SELECT)!=0)
|
51 | return 0xff;
|
52 |
|
53 | // Adressiere das E2PROM
|
54 | I2C_Send7bitAddress(I2C3, MEM_DEVICE_READ_ADDR, I2C_Direction_Receiver);
|
55 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=0)
|
56 | return 0xff;
|
57 |
|
58 | // NACK einstellen E2PROM anzuzeigen, dass keine weiteren Daten angefordert sind
|
59 | I2C_AcknowledgeConfig(I2C3, DISABLE);
|
60 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_BYTE_RECEIVED)!=0)
|
61 | return 0xff;
|
62 |
|
63 | // Stop Bedingung erzeugen NACH dem nächsten Lesezugriff
|
64 | I2C_GenerateSTOP(I2C3, ENABLE);
|
65 | if (I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_BYTE_RECEIVED)!=0)
|
66 | return 0xff;
|
67 |
|
68 | // Datenbyte auslesen
|
69 | Data = I2C_ReceiveData(I2C3);
|
70 |
|
71 | return Data;
|
72 | }
|