Forum: Mikrocontroller und Digitale Elektronik MSP430FR und I2C Master


von Daniel S. (snipod)


Lesenswert?

Hallo,
ich bin neu auf der MSP430 Plattform und komme aktuell mit dem I2C nicht 
zurecht.

Ich habe mich durch die Doku gekämpft und zahlreiche Tutorials gelesen, 
aber komme nicht weiter.

Ich möchte mit einem MSP430FR2532 einen VL53L0X einstellen und auslesen, 
scheitere aber schon am lesen der ID, vielleicht kann mir ja jemand 
weiterhelfen :)

Vorab:
VL53L0X und MSP430FR werden mit 2V8 versorgt. SDA hängt an P1.2 
(UCB0SDA), SCL hängt an P1.3 (UCB0SCL). SDA und SCL sind über 1k6 an 
2V8. Außerdem läuft der UART auf UCA0.

Und hier mein Code:
1
void I2C_Init()
2
{
3
    //-- Setup I2C periphal
4
    UCB0CTLW0 |= UCSWRST;           // put I2C B0 into SW reset
5
    UCB0CTLW0 |= UCSSEL_3;          // choose SMCLK
6
    UCB0BRW = 20;                   // set prescaler = 20 0> 8 MHz SMCLK => 400 kHz
7
    UCB0CTLW0 |= UCMODE_3;          // put into I2C mode
8
    UCB0CTLW0 |= UCMST;             // put into Master
9
10
    //-- Setup I2C ports
11
    P1SEL1 &= ~BIT3;                // P1.3 = SCL
12
    P1SEL0 |= BIT3;
13
14
    P1SEL1 &= ~BIT2;                // P1.2 = SDA
15
    P1SEL0 |= BIT2;
16
17
    UCB0CTLW0 &= ~UCSWRST;          // take I2C B0 out of SW reset
18
}
19
20
void I2C_Read_Bytes(uint8_t slv_addr, uint8_t reg_addr, uint8_t l, char *arr)
21
{
22
    uint8_t i;
23
24
    while (UCB0STAT & UCBBUSY); // wait until UCB0 not busy
25
26
    UCB0I2CSA = slv_addr;       // set slave address
27
28
    UCB0CTL1 |= UCTR | UCTXSTT; // transmitter mode and START condition.
29
30
    while (UCB0CTL1 & UCTXSTT); // wait for start to be sent
31
32
    UCB0TXBUF = reg_addr;       // send register address
33
34
    while ((UCB0IFG & UCTXIFG));// wait for tx buffer to be empty
35
36
    UCB0CTL1 |= UCTXSTP;        // send stop bit
37
38
    UCB0CTL1 &= ~UCTR;          // receiver mode
39
40
    UCB0CTL1 |= UCTXSTT;        // START condition
41
42
    while (UCB0CTL1 & UCTXSTT); // wait for start to be sent
43
44
    for (i = 0; i < l; i++)
45
    {
46
        while (!(UCB0IFG & UCRXIFG));   // wait for a byte to arrive in Rx Buffer
47
48
49
        if (i == l - 1) {
50
            UCB0CTL1 |= UCTXSTP;        // STOP condition on last byte
51
        }
52
53
        char val = UCB0RXBUF;           // read byte into buffer
54
        arr[i] = val;
55
    }
56
57
    while (UCB0CTL1 & UCTXSTP);         // wait until stop is sent
58
}

Der Code hängt bei
1
while (!(UCB0IFG & UCRXIFG));

Vielen Dank schon mal an Alle vorab!

von wv (Gast)


Lesenswert?

Hallo Daniel,

die Zeile
   while (!(UCB0IFG & UCRXIFG));
macht auch irgendwie keinen Sinn. Ich hab jetzt nicht im Family-Guide 
nachgeschaut, aber von den Bezeichnungen her sind das zwei 
Flags(Bitwerte) die Du vergleichst. Also überprüf mal welches Flag in 
welchem Register Du da prüfen willst und vergleiche dann das Register 
gegen das Flag.

Gruß wv

von Clemens L. (c_l)


Lesenswert?

wv schrieb:
> while (!(UCB0IFG & UCRXIFG));
>
> von den Bezeichnungen her sind das zwei Flags(Bitwerte) die Du vergleichst.

Nein, UCB0IFG ist ein Register.

Daniel S. schrieb:
> //-- Setup I2C ports
>     P1SEL1 &= ~BIT3;                // P1.3 = SCL
>     P1SEL0 |= BIT3;
>     P1SEL1 &= ~BIT2;                // P1.2 = SDA
>     P1SEL0 |= BIT2;

Hast du auch LOCKLPM5 gelöscht?

> while (UCB0STAT & UCBBUSY); // wait until UCB0 not busy

UCBBUSY verrät dir nicht, ob du auf die Register zugreifen darfst. Hier 
solltest du UCTXSTP abfragen (am Ende der Funktion ist das dann nicht 
notwendig).

>     UCB0CTL1 |= UCTR | UCTXSTT; // transmitter mode and START condition.
>     while (UCB0CTL1 & UCTXSTT); // wait for start to be sent

Das Flag, das dir sagt, dass du in TXBUF schreiben kannst, ist UCTXIFG.
Und du solltest auch auf UCNACKIFG testen.

>     UCB0TXBUF = reg_addr;       // send register address
>     while ((UCB0IFG & UCTXIFG));// wait for tx buffer to be empty

Der Kommentar ist falsch. Hier brauchst du nicht zu warten, und TXIFG 
wurde durch das Schreiben eh gelöscht.

>     UCB0CTL1 |= UCTXSTP;        // send stop bit

Das Stop-Bit brauchst du hier nicht (repeated start). Und wenn du es 
trotzdem setzt, musst du wahrscheinlich warten.

>     UCB0CTL1 &= ~UCTR;          // receiver mode
>     UCB0CTL1 |= UCTXSTT;        // START condition
>     while (UCB0CTL1 & UCTXSTT); // wait for start to be sent

UCTXSTT ist auch hier sinnlos; einfach auf UCRXIFG oder UCNACKIFG 
warten.

von Daniel S. (snipod)


Angehängte Dateien:

Lesenswert?

Hallo,
alles klar ich bin etwas weiter gekommen...

Habe wie Ihr geschrieben habt festgestellt, dass ich bisschen Register 
und Masken Gulasch hatte :)

Das sollte soweit jetzt passen, laufen will es aber noch immer nicht 
richtig.
1
uint8_t I2C_Read_Byte(uint8_t address, uint8_t *value) {
2
    while(UCB0CTL1 & UCTXSTP);      // wait for previous transaction to complete
3
4
    UCB0CTL1 |= (UCTR | UCTXSTT);   // transmitter mode + START
5
6
    while(!(UCB0IFG & UCTXIFG));    // wait for Tx Buffer
7
8
9
    if(UCB0IFG & UCNACKIFG)         // check for NACK
10
    {
11
        return UCB0STAT;
12
    }
13
14
    UCB0TXBUF = address;            // write register address
15
16
    while(!(UCB0IFG & UCTXIFG));    // wait for Tx Buffer
17
18
    if(UCB0IFG & UCNACKIFG)         // check for NACK
19
    {
20
        return UCB0STAT;
21
    }
22
23
    UCB0CTL1 &= ~UCTR;              // Receiver Mode
24
    UCB0CTL1 |= UCTXSTT;            // send Start
25
26
    //while(UCB0CTL1 & UCTXSTT);      // wait for START signal to be sent
27
28
    while (!(UCB0IFG & UCRXIFG));   // wait for RX Buffer
29
30
    UCB0CTL1 |= UCTXSTP;            // Transmit STOP
31
    *value = UCB0RXBUF;             // read RX data
32
33
    return 0;
34
}

Leider will der Controller immer 1 byte mehr lesen als ich - und ich hab 
keinen Plan warum...



Clemens L. schrieb:
> Hast du auch LOCKLPM5 gelöscht?

Ja


Irgendwann kackt mir dann der VL54L0X ab und SCL bleibt Low

von Clemens L. (c_l)


Lesenswert?

>     while(!(UCB0IFG & UCTXIFG));    // wait for Tx Buffer
>     if(UCB0IFG & UCNACKIFG)         // check for NACK

Wenn nur UCNACKIFG gesetzt ist, dann wird die Schleife nie beendet.

