Forum: Mikrocontroller und Digitale Elektronik PIC32MX I2C Modul nicht initialisiert


von Isildur (Gast)


Lesenswert?

Hallo,

ich nutze das PIC32 Starterkit und versuche eine I2C Kommunikation 
aufzubauen.

Der Code sieht wie folgt aus:
1
#define _SUPPRESS_PLIB_WARNING 1
2
3
#include <p32xxxx.h>
4
#include <stdio.h>
5
#include <stdlib.h>
6
#include <plib.h>
7
8
9
#include <stdio.h>
10
#include <stdlib.h>
11
12
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
13
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
14
#define SYS_FREQ (80000000L)
15
16
#define GetSystemClock()           (SYS_FREQ)
17
#define GetPeripheralClock()       (SYS_FREQ/1)
18
#define GetInstructionClock()      (SYS_FREQ)
19
20
#define I2C_CLOCK_FREQ             100000
21
22
23
24
#define EEPROM_I2C_BUS              I2C1
25
#define EEPROM_ADDRESS              32        // 0b0100000 = 32 = 0x20 
26
27
int main()
28
{
29
    
30
    UINT8               i2cData[10];
31
    // erstes Bit -> read/write; 7-Bit Slave Adresse
32
    I2C_7_BIT_ADDRESS   SlaveAddress;
33
    int                 Index;
34
    int                 DataSz;
35
    UINT32              actualClock;
36
    BOOL                Acknowledged;
37
    BOOL                Success = TRUE;
38
    UINT8               i2cbyte;
39
40
    // Initialize debug messages (when supported)
41
    DBINIT();
42
43
    // Set the I2C baudrate
44
    actualClock = I2CSetFrequency(EEPROM_I2C_BUS, GetPeripheralClock(), I2C_CLOCK_FREQ);
45
    if ( abs(actualClock-I2C_CLOCK_FREQ) > I2C_CLOCK_FREQ/10 )
46
    {
47
        DBPRINTF("Error: I2C1 clock frequency (%u) error exceeds 10%%.\n", (unsigned)actualClock);
48
    }
49
50
51
    // Enable the I2C bus
52
    I2CEnable(EEPROM_I2C_BUS, TRUE);
53
54
    // Initialize the data buffer
55
    I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_ADDRESS, I2C_WRITE);
56
    i2cData[0] = SlaveAddress.byte;
57
    i2cData[1] = 0xFF;              // EEPROM location to program (high address byte)
58
    i2cData[2] = 0xFF;              // EEPROM location to program (low address byte)
59
    
60
    DataSz = 3;
61
62
63
    // Start the transfer to write data to the EEPROM
64
    if( !StartTransfer(FALSE) )
65
    {
66
        while(1);
67
    }
68
69
...
70
}

Beim Debuggen bleibt das Programm immer in der Schleife
1
if( !StartTransfer(FALSE) )
2
    {
3
        while(1);
4
    }

hängen.


Hier nochmal die bereitgestellte StartTransfer Funktion:

[c]
BOOL StartTransfer( BOOL restart )
{
    I2C_STATUS  status;
    Nop();
    Nop();
    Nop();
    // Send the Start (or Restart) signal
    if(restart)
    {
        I2CRepeatStart(EEPROM_I2C_BUS);
    }
    else
    {
        // Wait for the bus to be idle, then start the transfer
        while( !I2CBusIsIdle(EEPROM_I2C_BUS) );

        if(I2CStart(EEPROM_I2C_BUS) != I2C_SUCCESS)
        {
            DBPRINTF("Error: Bus collision during transfer Start\n");
            return FALSE;   // <- Hier wird FALSE zurückgegeben
        }
    }

    // Wait for the signal to complete
    do
    {
        status = I2CGetStatus(EEPROM_I2C_BUS);

    } while ( !(status & I2C_START) );

    return TRUE;
}

[\c]


Wo False zurückgegeben wird habe ich oben markiert. Scheinbar wird das 
Modul nicht richtig konfiguriert. Ich nutze ja das I2C1-Modul. Diese 
befinden sich beim PIC32MX795L an den Pins 84 und 86. Bei vorherigen 
Pics musste ich noch mittels Peripheral Pin select die Funktionen auf 
die jeweiligen Pins Mappen. Dies entfällt offenbar bei dem PIC32. Also 
einfach I2C Komponente an Pins 84 u. 86 und fertig!

