Forum: Mikrocontroller und Digitale Elektronik I2C Modul sendet Adresse erneut anstelle von Stop-Condition (TI TMS320F28388D)


von Mductance (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Ich benutze gerade einen TMS320F28388D und müsste mit dem mit einem 
TLI493D-W2BW von Infineon  kommunizieren. Dazu implementiere ich die 
generische Bibliothek die von Infineon bereitgestellt wird.

Das Problem ist, dass meine I2C write Funktion nicht richtig 
funktioniert, das angehängte Bild (w2bw_debugging) zeigt das Resultat, 
wenn man zwei bytes in den Sensor schreiben möchte (also 
"w2bw_i2c_write" mit count=2).

Der uC schreibt die Adresse und die beiden bytes welche auch vom Sensor 
bestätigt werde. Danach verhält sich der uC allerdings seltsam und 
sendet die Adresse des Sensors erneut (der Protokoll-Analysator 
registriert das als einen "Re-Start", habe davon aber im Zusammenhang 
mit I2C noch nie gehört).

Das I2C Modul konfiguriere ich mittels:
1
void I2Cinit(){
2
    I2C_disableModule(I2C0_W2BW_BASE);
3
    I2C_initMaster(I2C0_W2BW_BASE, DEVICE_SYSCLK_FREQ, 200000, I2C_DUTYCYCLE_50);
4
    I2C_setConfig(I2C0_W2BW_BASE, I2C_MASTER_SEND_MODE);
5
    I2C_setSlaveAddress(I2C0_W2BW_BASE, 0);
6
    I2C_disableLoopback(I2C0_W2BW_BASE);
7
    I2C_setBitCount(I2C0_W2BW_BASE, I2C_BITCOUNT_8);
8
    I2C_setDataCount(I2C0_W2BW_BASE, 1);
9
    I2C_setAddressMode(I2C0_W2BW_BASE, I2C_ADDR_MODE_7BITS);
10
    I2C_enableFIFO(I2C0_W2BW_BASE);
11
    I2C_setFIFOInterruptLevel(I2C0_W2BW_BASE, I2C_FIFO_TXEMPTY, I2C_FIFO_RXEMPTY);
12
    I2C_setEmulationMode(I2C0_W2BW_BASE, I2C_EMULATION_FREE_RUN);
13
    I2C_enableModule(I2C0_W2BW_BASE);
14
}

Die Funktion die n bytes schreiben sollte ist definiert als:
1
/*! \brief Function Header: (uint8_t addr, const uint8_t* data, uint8_t count)
2
 *
3
 * I2C write command must have a header precisely of type:
4
 * (uint8_t addr, const uint8_t* data, uint8_t count), where:
5
 * \param addr Is the I2C address to read from data is the;
6
 * \param data is the array that the function will read to
7
 * \param count is the number of bytes the function will read
8
 *
9
 * \code{.c}
10
 * // =============== EXAMPLE ================
11
 * uint8_t payload[] = {5, 1, 2, 3};
12
 * // write 4 bytes from payload to the I2C device with address 0x23
13
 * error = _I2C_write(0x23, payload, 4);
14
 * \endcode
15
 * */
16
inline uint8_t w2bw_i2c_write(uint8_t addr,const uint8_t* data,uint8_t count){
17
    //set the I2C slave address to the write address
18
    I2C_setSlaveAddress(I2C0_W2BW_BASE,I2C_W2BW_ADDRESS_WRITE);
19
    //set the number of bytes to be sent
20
    I2C_setDataCount(I2C0_W2BW_BASE, count);
21
    //push the data to the I2C TX FIFO
22
    uint8_t i=0;
23
    for(i=0; i<count; i++){
24
        I2C_putData(I2C0_W2BW_BASE,data[i]);
25
    }
26
    //set the I2C mode to master
27
    I2C_setConfig(I2C0_W2BW_BASE, I2C_MASTER_SEND_MODE);
28
    //send the start condition
29
    I2C_sendStartCondition(I2C0_W2BW_BASE);
30
    //send the stop condition
31
    I2C_sendStopCondition(I2C0_W2BW_BASE);
32
    //wait until TX FIFO is empty
33
    while(I2C_getTxFIFOStatus(I2C0_W2BW_BASE)!=I2C_FIFO_TXEMPTY){
34
        ;
35
    }
36
    return 0;
37
}
38
#define _I2C_write w2bw_i2c_write

Das Programm scheint auch immer in der while loop stecken zu bleiben, 
e.g. die FIFO scheint nicht leer zu sein. Wenn ich mir die Register des 
I2C Moduls anschaue fällt auf, dass diese sich ändern sobald ich das 
Programm mit dem Debugger anhalte. Wenn das Programm normal läuft (also 
scheinbar in der while-loop stecken bleibt, zeigt die Register-Vorschau 
einen Transmit-FIFO status von 0 [also nichts in der Transmit-FIFO], 
wenn ich das Programm anhalte jedoch ändert sich die Register-Vorschau 
und zeigt einen Transmit-FIFO Status von 2 [also 2 bytes in der Transmit 
FIFO], zudem scheint das NACK interrupt bit gesetzt.

Weiss vielleicht jemand, was da los ist?

von PittyJ (Gast)


Lesenswert?

Zeile 18: müßte da nicht etwas von addr enthalten sein?

von Mductance (Gast)


Lesenswert?

PittyJ schrieb:
> Zeile 18: müßte da nicht etwas von addr enthalten sein?

Diese Zeile setzt die I2C Slave Adresse, addr ist ein pointer auf die 
Daten, die gesendet werden sollten.

von DerEinzigeBernd (Gast)


Lesenswert?

Mductance schrieb:
> addr ist ein pointer auf die
> Daten, die gesendet werden sollten.

Nö. Der heißt "data". addr ist kein Pointer, sondern ein uint8_t, und 
wird in Deiner Funktion nirgendwo verwendet.

von Mductance (Gast)


Lesenswert?

DerEinzigeBernd schrieb:
> Mductance schrieb:
>> addr ist ein pointer auf die
>> Daten, die gesendet werden sollten.
>
> Nö. Der heißt "data". addr ist kein Pointer, sondern ein uint8_t, und
> wird in Deiner Funktion nirgendwo verwendet.

Hmm, ok, das habe ich nun entsprechend geändert, allerdings ändert das 
nichts am Verhalten des uCs, die Adresse ist immer noch die gleiche 
under uC sendet weiterhin eine weitere Start-Condition nachdem er die 
zwei Bytes gesendet hat.

von DerEinzigeBernd (Gast)


Lesenswert?

Mductance schrieb:
> Hmm, ok, das habe ich nun entsprechend geändert,

Wie?

von Mductance (Gast)


Angehängte Dateien:

Lesenswert?

So, mittlerweile konnte ich herausfinden woran das Problem lag. Nachdem 
man das Stop-Condition bit mittels I2C_sendStopCondition gesetzt hat 
muss man eine Weile warten um sicherzustellen, dass die STOP condition 
auch richtig erzeugt wird, das kann man machen indem man das BB 
(Bus-Busy) bit pollt:
1
inline uint8_t w2bw_i2c_write(uint8_t addr,const uint8_t* data,uint8_t count){
2
    //set the I2C slave address to the write address
3
    I2C_setSlaveAddress(I2C0_W2BW_BASE,addr);
4
    //set the number of bytes to be sent
5
    I2C_setDataCount(I2C0_W2BW_BASE, count);
6
    //push the data to the I2C TX FIFO
7
    uint8_t i=0;
8
    for(i=0; i<count; i++){
9
        I2C_putData(I2C0_W2BW_BASE,data[i]);
10
    }
11
    //set the I2C mode to master
12
    I2C_setConfig(I2C0_W2BW_BASE, I2C_MASTER_SEND_MODE);
13
    //send the start condition
14
    I2C_sendStartCondition(I2C0_W2BW_BASE);
15
    //wait until TX FIFO is empty
16
    while(1){
17
        I2C_TxFIFOLevel state=I2C_getTxFIFOStatus(I2C0_W2BW_BASE);
18
        if(state==I2C_FIFO_TXEMPTY)
19
            break;
20
    }
21
    //send the stop condition
22
    I2C_sendStopCondition(I2C0_W2BW_BASE);
23
    while(I2C_isBusBusy(I2C0_W2BW_BASE))
24
        ;
25
    return 0;
26
}
27
#define _I2C_write w2bw_i2c_write

Zuvor gab es das Problem, dass sie Sensor-Library welche die 
w2bw_i2c_write interface Funktion benutzt mehrere I2C writes 
hintereinander aufruft. Der eine w2bw_i2c_write Aufruf kam dann bevor 
die Stop-Condition des vorigen Aufruds richtig auf den Bus gesetzt 
werden konnte. Durch das zusätzliche Warten am Ende der Funktion können 
dann mehrere I2C writes hintereinander richtig aufgerufen werden:

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.