Hallo zusammen,
ich möchte Daten aus einem Sensor der mittels I2C angeschlossen ist
auslesen. Dafür habe ich die Beispielfunktionen von TI auf meinen
Controller angepasst und würde sagen, diese sollten soweit auch passen
(Signal auf dem Bus, Ack des Sensors vorhanden).
Aber was muss ich tun, um Signale zu empfangen? Muss ich erst mittels
transmit Daten Anfordern, sodass ich diese dann über Receive lesen kann?
Ich verstehe das nicht ganz.
Was mich auch etwas irritiert sind die zwei Initialisierungsroutinen,
einmal für transmit und einmal für receive. Außer einem anderen
Interruptvektor sind sie sonst identisch. Ist das so angedacht, dass ich
vor jedem Transmit/ Receive, die Initialisierung durchführe?
Und wie werden Daten überhaupt gesendet.
Anhand dieser Funktion kann ich nirgends erkennen, wo die Daten jetzt
wirklich auf den Bus geschrieben werden sollen....
Ich habe die USCI I2C Master Library verwendet und möchte den MAG3110
ansprechen (http://www.ti.com/lit/an/slaa382a/slaa382a.pdf).
Danke!
Dominic schrieb:> Aber was muss ich tun, um Signale zu empfangen? Muss ich erst mittels> transmit Daten Anfordern, sodass ich diese dann über Receive lesen kann?
Du sollst die Registeradresse senden, dann eine Repeated Start Condition
(ein Start (UCTXSTT) ohne Stop (UXTXSTP) vorher), dann lesen. (Der
TI-Code kann das nicht.)
Wahrscheinlich geht es auch ohne Repeated Start, d.h., getrennte
Transmit-/Receive-Transaktionen.
> Ist das so angedacht, dass ich vor jedem Transmit/ Receive, die> Initialisierung durchführe?
Du kannst auch einfach UCTR umschalten. (Der TI-Code kann das nicht.)
> Anhand dieser Funktion kann ich nirgends erkennen, wo die Daten jetzt> wirklich auf den Bus geschrieben werden sollen....
Der Interrupthandler schreibt das nächste Byte aus TI_transmit_field in
TXBUF.
Ahhh, vielen Dank :)
Ähm ja, den ISR muss ich dann wohl noch implementieren... ups -.-
Aber mit anderen Worten ist der TI-Code dann eher für mich
unbrauchbar... Also müsste ich mir wohl am ehesten meinen eigenen
schreiben? Gibts da gut verwertbare Beispiele? Ich habe halt von I2C
keine Ahnung und bisher immer versucht diesen irgendwie zu umgehen bzw
fertige Bibliotheken zu benutzen.
Mit etwas Schmerzen kann man das auch selbst programmieren. Die
TI-Beispielcodes sind meist ganz ok, um zu sehen, dass es überhaupt
geht. Zur produktiven Verwendung sind sie erfahrungsgemäß weniger
geeignet. YMMV.
I2C ist im Grunde nicht wild. Nimm dir mal das Datenblatt deines
angesteuerten Bausteins, da steht (höchstwahrscheinlich) alles
detailliert drin, was auf dem Bus passieren soll. Wenn du kein
Multimaster-System hast (und das hast du ziemlich sicher nicht), kannst
du auch Stop und Start schicken. Repeated Start ist nur dann zwingend,
wenn ein zweiter Master konkurrierend auf den Bus zugreifen könnte.
I2C ist unidirektional, d.h. kann nur entweder lesen oder schreiben. Zur
Richtungsänderung braucht es einen Start oder Repeated Start.
Grob funktioniert Auslesen mit I2C (meist) so:
Start - I2C-Zieladresse mit Schreibbit - Registeradresse - Repeated
Start - I2C-Zieladresse mit Lesebit - Lesen - Stop.
Start, Repeated Start und Stop funktionieren durch Setzen der
entsprechenden Bits in UCBxCTL1. Adresse und Lese-/Schreibrichtung
Schreiben von Daten in das Register UCBxTXBUF, Lesen von empfangenen
Daten aus UCBxRXBUF. Ob fertig geschrieben ist (und das nächste Byte
raus kann), lässt sich aus einem der UCBxCTLx-Bits herauslesen. Welches,
überlasse ich deiner Datenblattlektüre. Genauer, der Lektüre des Family
User´s Guide.
Ergänzung
Wahlweise kannst du Polling verwenden (also einfach so lange warten, bis
das Bit zurückgesetzt wird) oder ISRs verwenden. Letzteres ist
aufwändiger, dafür kann der uC entweder schlafen oder was Sinnvolles
tun, so lange die I2C-Kommunikation läuft.
Nicht vergessen: I2C am MSP430 braucht externe Pullups.
Die Anschaffung eines Logicanalyzers (< 10 EUR aus China) ist extrem
empfehlenswert.
Auch nochmal vielen Dank. Ich habe hier ein 2-Kanal Oszilloskop stehen,
dass solle doch ausreichen oder?
Start | I2C-Zieladresse mit Schreibbit - Registeradresse | Repeated
Start | I2C-Zieladresse mit Lesebit - Lesen | Stop.
Nochmal eine kurze Frage: ist das jedesmal oben eine eigene Nachricht
bzw habe ich das so richtig aufgetrennt?
Oszi geht auch, wenn man weiß, wonach man sucht und sich nicht zu schade
ist, Bits auszuzählen, um herauszufinden, welche Adresse jetzt auf dem
Bus ist und ob das Lese-/Schreibbit gesetzt ist und ob das ACK kommt.
Ist fummelig, aber machbar.
Schau dir mal in
http://ww1.microchip.com/downloads/en/DeviceDoc/21189f.pdf die Fig. 6.2
an. Das zeigt recht gut, was auf dem I2C passiert, wenn man lesen will.
Sind zwar keine Register-, sondern Speicheradressen, aber das Prinzip
ist das gleiche. Die Datenblätter vieler anderer I2C-Bausteine haben
ähnliche Diagramme, vielleicht ja auch deines. Welchen Sensor willst du
denn ansteuern?
EDIT Beim MAG3110 steht das Diagramm auf S. 12 des Datenblatts.
Daniel schrieb:> Start | I2C-Zieladresse mit Schreibbit - Registeradresse | Repeated> Start | I2C-Zieladresse mit Lesebit - Lesen | Stop.
Ein extra "Repeated" gibt es nicht; das zweite Start wird "repeated"
genannt, wenn vorher kein Stop kam.
> Ich habe halt von I2C keine Ahnung und bisher immer versucht diesen> irgendwie zu umgehen bzw fertige Bibliotheken zu benutzen.
Dann nimm die Arduino-Bibliotheken (beim MSP: Energia).