Hallo,
vielleicht könnt ihr mir helfen. So langsam bin ich mit meinem Latein am
Ende.
Beim lesen der einzelen Bit eines CMPS03 Kompass Sensors bekomme ich
immer high, ergo 0xFF als Wert.
Die Routine ist aus dem Keil Buch von Baldischweiler. Prozessor ist ein.
8051, Compiler ist Keil C51.
Im Protokollanalyzer (Intronix Logicport)stimmt alles, es kommen auch
Werte vom Sensor auf dem Bus. (siehe Anhang)
Also Adressierung stimmt.
Anderer Sensor und anderer Prozessor bringen das gleiche.
Ich hab echt keine Ideen mehr.
Wäre nett wenn euch was einfällt.
DANKE
Code der Leseroutine:
/*
***************************************************
*
* I2C Library
*
* For Keil C, with features of bus fault
* detection, no acknowledgement feature,
* and I2C busy feature.
****************************************************
*/
uchar Si2c_in( bit btACK )
{
I2CWAIT2;
SSDA = 1; // Freigabe vom BUS
SSCL = 1; I2CWAIT3;
sbtD7 = SSDA; // Lesen des Bit 7 (MSB)
SSCL = 0; I2CWAIT4;
SSCL = 1; I2CWAIT3;
sbtD6 = SSDA; // Lesen des Bit 6
SSCL = 0; I2CWAIT4;
SSCL = 1; I2CWAIT3;
sbtD5 = SSDA; // Lesen des Bit 5
SSCL = 0; I2CWAIT4;
SSCL = 1; I2CWAIT3;
sbtD4 = SSDA; // Lesen des Bit 4
SSCL = 0; I2CWAIT4;
SSCL = 1; I2CWAIT3;
sbtD3 = SSDA; // Lesen des Bit 3
SSCL = 0; I2CWAIT4;
SSCL = 1; I2CWAIT3;
sbtD2 = SSDA; // Lesen des Bit 2
SSCL = 0; I2CWAIT4;
SSCL = 1; I2CWAIT3;
sbtD1 = SSDA; // Lesen des Bit 1
SSCL = 0; I2CWAIT4;
SSCL = 1; I2CWAIT3;
sbtD0 = SSDA; // Lesen des Bit 0 (LSB)
SSCL = 0; I2CWAIT4;
SSDA = btACK; // ACK/NACK vom Master
SSCL = 1; I2CWAIT3; // ACK-Takt
SSCL = 0; I2CWAIT4;
return(ucI2CVal);
}
hm
Hier ist timing extrem wichtig im Zweifel länger warten(langsamer
takten).
Am besten Signalsequenzen kontrollieren.
Das du zuvor die richtige Adresse senden und vielleicht noch ein
register setzen musst ist dir bekannt?
Hast du die Initsequenz des Kompasschips durchgezogen?
Du mußt schon die komplette I2C-Sequenz posten, nicht nur einen Brocken
einfach so hinwerfen.
Hier mal ein Beispielcode:
http://home.tiscali.de/peterd/appl/soft/c51/eeprom/index.htm
Peter
P.S.:
Man darf unter C auch Schleifen verwenden.
Copy&Paste-Code hat die Eigenschaft, sehr fehleranfällig zu sein. Und
speicherfressend ist er sowieso.
Hallo Peter,
ich vermute, dass der PIN immer high ist,und das Problem nicht in der
eigentlichen I2C Geschichte liegt und hab mein Posting daher auf die
vermutete Fehlerquelle beschränkt. Beim 8051 kann der PIN doch gelesen
und geschrieben werden ?
Bzgl. Schleife, hat mich bei den NOPS im Quellcode auch gestört und hab
das Cut&Paste dort auch schon ersetzt. Ich geb zu, dein Code ist da
eleganter als der vom Kollegen :)
Hallo,
das mit dem Dateinanhang hat wohl nicht geklappt. Ich beziehe mich die
ganze Zeit auf das hochgeladene Protokoll vom Analayzer und sehe gerade,
da ist nichts. (Bitte den Dateianhang vor dem Absenden noch einmal
auswählen! - werlesen kann hat Vorteile). Ich hängs nochmal an.
Timing nochmal prüfen.
Dein µC ist eine 2-State-Maschine, also ein Turbo-8051. Der ist 6x
schneller als ein Klassik. Das hast Du hoffentlich bedacht. Die 16MHz
wären dann einer Taktfrequenz von 96MHz gleichzusetzen.
> for(i=0; i<nops ;i++) // o,4uS = 1 NOP
0.4us würde dann nicht stimmen, sondern 0,125us pro NOP
Die Impulsbreite beträgt 5,5 uSec (siehe auch Hardcopy Analyzer),
absichtlich schon etwas über der 4,7 uSec Spec. Stimmt die 0,4 für ein
einzelnes NOP im REM sind falsch.
Der Sensor versteht ja auch meine gesendeten Daten und liefert mir laut
Analyzer die korrekten Daten zurück. Nur der der SDA Pin der ja beim
Schreiben auch korrekt arbeitet liefert beim Lesen einfach nur immer
High.
Stimmt der Pegel evtl. für den Prozessorpin nicht ? Aber für den
Analyzer ist die Schwelle ja auch okay ?
Die Ports sind bei allen 8051 ja problemlos und ohne zutun
bidirektional, oder habe ich da was übersehen ?
RATLOS !
> Die Ports sind bei allen 8051 ja problemlos und ohne zutun> bidirektional, oder habe ich da was übersehen ?
Nicht ganz. Beim Klassik-8051 musst Du um was von einen PIN einzulesen
vorher das Ausgangslatch auch 1 setzen. Sonst liest Du immer 0.
SDA = 1; // Portlatch vor lesen auf 1 setzen
input = SDA; //liest nun 1 oder 0, jenachmdem was am PIN anliegt
Bei solch speziellen µC wie Du hast kann das aber anders sein. Da musst
Du genauestens das Datenblatt lesen. Bei der 2Cycle 8051-Serie P89LPC9xx
von NXP muß man z.B. auch vorher festlegen, ob der Portpin Ein- oder
Ausgang sein soll.
Ansonsten nimm mal eine normale Varibale beim Einlesen, oder hier meine
Routine: