Forum: Mikrocontroller und Digitale Elektronik MSP430, I2C: Daten senden und empfangen (MAG3110)


von Dominic (Gast)


Angehängte Dateien:

Lesenswert?

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.
1
//------------------------------------------------------------------------------
2
// void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field)
3
//
4
// This function is used to start an I2C commuincation in master-transmit mode. 
5
//
6
// IN:   unsigned char byteCount  =>  number of bytes that should be transmitted
7
//       unsigned char *field     =>  array variable. Its content will be sent.
8
//------------------------------------------------------------------------------
9
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field){
10
  TI_transmit_field = field;
11
  byteCtr = byteCount;
12
  UCB1CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
13
}
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!

von Clemens L. (c_l)


Lesenswert?

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.

von Daniel (Gast)


Lesenswert?

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.

von Max G. (l0wside) Benutzerseite


Lesenswert?

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.

von Daniel (Gast)


Lesenswert?

Ähm sry, war gerade nur schnell am PC eines Freundes

von Max G. (l0wside) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch User
von Daniel (Gast)


Lesenswert?

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?

von Max G. (l0wside) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch User
von Clemens L. (c_l)


Lesenswert?

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).

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
Noch kein Account? Hier anmelden.