Forum: Mikrocontroller und Digitale Elektronik PIC32_I2C_MPLAB-C32-Compiler


von Chris B. (chrisb20)


Lesenswert?

Hallo zusammen,

ich mache gerade die ersten Schritte mit PIC32 Controller und habe 
hierbei noch ein paar Probleme.
Ich hab davor viel mit den Serien PIC12, PIC16 und PIC18 gemacht, bin 
also kein Neuling im Bereich PIC Controller.

Mein Problem ist folgendes, ich möchte mit dem Controller die I2C 
Schnittstelle initialisieren und Slaves ansprechen. Nach dem ich das 
PIC32 Reference Manual durch hatte, habeich festgestellt das die 
Architektur und der Umfang der Einstellungen beim PIC32 sehr viel größer 
sind als beim den anderen PICs bei dennen ich diese Schnittstelle 
bereits verwendet habe.

Mein Arbeitskollege meinte ich soll den Controller am besten mit dem C32 
Compiler programmieren. Ich habe bisher immer den Hi-Tech verwendet, 
daher ist mir der Compiler von den Befehlen neu.


Hat jemand von Euch schon einmal mit der I2C Schnittstelle bei den PIC32 
Controllern und dem C32 Compiler gearbeitet?
Ich bin über jede Hilfe dankbar.
Über die Googlesuche bin ich nicht wirklich weiter gekommen.

Den Controller den ich verwende ist der PIC32MX795F512L.

Vielen Dank.
Gruß Chris

von Chris B. (dekatz)


Lesenswert?

Es gibt im Verzeichniss worin der C32 installiert ist für fast jede 
Peripherie ein Beispiel. Auch wenn diese meist für ein bestimmtes 
DevBoard von MICROCHIP geschrieben sind, kann man diese relativ leicht 
anpassen.
I2C z.b. unter
....mplab32/v2.02/examples/plib_examples/i2c/i2c_master/source.....
ein Beispiel für den Zugriff auf ein 25LC256 EEPROM.

von Chris B. (dekatz)


Lesenswert?

Davon abgesehen würde ich mir MPLABX 1.85 und den dazugehörigen Compiler 
XC32 1.21 installieren da MPLAB (letzte Ver. 8.92) nicht mehr weiter 
unterstützt wird (und wahrscheinlich auch der C32 nicht).

von Chris B. (chrisb20)


Lesenswert?

Das habe ich gefunden, aber ich vermisse dabei z.B. eine Funktion mit 
der man die Schnittstelle initialisiert.

Mir ist klar das man dann sicher noch einiges anpassen muss, dennoch 
muss ja die Geschwindigkeit und verwendete Pins irgendwo eingerichtet 
werden.

von Chris B. (chrisb20)


Lesenswert?

Chris B. schrieb:
> Davon abgesehen würde ich mir MPLABX 1.85 und den dazugehörigen Compiler
> XC32 1.21 installieren da MPLAB (letzte Ver. 8.92) nicht mehr weiter
> unterstützt wird (und wahrscheinlich auch der C32 nicht).

Ah okay wusste ich noch gar nicht, dann steige ich vllt gleich auf das 
Programm und den Compiler um da das projekt auch später evtl 
softwareseitig erweitert werden muss.

von Chris B. (dekatz)


Lesenswert?

Chris Br schrieb:
> Das habe ich gefunden, aber ich vermisse dabei z.B. eine Funktion mit
> der man die Schnittstelle initialisiert.
>
> Mir ist klar das man dann sicher noch einiges anpassen muss, dennoch
> muss ja die Geschwindigkeit und verwendete Pins irgendwo eingerichtet
> werden.

In dem Beispiel gibt es auche eine Datei <HardwareProfile.h> wo unter 
anderem!!  <I2C_CLOCK_FREQU   100000 >  definiert ist.

Initialisiert wird mit
....actualClock = I2CSetFrequency(EEPROM_I2C_BUS, GetPeripheralClock(), 
I2C_CLOCK_FREQ);

von Chris B. (chrisb20)


Lesenswert?

> In dem Beispiel gibt es auche eine Datei <HardwareProfile.h> wo unter
> anderem!!  <I2C_CLOCK_FREQU   100000 >  definiert ist.
>
> Initialisiert wird mit
> ....actualClock = I2CSetFrequency(EEPROM_I2C_BUS, GetPeripheralClock(),
> I2C_CLOCK_FREQ);

Das ist alles?
Muss man keine Register wie das I2CxCON beschreiben, damit der 
Controller erstmal weiß ob er Master oder Slave ist?

