Hallo, ich befasse mich in den letzten Tagen mehr oder weniger erfolgreich mit der MSP430 Plattform, nachdem ich zunächst nur ATmegas benutzt habe. Hintergrund ist der, dass ich mit einem µC einen ADXL345 Sensor ansprechen/testen möchte, der nur 3.3V verträgt, und ich es nicht hingekriegt habe, mit einem ATmega8 mit diesem zu kommunizieren. Um auszuschließen, dass es an der 5V->3.3V Konverter-Schaltung lag, die ich im Internet gefunden hatte, habe ich mir gedacht: Versuche ich das einfach mal mit dem MSP430FG4016 vom dem Experimenters Board. Zunächst wollte ich die Ansprache mittels SPI versuchen (Siehe dazu auch Beitrag "MSP430FG4618/2013 Experimenters Board - Anfängerfrage"). Hat leider nicht so recht geklappt, weil der Sensor sehr seltsam reagierte. Nun habe ich mich heute an i2c versucht. Leider bin ich hier auch nicht sehr erfolgreich gewesen: Zwar war Erfolg insofern da, dass ich a) Die ID des Sensors erfolgreich auslesen konnte, b) ich ihn in den Measurement Modus schicken konnte. Heißt also, der Sensor scheint doch nicht hin zu sein, auch wenn die Kommunikation via SPI irgendwie gar nicht geklappt hatte. Aber: Ich habe immer wieder Hänger in der Kommuniation gehabt, die es nötig machten, dass ich entweder den Sensor power-toggeln mußte oder den µC, sprich: irgendwas stimmt da noch nicht, aber ich kann nicht mit Bestimmtheit sagen, ob der Sensor doch wirklich nen Hau hat oder ob mein USCI Code nicht passt... - ich vermute letzteres. Den Code um den Sensor via i2c anzusprechen habe ich aus verschiedenen Quellen: a) Aus den TI Code samples (msp430xG46x_uscib0_i2c_0x) - keines der Beispiele scheint sich aber mit dem "Spezialfall" der Ansprache eines Sensors zu beschäftigen, wo ich ein Write an den Sensor mache um ein Register zu selektieren und danach davon lese. b) Aus anderen Artikeln hier im Forum (der Code von dort hat dann zumindest funktioniert, wenn auch nur R/W mit 1 Byte) c) Aus der TI "Using the USCI i2c Master" (SLAA382) Doku (http://focus.ti.com/general/docs/litabsmultiplefilelist.tsp?literatureNumber=slaa382) Ich habe das Verhalten mit einem Oszi an SCL und SDA beobachtet. Mir ist aufgefallen, dass immer wenn das Programm hängt, dann SCL low bleibt, anstatt wieder high zu werden. Ob jetzt da die richtigen Stop-Bits auf der Leitung waren, kann ich anhand der Darstellung im Oszi leider nicht sehen. Woanders habe ich dann gelesen, dass das mit den Pullup-Widerständen zu tun haben könnte. Ich habe mich an die TI-Beispiele gehalten, wo immer die Rede von 10k Widerständen ist, habe dann aber gelesen, dass bei 3.3V deutlich geringere Werte möglich/sinnvoll sind. Bin zuletzt über 4.7k bis auf 2.2k runter, aber auch dies hat keine Verbesserung gebracht. >> Welche Werte soll ich denn nun konkret einsetzen? Ich habe nur diesen Sensor im i2c Netz, er ist auf einem Breadboard mit eigener 3.3V Stromversorgung und die Leitung ist ca. 20cm bis zum µC. Ich setze keine Interrupts im Code ein, somit sollte auch ein "zufälliges" Falschverhalten ausgeschlossen werden können, je nach Timing. Ich habe schon verschiedene Prescaler beim Initialisieren des i2c USCI getestet um die Taktrate anzupassen, auch dies hat keine Besserung gebracht. Ich würde mich freuen, wenn mal jemand einen Blick auf den Code werfen könnte und mir Hilfestellunge geben könnte. Nochmal zur Erläuterung was der Code machen soll und wo es Probleme gibt: Zeile 66-76: i2c initialisieren. Die 7Bit adresse des Sensors ist 0x1d. Ein Read ist demnach ein 0x3a und ein Write ein 0x3b. (Soweit ich das verstanden habe, muß ich die aber nie explizit angeben, sondern da kümmert sich der USCI Baustein drum, je nachdem ob ich UCTR in UCB0CTL1 setze oder nicht?) Zeile 81-84: Ein Read auf das Register 0x00. Der Sensor schickt daraufhin seine ID zurück. Diese muss 0xE5 sein. Klappt in 95% aller Fälle. Manchmal hängt hier dann einfach alles. Zeile 93-107: Hier aktiviere ich den Measurement-Mode. Zuerst wird in das Register 0x2d der Wert 0x28 geschrieben. Danach lese ich den Wert wieder aus und prüfe ob er wirklich 0x28 ist. Dies ist 1:1 von einem Codebeispiel von Sparkfun. Anscheinend klappt das nicht immer beim ersten Mal... Hier hängt sich der Code oft weg oder er kriegt immer nur 0 zurück anstatt 0x28. Beim Debuggen ist mir hier aufgefallen, dass "manchmal" in Zeile 175 sehr wohl in UCB0RXBUF 0x28 steht, beim Verlassen der Routine *data aber wieder 0x00 hat... Wie kann das sein? Wenn ich dann die Stromversorgung zum Sensor kappe und wieder anlege, klappt das Setzen des Wertes meistens sofort danach. Was mir sonst noch aufgefallen ist: Wenn sich mal wieder alles so richtig aufgehängt hat ist SCL low und bleibt low (sehe ich am Oszi). Und das auch wenn ich den Sensor ausgeschaltet habe. Das ist mir völlig schleierhaft, da die Stromversorgung noch an ist, und aufgrund des Pullup-Widerstands doch der Pegel wieder auf High gehen muß, weil er doch mit VCC verbunden ist??? Nach ein paar Mal Ein-/Ausschalten des Sensros, Restart des µC via JTAG Interface usw. geht es dann irgendwann wieder und der Bus initialisiert mit High auf SCL und SDA und ich darf's nochmal probieren... Das Datenblatt zum Sensor gibt es übrigens hier: http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf Bei Sparkfun kommt der Sensor leider nicht besonders gut weg (http://www.sparkfun.com/products/9156) und es gibt noch andere die über Probleme schreiben. Ich würde aber gerne wissen, ob meine Probleme auch von dem Sensor herrühren können oder ob ich hier einfach einen dummen Anfängerfehler gemacht habe. Also, passt mein Code oder springt Euch irgendwas ins Auge? Vielen Dank für Eure Mühe!
Du könntest ja zunächst mal rausfinden wer denn SCL auf low hält. Ich würde zwei Jumper einbauen (Einer vom Pull-Up Richtung µc und einer vom Pull-Up Richtung Sensor) und dann die Jumper ziehen und schauen wann die Spannung an SCL wieder high wird.
Als es scheint mir so, als würde der Sensor SDA runterziehen... ich sage "scheint so", weil es gerade ganz seltsam war: Ich habe die Jumper in beide Richtungen geöffnet, so dass eigentlich auf jeden Fall der Pegel wieder hoch gehen musste, aber er war immer noch low... Nachher war es dann reproduzierbar, dass beim Verbinden mit dem Sensor SDA auf low geht. Jetzt aber nochmal für Doofe: Ich hab zum ersten Mal so eine i2c Schaltung aufgebaut. Nur um Auszuschliessen, dass ich das völlig falsch gemacht habe: ------------------------------ GND Rail des Breadboards ++++++++|+++++++++|+++++++++++ VCC Rail des Breadboards |R1,4.7k |R2,4.7k | | ----- | | SCL |-------------|------> to MC pin SDA |-------------|------> to MC pin | ----- Das ist doch so richtig, oder? Die beiden Rs berühren sich natürlich nicht und haben nur Kontakt mit ihrer jeweiligen Leitung.
Nachtrag: Es ist also wirklich SDA low, SCL ging wieder hoch. Gerade habe ich den Fall, dass er sich "verschluckt" hat (Habe gerade oben gesehen, dass ich mich in meinem Original-Post daher verschrieben hatte. SCL verhält sich normal). Was ist denn im Allgemeinen der Grund für so ein Verhalten. Kann das ein Timing-Problem sein (Bustakt zu schnell?). Oder liegt sowas an falschen Pullup-Widerständen? Oder ist der Sensor einfach kaputt?
Beide Widerstände müssen Pullups sein, gegen GND dürfen diese nicht geschaltet werden.
Die Widerstände stecken in der VCC Rail. Sorry, falls das aus meiner Zeichnung nicht klar hervor ging.
SDA wird runter gezogen wenn er einen ACK auf den Bus legen will. Evt. bekommt er den nächsten SCL Takt nicht mit und lässt SDA deshalb weiter unten. Wie schnell ist denn dein I2C Bus?
So, hatte die Antwort leider im falschen Thread gepostet. Hier nochmal: -- Ich weißt es nicht 100%, da ich es nicht selbst definiert habe, aber wenn ich mir die Kommentare zu dem Codeschnippsel ansehe, dass ich zum Initialisieren des i2c Busses aus den TI Examples genommen habe würde ich sagen die normalen ca. 100 kHz (siehe UCB0BR0 = 0x0b Anweisung)
1 | P3SEL |= 0x06; // P3.1 + P3.2 USBI_B0 option select |
2 | UCB0CTL1 |= UCSWRST; // Enable SW reset |
3 | UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode |
4 | UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset |
5 | UCB0BR0 = 0x0b; // fSCL = SMCLK/11 = 95.3kHz |
6 | UCB0BR1 = 0; |
7 | UCB0I2CSA = 0x1d; // Set slave address (translates to 0x3a for write and 0x3b for a read |
8 | UCB0CTL1 &= ~UCSWRST; |
Ich habe mit diesem Prescaler auch schon gespielt (/63 usw.) Die Takte wurden entsprechend länger, aber am Verhalten hat sich nichts geändert...
Das Thema hat mir keine Ruhe gelassen... Ich habe heute mal meinen "Bus Pirate" ausgepackt und habe mal versucht über den mit dem Sensor zu sprechen und siehe da... DeviceID=E5, Measurement Mode aktiviert, alles ging... Habe dann auch mit dem Oszi mir die Kommunikation angesehen und war aber wieder verwundert, da SDA irgendwie um die 0V rumzuckelte und auch im Leerlauf nur 0V hatte, obwohl SDA über den Pullup direkt mit VCC verbunden war... Dachte ich mir, "Gibts doch nicht!" und hab dann mal mit dem Multimeter nachgemessen... aha! 3V!?!?! Lange Rede, kurzer Sinn: Nach einigen Ausschlusstests hat sich rausgestellt, dass wohl der Plastik-Aufsatz für den einen Tastkopf bei meinem Oszi einen Wackelkontakt hat (und zum Glück das Oszi in Ordnung ist...). "Drückt" man ihn ein bisschen zurecht, hat man auf einmal wieder ein schönes Signal im Oszi (Merke: Billig-Probes vom C auf den Müll werfen und noch einen Testec Kopf kaufen...) Ok, das heißt nun zumindest, dass i2c funktioniert und ich den Fehler erstmal ganz woanders gesucht hatte. SPI habe ich noch nicht ausprobiert, wird dann aber vermutlich auch gehen. Nur - in meinem Programm funktionierts halt deswegen immer noch nicht... Das bringt mich aber zu meiner ursprünglichen Frage zurück: Offenbar mache ich ja bei der i2c Kommunikation irgendwas falsch, vergesse ein ACK oder NACK oder sonstwas. OK - aber es muss für sowas aber doch fertige Bibliotheken geben, oder nicht?? Wie setzt Ihr denn i2c Funktionen in Euren Programmen ein? Das wird doch nicht nur via "Bit banging" gemacht? Grüße, Markus
Noch mal zusammengefasst: Die Kommunikation usw. geht alles problemlos, nur ab und zu bleibt der MSP hängen?
Hmm... lass es mich anders sagen: Anscheinend geht i2c problemlos, da es mit dem BusPirate (http://dangerousprototypes.com/docs/Bus_Pirate) als i2c Master ohne Probleme (=Hänger) funktioniert. Ich habe bislang i2c nur beim Auslesen eines LM75 verwendet, und der ist ja sehr einfach gestrickt. Insofern möchte ich nicht mit Sicherheit sagen, dass die Kommunikation (mit dem MSP430) problemlos funktionierte. Ich vermute halt, dass mein Code ganz oben, "das" nicht ganz richtig gemacht hat, aber ich weiß halt nicht, wie es gemacht werden muss. Die Konsequenz davon war dann, dass das Programm dann hing, weil er wahrscheinlich irgendein IO Flag, dass erwartet wurde, nicht empfangen oder versendet hatte. Auf dem Oszi stellte sich das ja so da, dass SDA nicht wieder freigegeben wurde - hier hatte ich aber bis dato noch nicht ermitteln können, woran das lag. Grüße, Markus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.