>     if(UCB0IFG & UCNACKIFG)         // check for NACK
>         return UCB0STAT;

UCB0STAT ist wahrscheinlich 0. Du solltest hier UCB0IFG oder einen 
Fehlercode zurückliefern.

>     UCB0CTL1 |= UCTXSTT;            // send Start
>     while (!(UCB0IFG & UCRXIFG));   // wait for RX Buffer
>     UCB0CTL1 |= UCTXSTP;            // Transmit STOP

UCTXSTP muss gesetzt werden, before das letzte Byte empfangen wird. 
Also:
1
    UCB0CTL1 |= UCTXSTT | UCTXSTP;  // send Start and Stop

: Bearbeitet durch User
von Daniel S. (snipod)


Lesenswert?

Hi,
danke für die Antwort;

Clemens L. schrieb:
> UCTXSTP muss gesetzt werden, before das letzte Byte empfangen wird.
> Also:    UCB0CTL1 |= UCTXSTT | UCTXSTP;  // send Start and Stop

nicht nur das, man muss warte, bis START gesendet wurde und erst danach 
das STOP bit setzen.
1
 UCB0CTL1 |= UCTXSTT;                                        // send Repeated Start
2
    while(UCB0CTL1 & UCTXSTT) ;                                 // wait for START
3
    UCB0CTL1 |= UCTXSTP;                                        // send STOP
4
    while (!((UCB0IFG & UCRXIFG)));                             // wait for RX Buffer
5
    *value = UCB0RXBUF;                                         // read RX data