Find ich seltsam das es von Micriochip dann ein Reference Manual gibt in 
dem das alles beschrieben ist wie welches Register beschrieben sein muss 
und in Ihrem Beispiel wenden Sie das gar nicht an.

von Chris B. (chrisb20)


Lesenswert?

So solangsam blick ich bei dem MPLABX und dem Controller durch.

Aktuell habe ich folgendes Problem mit dem I2C, wenn ich das CON 
Register beschrieben habe und anschließend die Startsequenz mit dem SEN 
bit einleite wird dieses gleich wieder deaktiviert und das BCL (Bus 
collision bit) wird gesetzt.

Jemand eine Idee woran das liegen kann?

von Chris B. (dekatz)


Lesenswert?

Chris Br schrieb:
> Das ist alles?
> Muss man keine Register wie das I2CxCON beschreiben, damit der
> Controller erstmal weiß ob er Master oder Slave ist?
>
> Find ich seltsam das es von Micriochip dann ein Reference Manual gibt in
> dem das alles beschrieben ist wie welches Register beschrieben sein muss
> und in Ihrem Beispiel wenden Sie das gar nicht an.

zum 1.:
Na gut ich habe mir jetzt nicht jedes Bit der I2C-SFR angesehen und auch 
nicht die Defaultwerte nach einem Reset angesehen, bin aber ziemlich 
sicher das ein simples I2C1CON = 0 und ein enstprechender Wert für die 
Busgeschwindigkeit in das enstsprechende Register das I2C-Modul in die 
Grundeinstellung  "MasterMode, 7-Bit-Adresse" schaltet. Das reicht für 
irgendwelche poppeligen EEPROM sicher aus ;-)

zum 2.:
Was die eingebundene <plib> alles kann, ist in <i2c.h> ersichtlich und 
das ist wesentlich mehr als die paar Einstellungen die für einen 
EEPROM-Zugriff notwendig sind (wie in dem angeführten Beispiel). Dort 
sind auch für jede Funktion Beispiel angeführt.

Falls es irgendwelche speziellen I2C-Eigenschaften gibt, welche NICHT 
durch die <plib>-Funktionen abgedeckt sind - dafür braucht man dann das 
Reference Manual. Aber dann die ausführliche Version (DS61116E) und 
nicht das allgemeine, wo die Sektion "I2C" gerade mal das Blockdiagramm 
und die paar Kontrollregister enthält.

von Chris B. (chrisb20)


Lesenswert?

So ich bin inzwischen einen Schritt weiter gekommen.

Ich hab jetzt mal mithilfe der plib.h ein Programm geschrieben das 
scheinbar auch durchläuft, aber am Port selbst kann ich mit dem Oszi 
keinerlei Pegeländerungen messen.

Hier einmal mein Programm, wenn jemand etwas findet was ich nicht 
beachtet habe wäre ich für Eure Hilfe dankbar.

Hier die ist der code meiner main.c
1
#include <p32xxxx.h>
2
#include <plib.h>
3
#include <peripheral/i2c.h>
4
#include "init.h"
5
6
7
// Configuration Bit settings
8
// SYSCLK = 80 MHz (8MHz Crystal / FPLLIDIV * FPLLMUL / FPLLODIV)
9
// PBCLK = 80 MHz (SYSCLK / FPBDIV)
10
// Primary Osc w/PLL (XT+,HS+,EC+PLL)
11
// WDT OFF
12
// Other options are don't care
13
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
14
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
15
#define SYS_FREQ (80000000L)
16
17
#define CCLK                      (SYS_FREQ)
18
#define PBCLK                     (SYS_FREQ/8)
19
20
#define Fsck 375000
21
#define BRG_VAL (PBCLK/2/Fsck)
22
23
#define Nop() asm( "nop" )
24
 
25
  UCHAR8                 SlaveAddress;
26
  char                   i2cData[10];
27
  int                    DataSz;
