Hallo,
seit einigen Tage komme ich nun leider nicht mehr weiter und hoffe, dass
ihr mir helfen könnt.
Ich habe ein PIC18 Experimentierboard, ein PicKit2 und ein MGC3130 Board
von Microchip.
Mit meinem PIC18 möchte ich gerne die I2C Datenübertragung auf dem
MGC3130 Board mitlesen. Dafür ist auch extra eine I2C Schnittstelle auf
dem Board angebracht.
Hierzu habe ich mit zwei Adern von einem Flachbandkabel, keine 10 cm
lang, das PIC Experimentierboard mit dem MGC3130 Board verbunden.
SCL kommt bei meinem PIC auf den External Interrupt INT0 Pin und SDA
kommt bei meinem PIC auf den External Interrupt INT1 Eingang.
Der Pic18 verfügt zwar über ein I2C Modul, welches ich jedoch bewusst
nicht nutzen möchte, da dann das einfache Mitlesen der I2C Verbindung
wegen der gleichen Slave Adresse, dem R/W Bit und dem ACK Bit nicht so
einfach möglich ist. (Auf dem MGC3130 Board kommuniziert der
MGC3130(Slave) mit einem Master).
Deshalb habe ich die beiden Leitungen auf external Interrupteingänge
gelegt.
Im C - Code passiert bei mir folgendes :
1. INT1 SDA reagiert auf fallende Flanken
2. Warten auf eine fallende Flanke am SDA Eingang
3. Fallende Flanke am SDA Eingang kommt : SCL Pin High ?
4. JA SCL ist High --> Startbedinung.
5. Der INT1 Interrupt wird deaktiviert und INT0 hingegen aktiviert mit
steigender Flanke.
6. Bei jeder SCL steigenden Flanke wird nun SDA auf HIgh oder Low
abgefragt und dementsprechend ein Bit in buffer[20] gesetzt.
7. Nach 20 EInträgen werden alle Interrupts abgeschaltet.
Das Problem ist nun aber, dass ständig falsche Werte in meinem Buffer
stehen. Die I2C Adresse kommt ja nach der Startbedinung als erstes. Die
ist 0x42 also 1000010 aber in meinem Buffer steht bei jedem Versuch
etwas anderes drin ?
Kommt ihr mir bitte weiterhelfen ?
Ich hänge mal meinen C code an und ein Bild, dass ich von meinem Oszi
Gerade zu dem was ich sage nicht ganz sicher, da ich den PIC den du
verwendest nicht kenne, aber:
Laut deinem Code läuft der PIC mit 20 MHz. Bedeutet, der PIC braucht:
(1 / 20MHz) * 4 = 200ns
um einen Befehl auszuführen, welcher einen Maschinenzyklus braucht.
Laut deinem KO Bild sendet dein I2C mit einer Frequenz con 370KHz
(Vermute mal, I2C läuft bei dir im Fast Mode, also 400 KHz?)
Heisst, du kriegst alle:
1 / 400KHz = 2,5 us
eine neue Flanke.
2,5 us / 200ns = 12,5
Heisst, du kannst gerade mal 12 Befehle ausführen, bis die nächste
Flanke eintrifft.
Ich habe sowas wie du hier probierst zwar noch nie gemacht, bin mir auch
absolut nicht sicher über meine Antwort, aber spontan würde ich sagen:
Der PIC ist zu langsam und daran scheitert es.
Vielen Dank, du hast Recht.
Habe das soeben mit meinem Oszilloskop überprüft.
Alleine einen High/Low Pegel abzufragen und diesen anschließend in einem
Buffer zu speichern, dauert auf meinem Controller in C fast 10us.
T.Gxxxx schrieb:> Vielen Dank, du hast Recht.> Habe das soeben mit meinem Oszilloskop überprüft.>> Alleine einen High/Low Pegel abzufragen und diesen anschließend in einem> Buffer zu speichern, dauert auf meinem Controller in C fast 10us.
Hallo,
dein Problem ist nicht, dass der Controller zu langsam wäre, sondern die
Interrupt Latency.
Bevor dein Controller in die ISR geht, muss erst einmal der ganze Käse
aus den Registern weggespeichert werden etc etc. Das dauert. Wie lange
steht im Datenblatt, aber sicher mal >10 Taktzyklen, eher viel mehr.
Zu schaffen ist das trotzdem: Du wirst es vermutlich hinbekommen, wenn
du das Startbit als "Trigger" verwendest und dann in die Empfangsroutine
springst. Den Interrupt muss man dann abschalten.
Wenn du in deiner Empfangsroutine bleibst, schafft der PIC das leicht.
In der Empfangsroutine darfst du dich aber nicht unterbrechen lassen
(Interrupts aus).
Somebody123 schrieb:> Bevor dein Controller in die ISR geht, muss erst einmal der ganze Käse> aus den Registern weggespeichert werden etc etc. Das dauert. Wie lange> steht im Datenblatt, aber sicher mal >10 Taktzyklen, eher viel mehr.
Stimmt. Die Speicherung des Workregisters und des Statusregisters
beanspruchen auch noch einmal ein paar Zyklen für sich, daran habe ich
garnicht mehr gedacht.
Denke aber auch ohne Interrupt wird das ganze sehr schwierig, da ich
denke dass meine Berechnung oben korrekt ist. Wird schon relativ schwer
mit 12 Maschinenzyklen da was anständiges zu schreiben. Denke, in
Assembler würde man es evt. mit einer guten Lösung noch knapp
hinkriegen, in C wohl kaum eine Chance, da der Code wirklich auf ein
Minimum reduziert werden muss..
T.Gxxxx schrieb:> Mit meinem PIC18 möchte ich gerne die I2C Datenübertragung auf dem> MGC3130 Board mitlesen.
Und was soll das ganze? Kann man dafür nicht einfach einen fertigen
I2C-Logger für 10..12€ nehmen, der die Daten auf den PC streamt?
Somebody123 schrieb:> Bevor dein Controller in die ISR geht, muss erst einmal der ganze Käse> aus den Registern weggespeichert werden etc etc. Das dauert.
Das war mal so (Mid-Range-Core). Bei den PIC18er sieht es anders aus:
> 9.9 Context Saving During Interrupts> During interrupts, the return PC address is saved on> the stack. Additionally, the WREG, STATUS and BSR> registers are saved on the Fast Return Stack.
Siehe: 5.1.3 FAST REGISTER STACK