Forum: Mikrocontroller und Digitale Elektronik MSP430 I2C Slave Adresse


von Frank (Gast)


Lesenswert?

Hallo,

Es ist mein erstes Projekt mit dem MSP430 und ich versuche einen 
Strom-Sensor über I2C anzusteuern. Die Hardware passt soweit, Pullups 
etc. sind vorhanden.

Leider ist es mein "Einstiegsprojekt" und Softwarekenntnisse sind kaum 
vorhanden.

Aus den Code Examples/User Guide von ti werde ich nicht ganz schlau...

Die Kommunikation funktioniert soweit, dass ich nach der Slaveadresse 
ein ACK erhalte (UCB0I2CSA).

Nun weiß ich aber nicht wie ich meinem Slave die 
Addressen&Contents/Daten vermittle(UCB0TXBUF)....

Als Beispiel: Configuration=> Address:00h und Contents:4127h..
              Shunt=> Address:01h und Contents:1f40h...

Vorausgesetzt mir kann jemand folgen, hätte ich gerne die paar 
wesentlichen Zeilen, damit ich darauf mein Programm aufbauen kann.

Ich bin um jede Hilfe dankbar!

Gruß Frank

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank schrieb:
> Aus den Code Examples/User Guide von ti werde ich nicht ganz schlau...

Und Du hast Dir auch das Beispiel angesehen, bei dem zwei MSP430 per I2C 
miteinander verbunden werden, der eine also Master und der andere Slave 
ist?

Welchen MSP430 verwendest Du überhaupt?

von Frank (Gast)


Lesenswert?

Hallo Rufus,

ich benutze den msp430g2553.

Den Code hab ich natürlich schon angeschaut und eine grobe Vermutung... 
Ich werde ihn morgen mal hochladen, vlt. kann mir ja jemand sagen ob ich 
auf dem richtigen Weg bin :)

Vielen Dank für deine Antwort.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann hast Du Dir auch slac485d angesehen?

Darin ist das hier zu finden:
1
msp430g2xx3_uscib0_i2c_04.c                USCI_B0 I2C Master RX single bytes from MSP430 Slave
2
msp430g2xx3_uscib0_i2c_05.c                USCI_B0 I2C Slave TX single bytes to MSP430 Master
3
msp430g2xx3_uscib0_i2c_06.c                USCI_B0 I2C Master TX single bytes to MSP430 Slave
4
msp430g2xx3_uscib0_i2c_07.c                USCI_B0 I2C Slave RX single bytes from MSP430 Master
5
msp430g2xx3_uscib0_i2c_08.c                USCI_B0 I2C Master TX multiple bytes to MSP430 Slave
6
msp430g2xx3_uscib0_i2c_09.c                USCI_B0 I2C Slave RX multiple bytes from MSP430 Master
7
msp430g2xx3_uscib0_i2c_10.c                USCI_B0 I2C Master RX multiple bytes from MSP430 Slave
8
msp430g2xx3_uscib0_i2c_11.c                USCI_B0 I2C Slave TX multiple bytes to MSP430 Master
9
msp430g2xx3_uscib0_i2c_12.c                USCI_B0 I2C Master TX/RX multiple bytes from MSP430 Slave 
10
                                           with a repeated start in between TX and RX operations.
11
msp430g2xx3_uscib0_i2c_13.c                USCI_B0 I2C Slave RX/TX multiple bytes to MSP430 Master

: Bearbeitet durch User
von Frank (Gast)


Angehängte Dateien:

Lesenswert?

Hey Rufus,

Vielen Dank um dein Bemühen!!

Die Code Examples kannte ich schon, ohne diese wäre ich komplett 
aufgeschmissen.

Ich hab mal das Original:
msp430g2xx3_uscib0_i2c_03.c - USCI_B0 I2C Master Interface to DAC8571, 
Write

versucht meinem Programm anzupassen und ein paar Zeilen verändert.

Zum Verständnis erst mal nur eine Adresse und seine Daten...

--------------------------------------------------------------------
1
#include <msp430.h>
2
3
4
unsigned int RxByteCtr;
5
unsigned int RxWord;
6
7
const unsigned char Contents[] =            // WERT 4127h
8
{
9
  0x41,
10
  0x27
11
12
13
};
14
15
int main(void)
16
{
17
  WDTCTL = WDTPW + WDTHOLD;                 // Stop Watchdog Timer
18
  // BIT1^= ALARM
19
  P1SEL |= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
20
  P1SEL2|= BIT6 + BIT7;                     // Assign I2C pins to USCI_B0
21
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
22
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
23
  UCB0CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
24
  UCB0BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
25
  UCB0BR1 = 0;
26
  UCB0I2CSA = 0x40;                         // Set slave address
27
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
28
  IE2 |= UCB0TXIE;                          // Enable TX ready interrupt
29
  UCB0CTL1 |= UCTR + UCTXSTT;               // I2C TX, start condition
30
  UCB0TXBUF = 0x00;                        // address?
31
  __bis_SR_register(CPUOFF + GIE);          // Enter LPM0 w/ interrupts
32
}
33
34
// USCI_B0 Data ISR
35
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
36
#pragma vector = USCIAB0TX_VECTOR
37
__interrupt void USCIAB0TX_ISR(void)
38
#elif defined(__GNUC__)
39
void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)
40
#else
41
#error Compiler not supported!
42
#endif
43
{
44
  static unsigned char ByteCtr=0;
45
46
  UCB0TXBUF = Contents[ByteCtr++];          // Transmit data byte
47
  ByteCtr &= 0x01;                          // Do not exceed table
48
}
49
50
--------------------------------------------------------------------------

