Forum: Mikrocontroller und Digitale Elektronik PIC18, bekomm I2C nicht ordentlich ans laufen


von Lena R. (eny)


Lesenswert?

Hallo,

komm irgendwie garnicht weiter mit dem I2C Bus am PIC18F2523.
MPLAB X, XC 8 Compiler, PicKit3.

Am I2C Bus hängt ein 12bit DA Wandler.

Hier erstmal der Code:
1
/*
2
 * File:   newmain.c
3
 * Author: Lena
4
 *
5
 * Created on 6. August 2013, 20:06
6
 */
7
8
#include <xc.h>
9
#include <plib/i2c.h>
10
11
12
13
// CONFIG1H
14
#pragma config OSC = HS         // Oscillator Selection bits (HS oscillator)
15
#pragma config WDT = OFF
16
17
#define _XTAL_FREQ 4000000
18
19
20
#define I2C_V1
21
#define I2C_IO_V1 
22
23
void main() {
24
25
26
    TRISA = 0xFF;   //Port A als Eingang
27
28
    TRISC = 0xFF;   //Port C als Eingang
29
    PORTC = 0x00;
30
31
    OpenI2C(MASTER, SLEW_OFF);
32
    SSPADD = 0x09;  //I²C Baud = 100kHz
33
34
    StartI2C();
35
    IdleI2C();
36
    WriteI2C(0x20); //Adresse vom Slave
37
    IdleI2C();
38
    WriteI2C(0xCF); //Modus MAX & erste 4 Databits
39
    IdleI2C();
40
    WriteI2C(0xFF); //Databyte
41
    IdleI2C();
42
    StopI2C();
43
44
45
    while(1)
46
    {}
47
}

Leider funktioniert das nicht.

Naja, es funktioniert schon, wenn ich vorher ein Programm einspiel, was 
ähnliches macht und auch für die Hardware geschrieben ist.
Sprich die Hardware ist ok.
Wenn ich dann aber den PIC resette und mein Programm drin ist, dann 
gehts nicht.
Nochmal genauer:

1. Fremdes Programm rein: funktioniert
2. Mein Prog rein: funktioniert auch
3. Strom aus oder Erase
4. Strom an: Geht nicht
5. Mein Prog nochmal rein: Geht nicht
6. Fremdes Prog rein: Geht...
7. goto Punkt 2 ;)

Habe schon alle SFR verglichen, aber kein Unterschied feststellen 
können.

Darf das fremde Programm leider nicht hier posten.

Im Grunde kann es ja nur irgendeine Config oder Einstellung in den 
Registern sein.
Habe die Datenblätter und die i2c.h schon ein paar mal durch jetzt, aber 
ich seh im obigen Code keinen Fehler oder irgendwas fehlendes. Ist auch 
eigentlich nur ein ganz simples Programm zum testen und lernen erstmal.

Weiß nicht weiter grad :(

von Jens P. (picler)


Lesenswert?

Schaue noch mal im Datenblatt ob I²C richtig initialsiert ist. Nur ein 
Register scheint mir etwas wenig zu sein. Habe aber gerade keine 
Vergleichsmöglichkeit mit meinen Programmen.

Lena R. schrieb:
> OpenI2C(MASTER, SLEW_OFF);
>     SSPADD = 0x09;  //I²C Baud = 100kHz

Das kann nicht funktionieren. Du öffnest erst I²C und danach definierst 
du das Register. Ob der ganze C-Quatsch drumherum richtig ist kann ich 
dir aber nicht sagen, ich nehme lieber ASM.

von Lena R. (eny)


Lesenswert?

1
void OpenI2C( unsigned char sync_mode, unsigned char slew )
2
{
3
  SSPSTAT &= 0x3F;                // power on state 
4
  SSPCON1 = 0x00;                 // power on state
5
  SSPCON2 = 0x00;                 // power on state
6
  SSPCON1 |= sync_mode;           // select serial mode 
7
  SSPSTAT |= slew;                // slew rate on/off 
8
9
  I2C_SCL = 1;
10
  I2C_SDA = 1;
11
  SSPCON1 |= SSPENB;              // enable synchronous serial port 
12
13
}
Von daher kein Unterschied welche Reihenfolge.

von Jens P. (picler)


Lesenswert?

SSPADD = 0x09;
  SSPCON1 = 0x08;
  I2C_SCL = 1;                       // ?
  I2C_SDA = 1;                     // ?
  SSPCON1 = 0x28;              // enable synchronous serial port


Sollte zum initialisieren ausreichen. Danach Bus übernehmen und los 
gehts...

PS: Ich habe die Werte für die Register mal von Hand festgelegt, weil 
ich mir nicht sicher bin, ob die Übergabe richtig ist. Ich kenne mich 
mit nicht so sehr aus.

von Lena R. (eny)


Lesenswert?

1
    SSPADD = 0x09;  //I²C Baud = 100kHz
2
    SSPCON1 = 0x08;
3
    I2C_SCL = 1;                       // ?
4
    I2C_SDA = 1;                     // ?
5
    SSPCON1 = 0x28;              // enable synchronous serial port
6
    StartI2C();
7
    IdleI2C();
8
    WriteI2C(0x20); //Adresse vom Slave
9
    IdleI2C();
10
    WriteI2C(0xCF); //Modus MAX & erste 4 Databits
11
    IdleI2C();
12
    WriteI2C(0xFF); //Databyte
13
    IdleI2C();
14
    StopI2C();
So funktionierts auch nicht.

Was ist mit "Bus übernehmen" gemeint?

Sorry, lerne noch ;)

