Forum: Mikrocontroller und Digitale Elektronik Problem mit PIC18 als Slave: Werde Daten nicht gesendet?


von Christian (Gast)


Lesenswert?

Hallo,

ich verzweifel gerade daran den PIC18F13K22 als I2C Slave aufzusetzen.
Ich finde den Fehler einfach nicht.
Der Master (auch ein PIC, aber nicht von mir programmiert) sendet nach 
Spannung ein 2x zyklisch mehrere Adressen (Startupphase). Alle Slaves 
die ihm in der Zeit antworten werden danach in der Betriebsphase auch 
weiterhin zyklisch abgefragt.
--> Spektrum TM1000 Telemetriemodul (RC Fernsteuerung)

Mein Slave sieht zwar seine Adresse (PIR1bits.SSPIF gesetzt) aber 
irgendwie scheint er keine gültigen Daten zu senden (er wird nicht in 
die Liste der Slaves mit aufgenommen).
Testweise habe ich bei einem Adressmatch mal den SSPBUF gelesen. Dort 
sollte doch eigentlich die Adresse des Slaves stehen. Aber der Vergleich 
schlägt fehl.
Hat jemand einen Tipp?
(nicht wundern über den I2C code in der Hauptroutine. Durch das ganze 
Testen habe ich viel hin und her kopiert. Soll eigentlich in die 
Interruptroutine (von der hier nur die while Schleife)

Hier der Code:
1
void initI2C(void)
2
{
3
    //set I2C  
4
5
    i2c_send_index = 0;
6
    SSPADD = SLAVE_POWERBOX;     // set slave address
7
    //SSPMSK = 0xFF;     // Only respond to my address ( All bits must match)
8
    SSPCON1bits.SSPM = 0b0110;  //I2C Slave mode, 7-bit address
9
    SSPCON1bits.CKP = 1;  //Release clock
10
    SSPCON1bits.SSPEN = 1;      // Enables I2C
11
    SSPSTATbits.SMP = 1;        //standard Speed mode
12
    SSPSTATbits.CKE = 0;        //Disable SMBus specific inputs
13
    SSPCON2bits.GCEN = 0;       //General call address disabled
14
    SSPCON2bits.SEN = 1;        //Clock stretching is enabled
15
    //Interrupt for I2C    
16
 //   IPR1bits.SSPIP = 1;         // Set SSP interrupt priority to high
17
    
18
    PIR1bits.SSPIF = 0;         // Clear interrupt flag
19
  //  PIE1bits.SSPIE = 1;         // Enable SSP interrupt
20
}
1
    while(1)
2
    {
3
        if (PIR1bits.SSPIF)
4
        {
5
        
6
        temp = SSPSTAT & 0b00101101; // Mask out unimportant bits in SSPSTAT 
7
        switch (temp)
8
        {
9
10
        // State 3: Read operation, last byte was an address, buffer is full.
11
        // SSPSTAT bits: S = 1, D_A = 0, R_W = 1, BF = 1
12
        // Start new read sequence
13
        case ( 0b00001101 ):
14
            temp2 = SSPBUF;      // Do a dummy read of SSPBUF -> BF is cleared
15
            i2c_send_index = 0; //reset index counter
16
            //+++++++++++++++++++++++++++++++++++++++++++++
17
            //WARUM IST DIESE BEDINGUNG UNWAHR? SOLLTE DOCH DIE ADRESSE DES SLAVES SEIN???????
18
            if (temp2 != SLAVE_POWERBOX) 
19
            {
20
                LED1 = LED_ON;               
21
             //   break;
22
            }
23
24
            LED2 ^= 1;
25
            do
26
            {
27
                SSPCON1bits.WCOL = 0;   // Clear WCOL flag
28
                SSPBUF = SLAVE_POWERBOX;//writeData[i2c_send_index];   // Write the data to the buffer
29
30
31
            }
32
            while ( SSPCON1bits.WCOL );  // Loop when there's a write collision
33
            
34
            i2c_send_index++;       //next Data Byte
35
            break;
36
        // State 4: Read operation, last byte was data, buffer is empty.
37
        // SSPSTAT bits: S = 1, D_A = 1, R_W = 1, BF = 0
38
        // continue sending
39
        case ( 0b00101100 ):
40
            do
41
            {
42
43
      
44
                SSPCON1bits.WCOL = 0;   // Clear WCOL flag
45
                SSPBUF = writeData[i2c_send_index];   // Write the data to the buffer
46
            }
47
            while ( SSPCON1bits.WCOL );  // Loop when there's a write collision
48
            i2c_send_index++;       //next Data Byte
49
            
50
            break;
51
52
        default:
53
            break;
54
55
     }
56
    i2c_send_index %= sizeof(writeData);
57
    SSPCON1bits.CKP = 1;    //Release Clock
58
    PIR1bits.SSPIF = 0;
59
    }
60
61
 }

von Christian (Gast)


Lesenswert?

Hallo,

ich habe vergessen: die zu übertragende Varaible heißt:
1
writeData = {SLAVE_POWERBOX, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

Sorry übrigens für den unausagekräftigen Titel. Kann ihn leider nicht 
mehr ändern

von Jens Martin (Gast)


Lesenswert?

Christian schrieb:
> Der Master (auch ein PIC, aber nicht von mir programmiert)
Womit du zwei Baustellen hast. Kannst du den einen Master selbst 
aufbauen (zum üben)?

Dann verstehe ich den Konzept nicht. Ein I2C Slave kann keine Daten 
senden. Der Master holt sich die ab.

Noch als Tipp: Reduziere den Code auf die nötigen I2C Funktionen. Mit 
einer simplen main wo nur senden und led on/off drin steht.
So als solltest du jemendem I2C in der Sprache C erklären.

Mir ist z.B nicht klar was SLAVE_POWERBOX ist oder ich habe die die 
Definition übersehen.

von Christian (Gast)


Lesenswert?

Hi,

Der Master PIC ist keine Baustelle, da es sich um ein  Produkt handelt 
(nennt sich Spektrum TM1000).
es handelt sich dabei um ein Telemetriemodul welches u.a. die über I2C 
empfangenen Daten an eine RC-Fernsteuerung sendet.

Der Master fragt beim einschalten einfach alle möglichen I2C Slave 
Adressen ab.
Die Slaves müssen dann Antworten (den als writeData definierten 
Zeichensatz übertragen. In den Bytes die mom. mit 0x00 gesetzt sind 
stehen später die Nutzdaten).
SLAVE_POWERBOX steht im header (habe ich nicht hier reinkopiert). Der 
ist mit 0x0a gesetzt.

Das Programm habe ich schon auf main mit while(1) reduziert. Hat leider 
nicht geholfen. Ich finde einfach keinen Fehler in meinem Programm.

Was mich mom. verwirrt ist das beim start einer neuern Sequenz (Master 
sendet Adresse) ja die Adresse im SSPBUF stehen müsste. Der Vergleich:
SSPBUF = 0x0a aber fehlschlägt.

von Jens Martin (Gast)


Lesenswert?

Christian schrieb:
> Der Master PIC ist keine Baustelle, da es sich um ein  Produkt handelt
> (nennt sich Spektrum TM1000).

Schon klar, aber du hast keine Möglichkeit zu prüfen was er empfängt.

Schau dir mal das Beispiel hier an:

http://ww1.microchip.com/downloads/en/DeviceDoc/i2c_slave.zip

Ist von:

http://www.microchip.com/CodeExamplesByFunc.aspx
(Function auf I2C eingegrenzt)

von Frank K. (fchk)


Lesenswert?

Besorge Dir einen Logic Analyzer und schau nach, was auf dem Bus 
passiert. Ansonsten ist das alles Raterei.

fchk

von Christian (Gast)


Lesenswert?

So, nachdem ich mit einen Logic Analyser gekauft habe (Logic Pirate für 
ca. 27 Euro ;-)  )

habe ich den Fehler gefunden.
Ich hatte im Prinzip geschrieben:
1
#define SLAVE_POWERBOX 0x0a  //die Adresse des Slaves
2
SSPADD = SLAVE_POWERBOX;

richtig ist aber:
1
#define SLAVE_POWERBOX 0x0a  //die Adresse des Slaves
2
SSPADD = SLAVE_POWERBOX<<1;  //bit0 wird nicht verwendet

(der PIC verwendet Bit1-7 vom SSPADD für die 7 bit Adressierung. Hatte 
ich überlesen...)

Vieleicht hift es ja jemanden nicht den gleichen Fehler zu machen.

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.