Hallo Eigentlich wollte ich ein kleines OLED-Display mit SSD1306 Controller über den I2C-Bus ansteuern. Da ich aber die I2C Adresse des Displays nicht kenne habe ich es erstmal mit einem I2C EEPROM (24C32)versucht. Dazu aktiviere ich den Bus, sende danach vier Byte an das EEPROM (Adresse mit Schreibwunsch, Adresse im EEPROM high, Adresse im EEPROM low, und zum Schluss ein Datenbyte welches in das EEPROM geschrieben werden soll. Danach gebe ich den Bus wieder frei, lege eine kleine Pause ein und wiederhole das ganze endlos, um es mit dem Oszilloskop kontrollieren zu können. Man sieht deutlich die vier zu übertragenden Byte auf SDA und den Takt auf SCL. Das fatale ist nun, das das Bild genauso aussieht, wenn ich eine falsche EEPROM Adresse sende oder das EEPROM sogar ganz entferne, der I2C-Bus also "offen" ist. Ich vermute das es an meiner Auswertung des Acknowledge liegt, weis aber nich weiter.
Hallo Hier mal eine Routine für das EEPROM 24C02. I2C1_Wr(0xA2) ' send byte via I2C (device address + W) I2C1_Wr(2) ' send byte (address of EEPROM location) I2C1_Wr(0xAA) ' send data (data to be written) I2C1_Stop() ' issue I2C stop signal Delay_100ms() I2C1_Start() ' issue I2C start signal I2C1_Wr(0xA2) ' send byte via I2C (device address + W) I2C1_Wr(2) ' send byte (data address) I2C1_Repeated_Start() ' issue I2C signal repeated start I2C1_Wr(0xA3) ' send byte (device address + R) LATB = I2C1_Rd(0) ' Read the data (NO acknowledge) I2C1_Stop() ' issue I2C stop signal Peter.
Hallo Peter Erstmal Danke für die schnelle Reaktion. Ich habe Deinen Code verstanden. Das ist jedoch nur der Ablauf zum schreiben oder lesen des EEPROMs. Mein Problem ist jedoch warscheinlich die Auswertung des Acknowledge Signals, um zu sehen das der Slave auf dem BUS überhaupt (unter dieser Adresse) existiert. Wie gesagt kann ich eine richtige oder auch eine falsche Adresse senden. Das Oszillogramm sieht immer gleich aus. Wenn ich aber kein Acknowledge vom EEPROM empfange, weil die Adresse falsch ist, müsste das Programm in "I2C_warte" hängen bleiben. Ich werte das Interrupt Flag des I2C Modules des PIC aus. void I2C_warte (void) { while (!SSP1IF) continue; // Warten bis fertig SSP1IF = 0; // Interrupt Flag wieder löschen __delay_us (10); // Test } Wo ist der Wurm drin?
Gast
#6900415
Ohne deinen Quellcode und die Information wie du den SSP1-Interrupt konfiguriert hast, wird dir niemand helfen können zu beurteilen wieso sich das SSP1-InterruptFlag SSP1IF verhält ...
Hallo Test (Gast) Der Interrupt für das I2C-Modul wird garicht konfiguriert und es wird auch kein Interupt ausgelöst bzw abgearbeitet. Es wird nur das Flag ausgewertet.
Gast
#6900487
So wie ich die I2C Implementation beim Pic verstanden habe, wird das SSP1IF Flag immer gesetzt, wenn das Byte versendet und das Ack eingelesen wurde - unabhängig vom Zustand des ACK-Bits. Ob eine positves Ack wmpfangen wurde, sieht man dann im Zustand des ACKSTAT- Bits im SSP1CON2-Register.
Gast
#6900505
Manfred F. schrieb: > Der Interrupt für das I2C-Modul wird garicht konfiguriert PEIE im INTCON sollte gesetzt sein. Anbei meine seit langem funktionierenden I2C-Routinen für den PIC16F1825, zwar in ASM, aber wohl verständlich. Da ASM, müssen ggf. BANK-Befehle gesetzt werden, das macht C ja automatisch.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
Gast
#6900516
Manfred F. schrieb: > Ich vermute das es an meiner Auswertung des Acknowledge liegt, weis aber > nich weiter. Hast du mal überprüft, ob dein Code mit dem Inhalt des DB übereinstimmt?
1 | |
2 | |
Manfred F. schrieb: > Ich vermute das es an meiner Auswertung des Acknowledge liegt, weis aber > nich weiter. WO wertest Du das ACk den aus? Das Result des I2C_write_byte() ignorierst Du ja fleissig. /regards P.S: Bevor Du PICs probierst wäre es evtl sinnvoll erst mal zu lernen, wie man Src-code postet. Ein .png ist da selten sinnvoll, insbesondere wenn es komplizierter wird.
Gast
#6900531
Vielleicht habe ich das Problem nicht ganz verstanden, aber wenn du bei offenem Bus (also ohne EEPROM) das geiche Timing siehst, dann bedeutet dass, das der EEPROM gar kein Acknowledge erzeugt (und der PIC also auch keines auswerten kann). Auf dem Oszi-Bild sieht man Bursts von 9 Takten, der 9. ist dabei der Ack-Impuls, in diesem Takt muss der Slave das SDA-Signal auf Low ziehen. Das ist im Bild nicht so eindeutig zu erkennen, ob das der Fall ist. Triggere mal nur auf einen einzelnen Bust und schaue genau hin, was beim 9. Takt passiert. Btw, die beiden unteren Anschlüsse der Widerstände in deinem Foto berühren sich nicht zufälligerweise?
Andreas H. schrieb: > WO wertest Du das ACk den aus? > Das Result des I2C_write_byte() ignorierst Du ja fleissig. Ach ja. Hatte ich übersehen (dawn .png^^): Deine I2C_write_byte() ist ja auch noch buggy. Nimm lieber Diese, geklaut von https://aticleworld.com/interfacing-eeprom-with-pic-microcontroller-i2c-based/:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
Dann bekommst du Du das ACK Bit als Ergebnis zurück. /regards
Manfred F. schrieb: > Wenn ich aber kein Acknowledge vom EEPROM empfange, weil die Adresse > falsch ist, müsste das Programm in "I2C_warte" hängen bleiben. Das wäre ein schlechter Bus, wenn er hängen bleiben könnte. Er liest ein NACK ein, welches Du auswerten solltest.
Gast
#6901228
Manfred F. schrieb: > I2C_Aufbau.JPG Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen.
Gast
#6901253
reminder schrieb: > Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Aber im Internet steht zu lesen dass man Abblock-Kondensatoren gar nicht braucht weil es auch ohne geht. Und weil die Kondensatoren soviel Geld kosten und soviel mehr Arbeit machen.
Hallo Erstmal Danke an Alle die geholfen haben. McMix schrieb: > So wie ich die I2C Implementation beim Pic verstanden habe, wird das > SSP1IF Flag immer gesetzt, wenn das Byte versendet und das Ack > eingelesen wurde - > unabhängig vom Zustand des ACK-Bits. > Ob eine positves Ack wmpfangen wurde, sieht man dann im Zustand des > ACKSTAT- Bits im SSP1CON2-Register. Ich habe nochmal das DB des PIC studiert. Du hast Recht, Der Empfang des ACK-Bits wird in ACKSTAT abgelegt. Ich habe mein Prog dementsprechend geändert, aber nun hängt es immer wenn ich ACKSTAT auf low überprüfe. Als wenn von Slave (EEPROM) kein Acknowledge gesendet würde. uxdx schrieb: > PEIE im INTCON sollte gesetzt sein. ok, habe ich gemacht, ändert aber nix. > Anbei meine seit langem funktionierenden I2C-Routinen für den > PIC16F1825, zwar in ASM, aber wohl verständlich. Da ASM, müssen ggf. > BANK-Befehle gesetzt werden, das macht C ja automatisch. Danke dafür. Dies entspricht genau meinen C-Routinen. Allerdings kann ich nicht erkennen wo Du das ACK auswertest. genau wie bei mir wertest Du bei jeder Aktion das Interrupt Flag SSPIF aus. Wenn Du mal Dein EEPROM aus der Fassung ziehst müsste das Programm trotzdem weiter laufen, da das SSPIF Flag vom PIC gesetzt wird und Acknowledge nicht geprüft wird. mh schrieb: > Hast du mal überprüft, ob dein Code mit dem Inhalt des DB > übereinstimmt?25.6.6.4 Typical Transmit Sequence ok, habe ich gemacht. EEPROM schreiben entspricht meiner Meinung nach Punkt 25.6.6.4. Andreas H. schrieb: > WO wertest Du das ACk den aus? > Das Result des I2C_write_byte() ignorierst Du ja fleissig. ok, Eine Auswertung des ACK habe ich nun implementiert. Nun hängt das Programm genau dort. > P.S: Bevor Du PICs probierst wäre es evtl sinnvoll erst mal zu lernen, > wie man Src-code postet. Ein .png ist da selten sinnvoll, insbesondere > wenn es komplizierter wird. Ich will mich bessern ;-) Aber wie geht das? reminder schrieb: > Ich muss bei jedem IC ein Abblock-C von VCC nach GND anschliessen. Vorne am Steckbrett sitzt ein 10uF Tantal und ein 100nF Keramikkondi. (Sieht man auf dem Foto nicht) Ich habe nun trotzdem nochmal je IC einen 100nF Keramikkondensator parallel zur Stromversorgung geschaltet (man waren die teuer). Also lange Rede kurzer Sinn: Die Auswertung des Inetrruptflgs klappt einwandfrei. Dann kann ich jedoch das EEPROM aus der Fassung ziehen und es läuft totzdem. Versuche ich ACK auszuwerten bleibt das Prog dort hängen. :-(((
Gast
#6901496
Manfred F. schrieb: > und ein 100nF Keramikkondi. (Sieht man auf dem Foto nicht) Der gehört ja auch ans IC und nicht an den Arsch des Steckbretts.
Manfred F. schrieb: > ok, Eine Auswertung des ACK habe ich nun implementiert. Nun hängt das > Programm genau dort. Warum willst Du es denn dort hängen lassen? Nach einem NACK sendest Du noch ein STOP und meldest der aufrufenden Instanz, daß die Aktion fehlgeschlagen ist. Nach einem Schreiben ist der EEPROM für ~5ms nicht mehr ansprechbar, d.h. dann ist ein NACK korrekt.
Manfred F. schrieb: > Andreas H. schrieb: >> WO wertest Du das ACk den aus? >> Das Result des I2C_write_byte() ignorierst Du ja fleissig. > > ok, Eine Auswertung des ACK habe ich nun implementiert. Nun hängt das > Programm genau dort. > Naja, ohne Code ist das mühseliges Rumraten. Nur falls das noch nicht aufgefallen ist: Das ACK ist **low-activ**, d.h. ein gültiges ACK ist 0V, ein NACK ist 5V (oder was auch immer die benutzte I2C Spannung ist, also da wo die PullUps dranhängen) Manfred F. schrieb: > Andreas H. schrieb: >> P.S: Bevor Du PICs probierst wäre es evtl sinnvoll erst mal zu lernen, >> wie man Src-code postet. Ein .png ist da selten sinnvoll, insbesondere >> wenn es komplizierter wird. > > Ich will mich bessern ;-) > Aber wie geht das? Entweder die Files als Anhang an die Mail dranhängen (da gibts einen Button. Suchen hilft ... ;) oder den Code mit den entsprechenden Tags direkt einfügen. Die Tags findest Du unter https://www.mikrocontroller.net/articles/Formatierung_im_Forum. Peter D. schrieb: > Warum willst Du es denn dort hängen lassen? > Nach einem NACK sendest Du noch ein STOP und meldest der aufrufenden > Instanz, daß die Aktion fehlgeschlagen ist. > Nach einem Schreiben ist der EEPROM für ~5ms nicht mehr ansprechbar, > d.h. dann ist ein NACK korrekt. Das habe ich auch noch nicht verstanden ;) /regards
Hallo, ich habe mir den Code auch mal angesehen. Ich arbeite mit dem XC8. Ich musste an der Stelle vor jedem Write ein I2CIdle(); einbauen, dann lief es. Ich kann Dir meine LIB für den PIC18F46K80 zusenden. Bitte schreibe mir eine PN dann schicke ich Sie Dir zu. Ingo
Ingo S. schrieb: > Hallo, > > ich habe mir den Code auch mal angesehen. Ich arbeite mit dem XC8. > Ich musste an der Stelle vor jedem Write ein I2CIdle(); einbauen, dann > lief es. Ich kann Dir meine LIB für den PIC18F46K80 zusenden. Bitte > schreibe mir eine PN dann schicke ich Sie Dir zu. > > Ingo Hallo Ingo Datei ist angekommen Danke schon mal im Voraus. Habe Heute leider kaum Zeit und schau Morgen mal rein. Schöne Grüße und Dankeschön.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.



