mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 16F88 als I2C Slave Kommunikationsfehler


Autor: S.Rau (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen & Frohes Neues :)

Ich habe mich in den letzten wochen mit dem 16F88 als I2C Slave 
auseinander gesetzt, und sämmtliche App.Notes(734,736) & Forenbeiträge 
durchgestöbert.
Leider alles ohne erfolg!

Mein Problem ist, das die Kommunikation vom Slave zum PC(Master) (Hab 
nen I2C <-> RS232 Wandler)
immer wieder abbricht. D.h. es kommen 10 fehlsendungen und 1 die 
funktioniert.
Der Wandler klappt bei anderen I2C Bausteinen einwandfrei.

Hier mal Codeschnippsel aus meinem Programm (CC5X):
// ***************************************************
// Mikrocontroller initialisieren
// ***************************************************
void InitPic(void)
{
    OSCTUNE = 0x00;
    OSCCON= 0b.0111.1110;            // Nutze Internen 8MHz OSC

    INTCON=0;                        // Interrupts aus
    SSPIF=0;                         // I²C Interrupt flag löschen                         
       
    PORTA = 0x00;                    // Ports resetten
    PORTB = 0x00;
    
    TRISA = 0b.0000.0001;            // I/O für PortA
    TRISB = 0b.0001.0010;            // I/O für PortB (RB1,RB4 -> I²C)
    
    //CCP1CON=0x00;                    // Comperatoren aus

    ANSEL = 0b.0000.0001;            // RA0 -> analogIn sonst Digital I/O
    ADCON1= 0b.1000.0000;            // <4:5> Vref= Vdd/Vss; <6> Fosc/8; <7> Daten Rechtsbündig
    ADCON0= 0b.0000.0000;            // <3:5> RA0 messen; <6:7> Fosc/8
    ADON = 1;                        // ADC einschalten
    
    SSPADD = NODE_ADDR;              // Slave Adresse des Linecatchers (I²C)
    SSPSTAT = 0;                     // I²C konfigurieren
    SSPCON = 0b.0011.0110;           

    PEIE = 1;                        // Interrupts (I²C erlauben)
    SSPIE = 1;
    GIE = 1;                         // Interrupts allgemein erlauben
}
// ***************************************************
// Interrupt
// ***************************************************
#pragma origin 4
interrupt InterruptRutine(void)             // Interruptroutine
{
    int_save_registers;                     // W, STATUS (und  PCLATH) retten
    char sv_FSR = FSR;                      // FSR sichern
    char temp_SSPSTAT;

    if(SSPIF)
    {
        CKP = 0;
        SSPIF = 0;
        
        temp_SSPSTAT = 0b.0010.1101;        // Unwichtige bit's maskieren
        temp_SSPSTAT &= SSPSTAT;            // und mit SSPSTAT verknüpfen (and)
        
        switch(temp_SSPSTAT)
        {
            // *************************
            // I²C Write operation
            // letztes Byte war ADRR
            // *************************            
            case 0b.0000.1001 :
                clearSSPBUF();
                if(SSPOV)
                {
                    SSPOV = 0;
                    clearSSPBUF();
                    goto EndSSPint;
                }
            
            // *************************
            // I²C Write operation
            // letztes Byte war DATA
            // *************************                    
            case 0b.0010.1001 :
                chan = ReadI2C();
                goto EndSSPint;                
                
            // *************************
            // I²C Read operation
            // letztes Byte war ADRR
            // *************************            
            case 0b.0000.1100 :   
                WriteI2C(150);                    
                //WriteI2C(ADCwertON[chan].low8);
                goto EndSSPint;                
                
            // *************************
            // I²C Read operation
            // letztes Byte war DATA
            // *************************
            case 0b.0010.1100 :
            //  WriteI2C(ADCwertON[chan].high8);
                WriteI2C(0);   
                goto EndSSPint;                 

            // *************************
            // Slave logik reset
            // (NACK vom Master)
            // *************************
            case 0b.0010.1000 :
                goto EndSSPint;             

            // *************************
            // I2C Fehler
            // Reinit...
            // *************************           
            default :
                while(1);
                
        }
                
        
EndSSPint:
        if(SSPOV)
        {
            SSPOV = 0;
            clearSSPBUF();
        }
        CKP = 1;       
    }
    
    FSR = sv_FSR;                           // FSR wiederherstellen 
    int_restore_registers;                  // W, STATUS (und PCLATH) Wiederherstellen
}

#pragma origin 100

// ***************************************************
// SSPBUF löschen, damit kein Overflow entsteht
// ***************************************************
void clearSSPBUF(void)
{
char t;
    t =  SSPBUF;
}
    
// ***************************************************
// Schreibe auf I2C Bus
// ***************************************************
void WriteI2C(char dat)
{
    while(BF);
    WCOL = 0;
    do
    {
        SSPBUF = dat;
    } while(WCOL);
        
    CKP = 1;
}
    
// ***************************************************
// Lese von I2C Bus
// ***************************************************
char ReadI2C(void)
{
    return(SSPBUF);
}


Die Funktion clearSSPBUF war ein versuch - klar das man keine extra 
funktion dafür braucht ;)


Falls mir jemand helfen könnte - wäre super!
Das while(1); (sollte) den eingeschalteten WDT auslösen

MfG
Stefan

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.