PIC18, bekomm I2C nicht ordentlich ans laufen

OP #3276031
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 :(
#3276044
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.
OP #3276051
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.
#3276088
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.
OP #3276125
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 ;)
OP #3276423
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
#3276501
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.
OP #3276544
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren