Ich bin schon am Verzweifeln, schreibe bereits das komplette Projekt neu und hab keine ahnung mehr was da alles falsch läuft.

Meine Technik


Windows 7, MPLAB X mit XC8-Compiler
18F2420 als I2C Slave

Was ich brauche


Einen einfachen I2C-Slave von dem ich die ADC-Werte auslesen kann. I2C-Master ist ein Raspberry Pi, dessen I2C-Treiber meiner Meinung vollständig funktionsfähig sind.
Der I2C-Teil sollte leicht an SMbus orentiert sein, folglich: Der Erste wert der vom Master -> Slave geschrieben wird ist ein Position im Register, bei jedem folgenden Schreibe oder Lese-Befehl wird dieser Wert dann erhöht.

Meine Probleme

Undurchsichtige Softwareprobleme, undurchsichtige Dokumentation

Beispiel:

Code:
SSPBUF = 0x77;
funktioniert schon mehr oder weniger gut,

Code:
unsigned char I2cRegisterSelect;
// ....
I2cRegisterSelect = 0x77;
SSPBUF = I2cRegisterSelect;
Funktioniert nicht mehr? Dabei ist es egal ob man einen eigentlich richtigen Datentyp nimmt oder gleich int oder sonst was.
SSPBUF schreibt auserdem nicht das höchste Bit auf den Bus:

Code:
SSPBUF = 0x77;
Code:
sudo i2cdump -y 1 0x44
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
10: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
20: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
30: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
40: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
50: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
60: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
70: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
80: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
90: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
a0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
b0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
c0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
d0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
e0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
f0: 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77    wwwwwwwwwwwwwwww
Das passt, aber:

Code:
SSPBUF = 0xFF;
Code:
sudo i2cdump -y 1 0x44
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
10: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
20: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
30: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
40: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
50: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
60: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
70: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
80: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
90: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
a0: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
b0: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
c0: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
d0: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
e0: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
f0: 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f    ????????????????
Mein Quellcode :
(umfasst derzeit nur I2C, da dieser Teil noch immer hakt)
Code:
/* 
 * File:   main.c
 * Author: pointhi
 *
 * Created on 24. März 2013, 18:36
 */

//############### DEFINE CONSTANT

#define __OSC_INTOSC 1          // nutze Internen Oszillator

#define __I2C_ADRESS 0x88

//############### END OF DEFINE CONSTANT
#include <pic18.h>
#include <xc.h>

#ifdef __OSC_INTOSC
    #pragma config IESO = OFF, OSC = INTIO67, FCMEN = OFF               // CONFIG 1H        // Internal Oscilator
#else
    #pragma config IESO = OFF, OSC = HS, FCMEN = OFF                    // CONFIG 1H        // External Oscillator
#endif
#pragma config BOREN = OFF, PWRT = OFF                                  // CONFIG 2L
#pragma config WDT = OFF                                                // CONFIG 2H
#pragma config CCP2MX = PORTC, PBADEN = OFF, LPT1OSC = OFF, MCLRE = OFF // CONFIG 3H
#pragma config STVREN = OFF, XINST = OFF, DEBUG = OFF                   // CONFIG 4L
#pragma config CP0 = OFF, CP1 = OFF                                     // CONFIG 5L
#pragma config CPD = OFF, CPB = OFF                                     // CONFIG 5H
#pragma config WRT0 = OFF, WRT1 = OFF                                   // CONFIG 6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF                       // CONFIG 6H
#pragma config EBTR0 = OFF, EBTR1 = OFF                                 // CONFIG 7L
#pragma config EBTRB = OFF                                              // CONFIG 7H

unsigned char I2cRegisterSelect;
unsigned char I2cHelp;