Das hat soweit auch funktioniert, nur irgendwann hatte ich dann immer 
"alte" Daten im RxBuffer, also ich habe die Funktion I2C_Read_Byte() 
ausgefürt, habe auf dem Logic Analyzer auch gesehen, welche Bytes 
gelesen und gesendet wurden, habe aber aus dem UCB0RXBUF immer den Wert 
der jeweils vorherigen Transaktion bekommen. Ich habe das Problem jetzt 
erst mal umschifft, indem ich den eUSCIB nach jeder Transaktion resette, 
aber das ist ja eigentlich auch nicht des Rätsels Lösung... Vielleicht 
findet ja noch jemand den Fehler in meinem I2C Wrapper....
1
void i2cInit()
2
{
3
    UCB0CTLW0 |= UCSWRST;       // put into SW Reset
4
    UCB0CTLW0 |= UCSSEL_3;      // choose SMCLK
5
    UCB0BRW = 20;               // set prescaler = 20 => 400 kHz
6
    UCB0CTLW0 |= UCMODE_3;      // put into I2C Mode
7
    UCB0CTLW0 |= UCMST;         // put into MASTER mode
8
    UCB0CTLW0 |= UCSYNC;        //
9
    UCB0I2CSA = 0x29;           // slave addr = 0x29
10
11
12
    P1SEL1 &= ~BIT3;            // P1.3 = SCL
13
    P1SEL0 |= BIT3;
14
15
    P1SEL1 &= ~BIT2;            // P1.2 = SDA
16
    P1SEL0 |= BIT2;
17
18
    UCB0CTLW0 &= ~UCSWRST;      // get out of SW Reset
19
}
20
21
void i2cReset() {
22
    UCB0CTLW0 |= UCSWRST;       // put into SW Reset
23
    UCB0CTLW0 &= ~UCSWRST;      // get out of SW Reset
24
}
25
26
27
uint8_t I2C_Read_Byte(uint8_t address, uint8_t *value) {
28
29
    UCB0CTL1 |= UCTR | UCTXSTT;                                 // transmitter mode + START
30
    while(UCB0CTL1 & UCTXSTT) ;                                 // wait for START
31
    while(!((UCB0IFG & UCTXIFG) || (UCB0IFG & UCNACKIFG)));     // wait for Tx Buffer
32
    if(UCB0IFG & UCNACKIFG)                                     // check for NACK
33
    {
34
        return 1;
35
    }
36
    UCB0TXBUF = address;                                        // write register address
37
    while(!((UCB0IFG & UCTXIFG) || (UCB0IFG & UCNACKIFG)));     // wait for Tx Buffer
38
    if(UCB0IFG & UCNACKIFG)                                     // check for NACK
39
    {
40
        return 2;
41
    }
42
    UCB0CTL1 &= ~UCTR;                                          // Receiver Mode
43
    UCB0CTL1 |= UCTXSTT;                                        // send Repeated Start
44
    while(UCB0CTL1 & UCTXSTT) ;                                 // wait for START
45
    UCB0CTL1 |= UCTXSTP;                                        // send STOP
46
    while (!((UCB0IFG & UCRXIFG)));                             // wait for RX Buffer
47
    *value = UCB0RXBUF;                                         // read RX data
48
    while(UCB0CTL1 & UCTXSTP);                                  // wait for previous transaction to complete
49
    i2cReset();
50
51
    return 0;
52
}
53
54
uint8_t I2C_Read_Bytes(uint8_t address, uint8_t *value, uint8_t length)
55
{
56
    uint8_t i = 0;
57
58
    UCB0CTL1 |= UCTR | UCTXSTT;                                 // transmitter mode + START
59
    while(UCB0CTL1 & UCTXSTT) ;                                 // wait for START
60
    while(!((UCB0IFG & UCTXIFG) || (UCB0IFG & UCNACKIFG)));     // wait for Tx Buffer
61
    if(UCB0IFG & UCNACKIFG)                                     // check for NACK
62
    {
63
       return 1;
64
    }
65
    UCB0TXBUF = address;                                        // write register address
66
    while(!((UCB0IFG & UCTXIFG) || (UCB0IFG & UCNACKIFG)));     // wait for Tx Buffer
67
    if(UCB0IFG & UCNACKIFG)                                     // check for NACK
68
    {
69
       return 2;
70
    }
71
72
    UCB0CTL1 &= ~UCTR;                                          // Receiver Mode
73
    UCB0CTL1 |= UCTXSTT;                                        // send Start
74
    while(UCB0CTL1 & UCTXSTT) ;                                 // wait for START
75
    do
76
    {
77
        while(!(UCB0IFG & UCRXIFG));                            // wait for Rx Buffer
78
        value[i] = UCB0RXBUF;                                   // read RX Buffer
79
        i++;
80
    }while(i < (length - 1));
81
82
    while(!(UCB0IFG & UCRXIFG));                                // wait for Rx Buffer
83
84
    UCB0IFG &= ~UCTXIFG;
85
    UCB0CTL1 |= UCTXSTP;
86
    value[length - 1] = UCB0RXBUF;
87
    while(UCB0CTL1 & UCTXSTP);                                  // wait for previous transaction to complete
88
    i2cReset();
89
    return 0;
90
}
91
92
uint8_t I2C_Write_Byte(uint8_t address, uint8_t value)
93
{
94
    UCB0CTL1 |= (UCTR | UCTXSTT);
95
    while(UCB0CTL1 & UCTXSTT) ;                                 // wait for START
96
    while(!((UCB0IFG & UCTXIFG) || (UCB0IFG & UCNACKIFG)));     // wait for Tx Buffer
97
    if(UCB0IFG & UCNACKIFG)                                     // check for NACK
98
    {
99
        return 1;
100
    }
101
102
    UCB0TXBUF = address;
103
104
    while(!((UCB0IFG & UCTXIFG) || (UCB0IFG & UCNACKIFG)));     // wait for Tx Buffer
105
    if(UCB0IFG & UCNACKIFG)         // check for NACK
106
    {
107
        return 2;
108
    }
109
110
    UCB0TXBUF = value;
111
112
    while(!((UCB0IFG & UCTXIFG) || (UCB0IFG & UCNACKIFG)));     // wait for Tx Buffer
113
    if(UCB0IFG & UCNACKIFG)         // check for NACK
114
    {
115
        return 3;
116
    }
117
    UCB0CTL1 |= UCTXSTP;
118
    while(UCB0CTL1 & UCTXSTP);                                  // wait for previous transaction to complete
119
    i2cReset();
120
    return 0;
121
}

von Clemens L. (c_l)


Lesenswert?

Wenn UCB0RXBUF ein noch nicht vom Code gelesenes Byte enthält, dann wird 
UCRXIFG gesetzt. Kannst du testen, wann es zuerst gesetzt wird? Schon 
vor dem Aufruf von I2C_Read_Byte, oder später?

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.