Siehe Bild vom Signal im Anhang.

Frage hierzu:

1)UCB0TXBUF = 0x00; wird dieser Bitstream als Adresse erkannt oder muss 
ich da noch was beachten?

2)Warum wird 0x27 ein zweites mal versendet? Brauch ich noch Stop 
Conditions oder kann ich mein ByteCtr anpassen...


Vielen Dank

--
Quelltext bitte in [ c ] [ /c ] -Tags einschließen.
-rufus

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

>  1)UCB0TXBUF = 0x00; wird dieser Bitstream als Adresse erkannt
> oder muss ich da noch was beachten?

Das ist nicht die Adresse. Die wird ein paar Zeilen weiter oben in das 
Register UCB0I2CSA eingetragen.

Der Wert 0x00 ist das erste übertragene Datenbyte.

Danach werden noch die beiden Bytes in Deiner Tabelle gesendet, 0x41 
(65) und 0x27 (39).

Merkwürdig ist Dein I2C-Mitschrieb, weil in dem das Adressbyte nicht die 
Adresse (0x40) enthält.

: Bearbeitet durch User
von Frank (Gast)


Angehängte Dateien:

Lesenswert?

Rufus Τ. Firefly schrieb:

> Das ist nicht die Adresse. Die wird ein paar Zeilen weiter oben in das
> Register UCB0I2CSA eingetragen.

ja

  und mein Problem:

> Der Wert 0x00 ist das erste übertragene Datenbyte.

genau und diesen möchte ich als meinen Register Pointer Byte 
nutzen.(Bild)
Oder habe ich noch eine andere Möglichkeit außer diese als Datenbyte 
handzuhaben, sowas wie UCBO...

(Entschuldigung, dass ich mich unklar ausgedrückt habe).

Und Danke.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank schrieb:
> und mein Problem:
>
>> Der Wert 0x00 ist das erste übertragene Datenbyte.
>
> genau und diesen möchte ich als meinen Register Pointer Byte
> nutzen.(Bild) Oder habe ich noch eine andere Möglichkeit außer diese als
> Datenbyte handzuhaben, sowas wie UCBO...

Das ist dann kein Problem, sondern in Ordnung. Daß das vom I2C-Baustein 
als "Register Pointer" interpretiert wird, ist egal, von der I2C-Seite 
her ist das ein stinknormales Datenbyte.


Und jetzt klärt sich auch das "Geheimnis" um das Adressbyte 0x40 -- Dein 
Protokollanalysator wertet das erste Byte des I2C-Rahmens als 8-Bit-Wert 
aus, d.h. das R/W-Bit ist Bit 0, und damit wird aus 0x40 0x80 (128).

Das ist also auch in Ordnung.

Was nicht in Ordnung ist, ist, daß Du insgesamt vier Bytes sendest (was 
zum Resultat hat, daß es auf das vierte Byte ein NAK als Antwort gibt, 
weil Dein Baustein damit nichts anzufangen weiß.

Das zuviel gesendete Byte liegt daran, daß Deine Routine kein Ende 
erkennt, das Maskieren des Zählers mit 0x1 im Interrupt hilft da nicht.

Sieh Dir mal an, wie der Code aus msp430g2xx3_uscib0_i2c_08.c aussieht, 
hier musst Du Dir insbesondere den Interrupthandler ansehen.

Was da gemacht wird, musst Du auch machen.

Hier werden vier Nutzbytes versendet, und vor dem Versenden wird ein 
Pointer auf die zu versendenden Daten gesetzt (das ist PTxData) und ein 
Bytezähler initialisiert (das ist TXByteCtr).

Das interruptgesteuerte Senden wird --anders als in Deinem Code-- nicht 
durch Beschreiben von UCB0TXBUF mit dem ersten zu sendenden Byte 
angestoßen, sondern durch das Setzen der Bits UCTR und UCTXSTT in 
UCB0CTL1.

(vorher wird darauf gewartet, daß die vorangehende Übertragung beendet 
ist, was durch eine 0 im Bit UCTXSTP im Register UCB0CTL1 erkannt wird).

Um das ganze auf Deine Anwendung anzupassen, kannst Du das Array TxData 
um ein Byte verkleinern. Das erste Byte ist der Wert, der als "Register 
Pointer" dient, das zweite und dritte Deine Daten.

Natürlich musst Du auch die I2C-Adresse anpassen; Du willst 0x40 
verwenden, im Beispiel wird 0x48 verwendet (und in UCB0I2CSA 
eingetragen).

Viel Erfolg!

von Frank (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das ist also auch in Ordnung.

Super :) Das habe ich gehofft,...

Damit hätte ich dann meine "Stütze" die ich gebraucht habe um weiter zu 
kommen.

Ein gaaanz großes Dankeschön für die schnellen Antworten.

Super Forum!!

in diesem Sinne... Schönes Wochenende ;)

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.