void interrupt tc_int(void)
    {
    if(PIR1bits.ADIF == 1 && PIE1bits.ADIE == 1)    // ADC-Interrupt
        {
        PIR1bits.ADIF = 0;
        }

    if(PIR1bits.SSPIF == 1 && PIE1bits.SSPIE == 1)  // I2C-Interrupt
        {

        if(SSPSTATbits.BF)  // New Byte recive
            {
            if(!SSPSTATbits.R_NOT_W) // Master Write Data
                {
                if(SSPSTATbits.D_NOT_A) // Last recived Byte was Data
                    {
                    I2cRegisterSelect = SSPBUF;
                    }
                else    // Last recived Byte was Adress
                    {
                    I2cRegisterSelect = SSPBUF; // Update Register Select
                    }
                
                SSPCON1bits.CKP = 1;
                }
            else    // Master Request Data
                {
//                if(I2cRegisterSelect > 0x7F || I2cRegisterSelect == 0x00) // Test System
//                    {
//                    I2cRegisterSelect = 0x01;
//                    }
//                I2cRegisterSelect = 0x77;
                SSPBUF = 0x77;
//                SSPBUF = 0xFF;
                I2cRegisterSelect ++;

                SSPCON1bits.CKP = 1;
                }
            }
        
        PIR1bits.SSPIF = 0; // Reset Interrupt-Byte

        }
    }

int main() {

    #ifdef __OSC_INTOSC          // PLL Enable, 8MHz => 32MHz
        OSCCONbits.IRCF2    = 1;
        OSCCONbits.IRCF1    = 1;
        OSCCONbits.IRCF0    = 1;
        OSCTUNEbits.PLLEN   = 1;
    #endif

    TRISA   = 0b11111000;       // 1... Input
    TRISB   = 0b11110011;       // 0... Output
    //TRISC   = 0b11111110;
    TRISC   = 0b11111000;       // openpoint todo

    // Clear Ports to Default Value

    PORTA   = 0x00;
    PORTB   = 0x00;
    PORTC   = 0x00;

    LATA    = 0x00;
    LATB    = 0x00;
    LATC    = 0x00;

    // Init Interrupt

    INTCON  = 0x00;
    INTCON2 = 0x00;
    INTCON3 = 0x00;

    PIE1    = 0x00;
    PIE2    = 0x00;

    INTCONbits.PEIE = 1;        // Aktiviere Pheripherale Interrupts
    RCONbits.IPEN   = 0;        // Keine Interrupt Level (High/Low)
    INTCONbits.GIE = 1;         // Aktiviere Interrupt global

    // Init I2C

    I2cRegisterSelect = 0;

    SSPADD = __I2C_ADRESS;      // Set Adress

    SSPSTAT = 0x00;
//    SSPSTAT &= 0x3F;            // Delete Bit 6. and 7.
    
//    SSPSTATbits.SMP = 1;        // Slew Rate Control disabled for Standard Speed mode
//    SSPSTATbits.CKE = 1;        // Enable SMBus specific inputs


    SSPCON1 = 0x00;
//    SSPCON1 &= 0x2F;

//    SSPCON1 |= 0x0E;            // Slave mode, 7-bit adress with STart and Stop bit interrupts enabled
    SSPCON1 |= 0x06;            // Slave mode, 7-bit adress
    
    SSPCON1bits.SSPEN = 1;      // Enables the serial Port


    SSPCON2 = 0x00;

//    SSPCON2bits.GCEN = 1;       // Enable interrupt on general adress
//    SSPCON2bits.SEN = 1;        // Clock Streching is enabled for transmit and receive

    PIE1bits.SSPIE = 1;         // Aktiviere Interrupt für MSSP-Modul

    // Init ADC

//    PIE1bits.ADIE = 1;        // Aktiviere Interrupt für ADC
    
    while(1)
        {
        }
}
Ich hab keine ahnung was falsch läuft, brauche aber einen funktionierenden Slave aber in wenigen Wochen. Ich hab schon eine laufende I2C-Slave-Routine geschrieben, die sich dafür aber hin und wieder aufgehängt hat. Die Dokumentation hab ich auch schon mehrmals durchgelesen, ohne auf die Probleme zu stoßen.

mfg, pointhi