Irgendwelche Verbesserungsvorschläge oder Ideen woran es liegen kann, 
dass ich immer in der Schleife hängen bleibe?

Danke und Gruß

von Isildur (Gast)


Lesenswert?

Die Pins befinden sich bei dem Starterkit auf Pins 84 und 86, beim PIC 
selbst auf 66 und 67, aber das ist beim Starterkit ja unerheblich!

von Isildur (Gast)


Lesenswert?

Habe jetzt mal für 100KHz den High Speed Mode aktiviert, ebenfalls ohne 
Erfolg!

von Isildur (Gast)


Lesenswert?

Niemand eine Ahnung, woran es liegen könnte, dass ich das Startbit nicht 
senden kann? Ich würde einen Softwarefehler fast ausschließen, dass das 
Senden des Startbits in nahezu allen LIBs genauso implementiert ist.

Die SCL1 und SDA1 Leitung hab ich über einen 3,9K PullUp einfach an die 
entsprechenden Leitung der I2C Komponente gehängt.

von Hameg (Gast)


Lesenswert?

Ist while(1); denn nicht eine Endlosschleife?

von Isildur (Gast)


Lesenswert?

Hameg schrieb:
> Ist while(1); denn nicht eine Endlosschleife?

richtig, hier bleibt er ja hängen. Wenn das Startbit richtig gesendet 
werden würde, sollte in diese Schleife ja idealerweise gar nicht in die 
Schleife springen.

Es muss etwas mit der Initialisierung des I2C Moduls zu tun haben.

Über
•
1
#define EEPROM_I2C_BUS              I2C1

habe ich ja (so hoffe ich) das I2C1 Modul ausgewählt. Ich bin mir 
unsicher ob das alles ist was ich tun muss.

Es gibt auch die weiteren Module wie

*          chn   :  I2C1A
*          chn   :  I2C2A
*          chn   :  I2C3A
*          chn 3  : I2C1
*          chn   :  I2C2
*

Was es damit auf sich hat ist mir noch nicht so ganz klar!

von PIC_fan (Gast)


Lesenswert?

Isildur schrieb:
> // Start the transfer to write data to the EEPROM
>     if( !StartTransfer(FALSE) )
>     {
>         while(1);
>     }


wenn ich das richtig deute bleibt er in der endlosschleife hängen.
WEIL:
 in der if anweisung hebst du das false wieder auf mit dem !

wenn start transfehr nicht FALSE ist dann

while(1)

da du deine initialisierung hinbekommst ist der start transfer richtig.

von Isildur (Gast)


Lesenswert?

Es wird in der while Schleife verweilt, weil in 
if(I2CStart(EEPROM_I2C_BUS) != I2C_SUCCESS)
 False zurückgegeben wird.

Ich habe das ganze jetzt mit I2C2 versucht (also nicht mit dem I2C1) und 
ich kann zumindest ein Byte übertragen. Leider wird nach dem ersten 
Adressbyte kein ACK-Bit gesendet.

Wird bei I2C grundsätzlich nach jedem gesendeten Byte ein ACK-Bit 
gesendet?
Wie kann es sein, dass I2C2 funktioniert, aber I2C1 nicht?

von Pic_Fan (Gast)


Lesenswert?

Isildur schrieb:
> Wie kann es sein, dass I2C2 funktioniert, aber I2C1 nicht?

das kann ich dir leider nicht sagen habe nie mit einem PIC gearbeitet 
der diese Auswahl hatte.

Isildur schrieb:
> Wird bei I2C grundsätzlich nach jedem gesendeten Byte ein ACK-Bit
> gesendet?

Ja, solange du werte Lesen möchtest.
Wenn du deine werte hast die die brauchst sendest du ein nack und es 
wird nicht weitergesendet.

von Chris B. (dekatz)


Lesenswert?

Isildur schrieb:

> Wie kann es sein, dass I2C2 funktioniert, aber I2C1 nicht?

Die I2C1-Pins 66 & 67 liegen auch die "alternativen" Ethernetsignale 
AETXEN & AETXCLK.
Die würde ich mal abschalten da nach einem Reset ungewiss ist, welche 
Einstellung vorhanden ist.
<DEVCFG3.FETHIO = 1> weist Ethernet die Default-Pinbelegung zu. Wenn 
dort nach einem Reset "0" steht, ist I2C1 blockiert.

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.