28
29
30
void i2c_wait(unsigned int cnt)
31
{
32
while(--cnt)
33
{
34
Nop();
35
Nop();
36
}
37
}
38
39
40
void main(void)
41
{
42
43
    init();
44
45
    OpenI2C2( I2C_EN, BRG_VAL );
46
47
    SlaveAddress = 0x57;            // 1010 111 0
48
49
    i2cData[0] = (SlaveAddress << 1) | 0;
50
    i2cData[1] = 0x0A;
51
    i2cData[2] = 0x00;
52
    i2cData[3] = 0xAA;
53
    DataSz = 4;
54
55
    StartI2C2();            // Sende das Start Bit
56
    IdleI2C2();             //Warten bis Ende
57
58
    int Index = 0;
59
    while(DataSz)
60
    {
61
        MasterWriteI2C1(i2cData[Index++]);
62
        IdleI2C2();
63
64
        DataSz--;
65
66
        //ACKSTAT is 0 when slave acknowledge. if 1 then slave has not
67
        //acknowlede the data
68
        if(I2C2STATbits.ACKSTAT)
69
            break;
70
    }
71
72
    StopI2C2();
73
    IdleI2C2();
74
75
    while(1)
76
    {
77
        i2c_wait(10);
78
79
        StartI2C2();
80
        IdleI2C2();
81
82
        MasterWriteI2C2(i2cData[0]);
83
        IdleI2C2();
84
85
        if(I2C2STATbits.ACKSTAT == 0)
86
        {
87
            StopI2C2();
88
            IdleI2C2();
89
90
            break;
91
        }
92
93
        StopI2C2();
94
        IdleI2C2();
95
    }
96
97
    //Now Readback the data from the serial eeprom
98
99
    i2cData[0] = (SlaveAddress << 1) | 0;
100
    i2cData[1] = 0x05;
101
    i2cData[2] = 0x40;
102
    DataSz = 3;
103
104
    StartI2C2();
105
    IdleI2C2();
106
107
    Index = 0;
108
    while(DataSz)
109
    {
110
        MasterWriteI2C2(i2cData[Index++]);
111
        IdleI2C2();
112
113
        DataSz--;
114
        //ACKSTAT is 0 when slave acknowledge. if 1 then slave has not
115
        //acknowlede the data
116
        if(I2C2STATbits.ACKSTAT)
117
            break;
118
    }
119
120
    //now send a start sequence again
121
    RestartI2C2();
122
    IdleI2C2();
123
124
    MasterWriteI2C2((SlaveAddress << 1)| 1);
125
    IdleI2C2();
126
127
    unsigned char i2cbyte;
128
    i2cbyte = MasterReadI2C2();
129
130
    StopI2C2();
131
    IdleI2C2();
132
133
    if(i2cbyte != 0xAA)
134
    {    
135
        while(1)                //Error
136
        {
137
            PORTDbits.RD1 = 1;
138
        }
139
    }
140
141
    while(1)                    //Success
142
    {
143
        PORTBbits.RB10 = 1;
144
    }
145
146
}

und hier noch die init.c
1
#include <p32xxxx.h>
2
3
void init(void)
4
{
5
    AD1PCFG = 0xFFFF;                           // PORTS auf Digital umschalten
6
    
7
    TRISBbits.TRISB10 = 0;                      // TRIS Register für LED
8
    TRISDbits.TRISD1 = 0;                       // TRIS Register für LED
9
    TRISDbits.TRISD2 = 0;                       // TRIS Register für LED
10
    PORTBbits.RB10 = 0;                         // LED = 0 setzen
11
    PORTDbits.RD1 = 0;                          // LED = 0 setzen
12
    PORTDbits.RD2 = 0;                          // LED = 0 setzen
13
14
    TRISAbits.TRISA15 = 1;      // PORT RA14 als Eingang definieren --> SCL1
15
    TRISAbits.TRISA14 = 0;      // PORT RA15 als Eingang definieren --> SDA1
16
    LATA = 0;
17
//    TRISAbits.TRISA2 = 1;      // PORT RA14 als Eingang definieren --> SCL2
18
//    TRISAbits.TRISA3 = 1;      // PORT RA15 als Eingang definieren --> SDA2
19
20
}

Dieses Programm ist ein example von Microchip, von dort ist alles bis 
auf die Port Init und dort liegt vermutlich auch das Problem.

Danke schonmal im Vorraus.

Gruß Chris

von holger (Gast)


Lesenswert?

>aber am Port selbst kann ich mit dem Oszi
>keinerlei Pegeländerungen messen.

Und wo ist der Pegel? Mach mal Pullups auf SDA und SCL.

von Chris B. (chrisb20)


Lesenswert?

holger schrieb:
>>aber am Port selbst kann ich mit dem Oszi
>>keinerlei Pegeländerungen messen.
>
> Und wo ist der Pegel? Mach mal Pullups auf SDA und SCL.

Die Pullups sind drauf 4,7k gegen 3,3V zu SDA und zu SCL.
Der Pegel ist also immer auf 3,3V und ändert sich auch nicht.
Hab das programm auch mal mit dem Debugger durchgearbeitet, hier hat 
sich aber auch nichts geändert.

Was ich sehr komisch finde ist das der Controller die Acknowledge abfrag 
durchläuft obwohl der Bus eindeutig high ist.

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.