Hallo zusammen. Ich bin dabei eine Kommunikation von 2 PICs über I²C zu
realisieren. Da ich erstmal mit I²C selber klarkommen will, will ich
erstmal etwas in ein I²C-EEPROM schreiben und auslesen. Hierfür benutze
ich einen PIC16F1937 bei 8MHz internen Takt und 4xPLL:
Das funktioniert so nicht bzw. die LEDs, die an PORTD hängen zeigen
nichts an. Also hab ich zwischendurch eine "Debug"-Ausgabe gemacht:
1
while(!button1);
2
delay_ms(20);
3
while(button1);
4
5
I2C1_Start();
6
I2C1_Wr(0b10100100);
7
I2C1_Wr(0);
8
I2C1_Wr(0);
9
I2C1_Wr(0b00001010);
10
I2C1_Stop();
11
PORTD=0x0F;
12
13
while(!button1);
14
delay_ms(20);
15
while(button1);
16
17
I2C1_Start();
18
I2C1_Wr(0b10100100);
19
I2C1_Wr(0);
20
I2C1_Wr(0);
21
I2C1_Repeated_Start();
22
I2C1_Wr(0b10100101);
23
PORTD=I2C1_Rd(0);
24
I2C1_Stop();
und dort hab ich dann gesehen, dass die LEDs nichtmal die 0x0F
ausgegeben haben. Also hab ich den Code solange reduziert, bis die LEDs
angingen:
1
while(!button1);
2
delay_ms(20);
3
while(button1);
4
5
I2C1_Start();
6
I2C1_Wr(0b10100100);
7
//I2C1_Wr(0);
8
//I2C1_Wr(0);
9
//I2C1_Wr(0b00001010);
10
I2C1_Stop();
11
PORTD=0x0F;
12
13
while(!button1);
14
delay_ms(20);
15
while(button1);
16
17
/*I2C1_Start();
18
I2C1_Wr(0b10100100);
19
I2C1_Wr(0);
20
I2C1_Wr(0);
21
I2C1_Repeated_Start();
22
I2C1_Wr(0b10100101);
23
PORTD = I2C1_Rd(0);
24
I2C1_Stop();*/
Doch wenn ich dann das erste "I2C1_Wr(0);" wieder reinnehme, bzw die
"//" davor lösche, dass es nicht mehr auskommentiert ist, gehen die LEDs
nicht mehr an. Da frage ich mich, warum das so ist und mir ist beim
besten Willen nichts eingefallen. Hängt sich der PIC auf, wenn er vom
EEPROM nichts mitbekommt? Anderer Seits soll er ja auch nur schreiben
und es ist ja auch nicht sehr klug, dass das Programm abstürzt, nur weil
ein Slave nicht erreicht wird/werden sollte. Es hängt schon ein EEPROM
dran und sollte eigentlich so auch funktionieren.
Kann mir da jemand helfen?
Ja will ich auch. Ich hab mir gedacht, damit ich Prüfen kann, was ich
ins EEPROM schreibe ( "I2C1_Wr(0b00001010);" ), lese ich es aus und geb
es an PORTD aus, wo die LEDs hinter hängen ( "PORTD = I2C1_Rd(0);" ).
edit:
> Das funktioniert so nicht bzw. die LEDs, die an PORTD hängen zeigen> nichts an.
Ich habs am Anfang nicht gleich gesagt. Also am PORTD hängen LEDs dran,
die bei High leuchten.
Das EEPROM ist ein 24FC1025, auch von Microchip.
Angehängt auch mal den auf die Schnelle gemachten Schaltplan. Jedoch
funktioniert es ja soweit, dass wenn ich den Taster drücke und loslasse
die 4 LEDs leuchten (solange das //I2C1_Wr(0); auskommentiert ist).
Das Problem ist halt, wenn 2 mal "I2C1_Wr();" hintereinander kommen hab
ich das Gefühl.
Benutzen tu ich mikroC for PIC 4.60. Ich hab es auch einmal mit der 5.40
Version compiliert, ist aber das gleiche. Sobald ich ein zweiter I2C1_Wr
benutze, bleibt das Programm wohl hängen und die LEDs bleiben alle aus.
Ich hab auch schonmal mit "I2C1_Is_Idle" geprüft, ob durch irgendwas der
Bus "in Benutzung" ist, das ist jedoch nicht der Fall.
Also laut Datenblatt nicht:
http://ww1.microchip.com/downloads/en/DeviceDoc/21941J.pdf
Seite 8:
Startbit, 1010, Block Select Bit, A1, A0, R/W, ACK.
Der A2 Pin muss auf Vcc liegen, da offen oder auf GND einen
undefinierten Zustand hervor ruft.
Aber was ich mich frage, selbst wenn die Adresse falsch wäre, der EEPROM
kaputt wäre oder auch wenn garkein EEPROM oder anderer Slave am Bus ist,
wieso geht das Programm nicht weiter.
Wenn z.B. durch was auch immer die Leitung zum EEPROM gestört oder
kaputt ist oder der EEPROM durch was auch immer defekt ist, dann kann
doch nicht das Programm abschmieren!?
Mein Verdacht liegt daran, dass das evtl ein Fehler von der
Compilerseite ist. Doch die Funktion I2C1_Wr geht ja ansich, wenn sie
nur einmal da steht.
Naja, wie gesagt, ich bin ratlos.
Aber so hab ich das doch. Ich hab A0 auf low und A1 auf high, deswegen
ist bei mir das Commandbyte nicht 0xA2 sondern 0xA4. Und ich schreib in
Adresse 0 und nicht in Adresse 2. Das init ist in der init-Funktion und
was für Daten ich schreibe sollte ja egal sein. Doch, und korrigiert
mich bitte, wenn ich falsch liege, darf doch das Programm nicht
abstürzen, nur weil ein Slave am Bus nicht antwortet (da Leitung defekt
oder falsch adressiert o.ä.)!?
Laut deinem Schaltplan hast du A0 auf LOW, A1 UND A2 auf HIGH.
Also lauten die beiden Adressen:
b'10101100' = 0xAC
b'10101101' = 0xAD
^----R/W
^-----A0
^------A1
^-------A2
Sehe gerade an denBeispielen im Datenblatt wird A2 immer als "0"
behandelt.
Das ergäbe dann die Adressen:
b'10100100' = 0xA4
b'10100101' = 0xA5
^----R/W
^-----A0
^------A1
^-------A2
nein. Im datenblatt steht, das A2 high sein muss und beim Adressieren
1010 und dann der Block gewählt wird. Also als wären in dem 1024k
Speicher 2 512k Speicher drin, einmal mit "A2" auf 0 und einmal auf 1.
Doch nochmals: Wieso kackt das Programm ab? Selbst wenn die Adresse
falsch ist darf das doch nicht passieren. Ein Riss auf der Leiterbahn
vom I2C und schon kann das ganze System nicht mehr funktionieren? Das
kann doch nicht sein.
Michael Skropski schrieb:> Doch nochmals: Wieso kackt das Programm ab? Selbst wenn die Adresse> falsch ist darf das doch nicht passieren. Ein Riss auf der Leiterbahn> vom I2C und schon kann das ganze System nicht mehr funktionieren? Das> kann doch nicht sein.
Das ist so, weil du es so programmierst. Die Routine hat keinen timeout.
Woher soll Sie auch wissen ob du das willst und wie Sie den
bewerkstelligen soll?
Das Programm wird auch noch laufen, es kann sein das es auf das Ende der
letzten I2C Operation wartet.
Schau dir mal die I2C Register an ob die Daten wirklich gesendet
wurden, vermutlich kommt kein ACK vom EEprom.
Boa ich Trottel-.- Ich hab von der Datenleitung den Pullup-Widerstand
nicht festgelötet...
Doch ich werd mir wohl eigene Funktionen bauen. Wenn sowas durch eine
kalte Lötstelle oder so nochmal passiert, soll mein Programm trotzdem
laufen und einen Error anzeigen oder sonstwas.
Dennoch danke an alle. Mein Programm hat soweit auch auf Anhieb
Funktioniert.