von Jens P. (picler)


Lesenswert?

Auch wenn es praktisch ist, fertige Routinen einfach zu kopieren, um so 
problematischer ist es bei Problemen.

Arbeite dich mal durch die Seite von Sprut www.sprut.de

Da gibt es unter http://www.sprut.de/electronic/pic/grund/i2c.htm eine 
recht gute Einführung in den I²C-Bus.

Lena R. schrieb:
> Was ist mit "Bus übernehmen" gemeint?

Das ist dort alles recht gut erklärt.

von Frank M. (frank_m35)


Lesenswert?

Du sagst du hast ein funktionierendes Programm, warum schaust du nicht 
einfach bei dem wie es dort gemacht wird?

Woran merkst du denn, dass es nicht funktioniert? (also ab wann hängt 
er?)

von holger (Gast)


Lesenswert?

Welcher DA Wandler?

von Lena R. (eny)


Lesenswert?

1
void main() {
2
3
//    delay(100);
4
    TRISA = 0xFF;   //Port A als Eingang
5
//
6
    TRISC = 0xFF;   //Port C als Eingang
7
    TRISCbits.RC3 = 1;
8
    TRISCbits.RC4 = 1;
9
10
//    PORTC = 0x00;
11
12
13
    SSPADD = 0x09;  //I²C Baud = 100kHz
14
    SSPCON1 = 0x08;
15
    SSPCON1bits.SSPEN = 1;
16
    SSPCON2bits.SEN = 1;
17
    while(!PIR1bits.SSPIF);
18
    PIR1bits.SSPIF = 0;
19
    SSPBUF = 0x20;
20
    while(!PIR1bits.SSPIF);
21
    PIR1bits.SSPIF = 0;
22
    SSPBUF = 0xCF; //Byte 1
23
    while(!PIR1bits.SSPIF);
24
    PIR1bits.SSPIF = 0;
25
    SSPBUF = 0xFF; //Byte 2
26
    while(!PIR1bits.SSPIF);
27
    PIR1bits.SSPIF = 0;
28
    SSPCON2bits.SEN = 0;
29
    SSPCON1bits.SSPEN = 0;

Haargenau nach Anleitung von Sprut und auch nochmal mit dem Datenblatt 
abgeglichen.

Das andere Programm ist für CCS geschrieben, kenn ich nicht, hab ich 
allerdings nach Recherche alles so gut es geht übernommen.

D/A Wandler ist MAX5812L
Im obigen Beispiel sollten eigentlich 5V rauskommen.

Das Einzige was ich im anderen Programm nicht versteh ist:
#byte portc = 0xF82
Was bedeutet das? Aus dem CCS PDF wird mir das nicht wirklich klar.
SDA und SCL liegen ja an Port C

von Frank M. (frank_m35)


Lesenswert?

du hast ein PicKit 3, also Debugge dein Programm doch einfach. Wo bleibt 
der PIC hängen? Oder läuft er durch?

du kannst auch noch das ACKSTAT abfragen um zu sehen ob er überhaupt 
antwortet, so in der Art:
http://www.microchip.com/forums/tm.aspx?high=&m=536035&mpage=1#536095

und dann eben falls nicht mit einem Stop anhält, damit du es auch 
mitbekommst, dass es nicht klappt.

Ebenso kannst du mal noch die anderen Register überprüfen, d.h. checken 
ob eine Write Collision (WCOL Bit) aufgetreten ist etc.

Stimmen denn die 4MHz? (also nicht dass er nachher mit 32MHz läuft 
(kannst ja mal sspadd dementsprechend ändern zum ausprobieren))

Hast du mal die alternative Adresse versucht (falls Vadd gegen VDD 
geschalten ist)?

Sende mal ein Stop vor dem Start befehl.

von Lena R. (eny)


Lesenswert?

Danke für die Hilfe Frank.
Habs jetzt vorerst selbst rausgefunden:

    SSPADD = 0x09;  //I²C Baud = 100kHz
    SSPCON1 = 0x08;
    SSPCON1bits.SSPEN = 1;
    SSPCON2bits.SEN = 1;
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPBUF = 0x20;
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPBUF = 0x40; //Byte 1
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPBUF = 0x00; //Byte 2
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPCON2bits.SEN = 0;
    SSPCON1bits.SSPEN = 0;

als Initialisierung in void main();

Dann kann ich meine Werte übertragen:

    SSPCON1bits.SSPEN = 1;
    SSPCON2bits.SEN = 1;
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPBUF = 0x20;
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPBUF = b1; //Byte 1
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPBUF = b2; //Byte 2
    while(!PIR1bits.SSPIF);
    PIR1bits.SSPIF = 0;
    SSPCON2bits.SEN = 0;
    SSPCON1bits.SSPEN = 0;

Scheint irgendwas spezifisch für den MAX D/A zu sein.
Wenn ich es nicht überlesen habe, steht davon nix im Datenblatt...

Mal schauen ob ich es rausfinde.

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.