Hallo,
ich habe ein Problem bei meiner Software mit dem I2C-Bus. Das Problem
besteht daraus, dass der I2C- Bus meiner Meinung nach eine Buskollision
verursacht und nach mehreren Kollisionen der I2C-Bus in den IDLE-Modus
geht was durch eine LED angezeigt wird. Die Buskollision treten
bevorzugt dann auf, wenn ein Relais anzieht. Wenn eine Taster gedrückt
wird, bekomme ich keine Buskollision durch die LED angezeigt aber es
bricht die Komplette I2C-Komunikation zusammen. Das Datenblatt des
PIC18F2320 den ich hier für Master und Slave verwende habe ich schon
einige Informationen entnommen aber noch kein Erfolg damit gehabt.
Anbei habe ich den Mastercode und den Slavecode angefügt. Sind hier
vielleicht Fehler vorhanden?
Beim Master erfolgt das Senden bzw Lesen nicht im Interrupt. Beim Slave
jedoch schon.
Vielen Dank schonmal im vorraus für eure hilfreichen Antworten/Tipps.
MASTER-CODE
•
Wie groß sind Deine Pullups?
Es kann sein, daß Störungen auf den I2C einkoppeln und dann der Master
denkt, er hätte die Arbitrierung gegen einen anderen Master verloren.
Da dann keiner ein STOP sendet, bleibt der Bus auf ewig busy.
Eine Lösung ist nur mit einem Timeout möglich. Dann muß man den Master
abschalten und per Bit-Banging ein STOP generieren, bis es Erfolg hat
(bis zu 9 mal).
Einige HW-I2C haben deshalb einen Timer fürs Timeout.
Peter
Danke für die schnellen Antworten.
Meine Pullups sind 4,7 kOhm. Ich habe jetzt mal alle Module aus der
mainloop rausgehauen und nur Senden und Empfangen reingesetzt. Dabei
erhalte ich eine Writecollision was mir dLED1 signalisiert. Das
Display(SLAVE) müsste jetzt StBy anzeigen mit drei Punkten. Jedoch wird
nichts angezeigt jedoch wird 0x02 vom Slave empfangen. Demnach kann ich
ausschließen das es an den Relais lag sondern doch möglicherweiße an
meinem I2C-Syntax. Ich habe anbei nochmal den Master und Slave Code
angefügt mit ISR vllt sieht man wo der Hund im Syntax begraben sein
könnte.
Um eine evtl. aufkommende Frage im vorraus zu beantworten warum in der
Slave ISR so oft das fI2CDATENEMPFANGEN vorkommt: Es hat so funktioniert
das die Daten rechtzeitig abgeholt wurden.
Master
1
// Hier wurde vom Mod unheimlich viel Quelltext gelöscht.
Antwort schreiben
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
----^ !!!
Peter
Danke für die schnellen Antworten.
Meine Pullups sind 4,7 kOhm. Ich habe jetzt mal alle Module aus der
mainloop rausgehauen und nur Senden und Empfangen reingesetzt. Dabei
erhalte ich eine Writecollision was mir dLED1 signalisiert. Das
Display(SLAVE) müsste jetzt StBy anzeigen mit drei Punkten. Jedoch wird
nichts angezeigt jedoch wird 0x02 vom Slave empfangen. Demnach kann ich
ausschließen das es an den Relais lag sondern doch möglicherweiße an
meinem I2C-Syntax. Ich habe anbei nochmal den Master und Slave Code
angefügt mit ISR vllt sieht man wo der Hund im Syntax begraben sein
könnte.
Um eine evtl. aufkommende Frage im vorraus zu beantworten warum in der
Slave ISR so oft das fI2CDATENEMPFANGEN vorkommt: Es hat so funktioniert
das die Daten rechtzeitig abgeholt wurden. Jedoch glaube ich nicht das
diese hinbastelei richtig ist.
Lukas D. schrieb:> erhalte ich eine Writecollision
Ich kenn jetzt Deinen MC nicht.
Aber Writecollision sollte bedeuten, Du schreibst in das Datenregister,
obwohl noch eine oder bereits die nächste I2C-Aktion läuft.
Üblicher Weise hält der I2C an, solange das Interuptflag gesetzt ist.
Das darf also immer erst als letztes gelöscht werden.
Peter
> Ist denn überhaupt ein zweiter Master auf dem I2C vorhanden?
Ein zweiter Master ist nicht vorhanden.
> Aber Writecollision sollte bedeuten, Du schreibst in das Datenregister,>> obwohl noch eine oder bereits die nächste I2C-Aktion läuft.
Ich verwende den PIC18F2320 für Master und Slave. Ja das war im
Datenblatt des PICs ebenso aufgeschrieben. (ab S.185 WCOL STATUS FLAG)
Ich gehe nun davon aus das es an der Slave ISR liegt. Die Daten stehen
dem Slave in einer Taktrate von 100 kHz zur Verfügung. Da sich meine
"Datenabholung" im Timer0 Interrupt befindet ist sie vom auslösen des
Timers abhängig. Befinden sich also gerade Daten im Buffer und das
Interrupt ist aber bereits abgeschlossen und startet neu wird durch die
fI2CDATENSENDEN Funktion wieder auf den Buffer ein Byte geschrieben auch
wenn es nur 0x00 ist. D.h. Ich schreibe in das Datenregister (Buffer)
obwohl noch bzw. bereits eine I2C aktion läuft/vorhanden ist. Dies würde
die Writecollision erklären wenn ich mich da jetzt nicht irre. Ich würde
also jetzt ein MSSP Interrupt für den I2C mit High-Priority einfügen.
Was meint ihr? Würde ein solches Interrup die Uhrzeit irgendwann
verfälschen? Noch eine Frage hätte ich zum Thema Zeit. Wie berechne ich
wie oft der Timer0 hochgezählt wird, dass es möglichst exakt eine
Sekunde ist?
Es wäre schön, wenn Du die Lösung des Problems beschreiben könntest,
damit andere auch etwas davon haben.
Ein "funktioniert jetzt" hilft einem nämlich nicht wirklich weiter, wenn
man diesen Thread nach einer Suche öffnet.
Chris D.
Hallo,
die Lösung habe ich eigentlich oben schon beschrieben. Aber gerne noch
einmal ausführlich.
Mein anfängliches Hauptproblem was ich hatte war eine Writecollision. Da
ich in meiner Software permanent Senden und Empfangen muss und dies
möglichst gleichzeitig.
Da sich meine "Datenabholung" im Timer0 Interrupt befand ist sie vom
auslösen des Timers Overflows abhängig. Befinden sich also gerade Daten
im Buffer und das Interrupt ist aber bereits abgeschlossen und startet
neu wird durch die fI2CDATENSENDEN Funktion wieder auf den Buffer ein
Byte geschrieben auch wenn es nur 0x00 ist. D.h. Ich schreibe in das
Datenregister (Buffer) obwohl noch bzw. bereits eine I2C aktion
läuft/vorhanden ist.
Somit habe ich jetzt eine MSSP ISR im SLAVE eingefügt mit niedriger
priorität in der sich die "Datensenden an Master" und "Datenempfangen
vom Master" Funktion befindet. Folglich erhält man eine saubere I2C
Funktion ohne sechs mal die gleiche Funktion im Timer0 interrupt
aufrufen. Mein Slave besteht aus einem PIC18 und einer 4x7
Segmentanzeige die über den I2C-Bus gemultiplext wird.
Wenn man jetzt noch mit dem MSSP Interrupt im Master arbeitet und dort
die Daten vom Slave lesen Funktion reinschreibt kann man gleichzeitig
senden und emfpangen. Jedoch habe ich gemerkt, dass das ungeeignet für
das multiplexen des Displays ist. Möglich ist das man den Bustakt
beschläunigt und den Slave auf einer anderen Taktfrequenz laufen lässt
dann muss aber noch die Clock synchronisiert werden. Mal sehen.
Das ist gerade mein Hauptquest was ich versuche in den griff zu bekommen
damit die Lesefunktion des Masters das multiplexen des Displays nicht
beeinflusst. Falls dazu jemand Tipps hat dann her damit ansonsten fals
noch Fragen offen sind kann ich die gerne beantworten.
Weiterhin habe ich immer noch offene fragen wie:
Wie berechne ich wie oft der Timer0 hochgezählt wird, sodass möglichst
exakt eine Sekunde dabei herauskommt?
Cheers