Hallo,
ich versuche seit Tagen, eine stabile I2C Kommunikation zwischen eine
PIC16F877 (Master) und einem PIC16F872(Slave) hinzubekommen. Fuer den
Master hab ich die Routinen von www.sprut.de uebernommen und die
Routinen des Slaves sind aus der Application note von Microchip
(http://ww1.microchip.com/downloads/en/AppNotes/00734a.pdf).
Solange kein Overlow auftritt, also der Slaves alles direkt per
Interrupt verarbeiten kann, laueft die Kommunikation ohne Probleme.
Jetzt muss der Slave aber zeitabhängige Messungen machen, darum wuerd
ich gern fuer einen kurzen Moment die Interrupts deaktivieren. In der
Zeit kann dann aber ein Buffer Overflow auftreten. Meine Idee ist, dann
den Master solange das Datenbyte erneut senden zu lassen, bis er wieder
ein ACK vom Slaver erhält. Danach kann er dann wie gewohnt weiter
machen.
Das Problem ist aber jetzt, dass ich durch das loeschen von SSPCON,
SSPOV den Slave nicht dazu bewegen kann, beim naechsten Byte wieder ein
ACK zu senden, d.h. tritt einmal ein Overflow auf, dann bekommt der
Master nie mehr ein ACK zurueck, auch wenn der Slave eigentlich wieder
bereit wäre. Und das obwohl ich wirklich alles schon versucht habe. Im
Datenblatt steht: Das ACK signal wird erzeugt wenn BF=0 und SSPOV=0 ist;
ich lese aber bei Overlflow das SSPBUF Register aus, loesche Damit das
BF Bit, und setze SSPCON, SSPOV = 0. Warum erzeugt der PIC das ACK
Signal danach nicht mehr???
Anbei mein I2C Slave Interrupt Handler.
Hi,
es gibt eine möglichkeit, wie der slave den master am senden neuer daten
hindern kann, ist auch im I2C protokoll festgehalten.
meines wissens nach zieht der slave den takt daueraft low, bis er wieder
bereit ist. das muss der master nat. erkennen und nicht einfach stupide
weiterversuchen zu senden ;) Ist nat auch unpraktisch wenn mehrere
slaves da sind...
Gruß, Marc
Hi,
ja die Möglichkeit kenn ich, aber leider fällt die für mich raus, weil
der Slave unter Umständen nicht direkt in der Lage ist die CLK Leitung
low zu ziehen.
Es kann z.B. sein, dass der Master einen Write Versuch startet, während
der Slave gerade keine Zeit hat. Das SSP Modul des Slaves erzeugt dann
automatisch das ACK, weil der Buffer beim ersten Byte noch nicht voll
ist. Jetzt müsste der Slave CLK auf low ziehen um den Master am Senden
weiterer Bytes zu hindern, das kann er aber nicht, weil er noch nicht
auf das interrupt reagiert hat (er ist ja noch beschäftigt). Der Master
sendet also das zweite Byte und es kommt zum Overflow. Erst jetzt sendet
das SSP Modul vom Slave NOT ACK und der Master kann darauf reagieren.
Sobald ein I2C-Slave eine Aktion erfordert, d.h. einen Interrupt
auslöst, zieht er SCL auf Low, daran kannst Du nichts ändern.
Erst, wenn im Interrupthandler das Flag rückgesetzt wird, kann der
Master weiter machen.
Es kann also nie einen Buffer-Overflow geben, der I2C-Bus synchronisiert
sich immer auf den langsamsten Teilnehmer.
Peter
Das wär schön, wenn dem so wäre. Der PIC macht das aber leider nicht
automatisch. Das entsprechende Flag (SSPCON, CKP) muss per Software auf
0 gesetzt werden um SCL auf Low zu ziehen.
Wenn es nie einen Buffer-Overflow geben kann, warum gibt es dann ein
"receive overflow indicator bit" ?
Ich kenne zwar nur AVR, ARM und 8051-I2C, aber kann mir nicht
vorstellen, daß die das im PIC total vergurkt haben.
Keine CPU kann sicherstellen, daß sie innerhalb 1µs den Interrupthandler
ausführt um den SCL per Software auf low zu ziehen.
Dazu ist ja das I2C in Hardware gegossen, damit das automatisch
geschieht und dann der Interrupt ausgeführt werden kann, wenn Zeit ist.
Ich hab grad keinen DSL-Zugang, um mal ins PIC-Datenblatt zu schauen.
Peter
Das ACK Bit, also das Low ziehen beim 9. Taktimpuls geht automatisch bzw
in Hardware. SDL Low halten, damit der Slave zeit hat die Daten zu
verarbeiten geht nur per software soweit ich das datenblatt verstehe.
So, ich hab mal ins Datenblatt geschaut, der PIC hat tatsächlich nur ein
sehr rudimentäres I2C.
Du mußt die Daten abholen nach dem 9.Takt und vor dem 8.Takt des
nächsten Bytes, ansonsten Pech gehabt.
Da hilft dann nur noch, den Master-Takt runter zu setzen.
Und der Slave muß dem I2C die allerhöchste Priorität geben und darf
nicht viel machen (Daten in SRAM-Puffer schreiben und fertig).
Die Auswertung muß dann im Main erfolgen.
Interrupts länger sperren geht natürlich nicht, oder Du mußt das I2C
vorher komplett abschalten.
Peter