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


von S.Rau (Gast)


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):
1
// ***************************************************
2
// Mikrocontroller initialisieren
3
// ***************************************************
4
void InitPic(void)
5
{
6
    OSCTUNE = 0x00;
7
    OSCCON= 0b.0111.1110;            // Nutze Internen 8MHz OSC
8
9
    INTCON=0;                        // Interrupts aus
10
    SSPIF=0;                         // I²C Interrupt flag löschen                         
11
       
12
    PORTA = 0x00;                    // Ports resetten
13
    PORTB = 0x00;
14
    
15
    TRISA = 0b.0000.0001;            // I/O für PortA
16
    TRISB = 0b.0001.0010;            // I/O für PortB (RB1,RB4 -> I²C)
17
    
18
    //CCP1CON=0x00;                    // Comperatoren aus
19
20
    ANSEL = 0b.0000.0001;            // RA0 -> analogIn sonst Digital I/O
21
    ADCON1= 0b.1000.0000;            // <4:5> Vref= Vdd/Vss; <6> Fosc/8; <7> Daten Rechtsbündig
22
    ADCON0= 0b.0000.0000;            // <3:5> RA0 messen; <6:7> Fosc/8
23
    ADON = 1;                        // ADC einschalten
24
    
25
    SSPADD = NODE_ADDR;              // Slave Adresse des Linecatchers (I²C)
26
    SSPSTAT = 0;                     // I²C konfigurieren
27
    SSPCON = 0b.0011.0110;           
28
29
    PEIE = 1;                        // Interrupts (I²C erlauben)
30
    SSPIE = 1;
31
    GIE = 1;                         // Interrupts allgemein erlauben
32
}
1
// ***************************************************
2
// Interrupt
3
// ***************************************************
4
#pragma origin 4
5
interrupt InterruptRutine(void)             // Interruptroutine
6
{
7
    int_save_registers;                     // W, STATUS (und  PCLATH) retten
8
    char sv_FSR = FSR;                      // FSR sichern
9
    char temp_SSPSTAT;
10
11
    if(SSPIF)
12
    {
13
        CKP = 0;
14
        SSPIF = 0;
15
        
16
        temp_SSPSTAT = 0b.0010.1101;        // Unwichtige bit's maskieren
17
        temp_SSPSTAT &= SSPSTAT;            // und mit SSPSTAT verknüpfen (and)
18
        
19
        switch(temp_SSPSTAT)
20
        {
21
            // *************************
22
            // I²C Write operation
23
            // letztes Byte war ADRR
24
            // *************************            
25
            case 0b.0000.1001 :
26
                clearSSPBUF();
27
                if(SSPOV)
28
                {
29
                    SSPOV = 0;
30
                    clearSSPBUF();
31
                    goto EndSSPint;
32
                }
33
            
34
            // *************************
35
            // I²C Write operation
36
            // letztes Byte war DATA
37
            // *************************                    
38
            case 0b.0010.1001 :
39
                chan = ReadI2C();
40
                goto EndSSPint;                
41
                
42
            // *************************
43
            // I²C Read operation
44
            // letztes Byte war ADRR
45
            // *************************            
46
            case 0b.0000.1100 :   
47
                WriteI2C(150);                    
48
                //WriteI2C(ADCwertON[chan].low8);
49
                goto EndSSPint;                
50
                
51
            // *************************
52
            // I²C Read operation
53
            // letztes Byte war DATA
54
            // *************************
55
            case 0b.0010.1100 :
56
            //  WriteI2C(ADCwertON[chan].high8);
57
                WriteI2C(0);   
58
                goto EndSSPint;                 
59
60
            // *************************
61
            // Slave logik reset
62
            // (NACK vom Master)
63
            // *************************
64
            case 0b.0010.1000 :
65
                goto EndSSPint;             
66
67
            // *************************
68
            // I2C Fehler
69
            // Reinit...
70
            // *************************           
71
            default :
72
                while(1);
73
                
74
        }
75
                
76
        
77
EndSSPint:
78
        if(SSPOV)
79
        {
80
            SSPOV = 0;
81
            clearSSPBUF();
82
        }
83
        CKP = 1;       
84
    }
85
    
86
    FSR = sv_FSR;                           // FSR wiederherstellen 
87
    int_restore_registers;                  // W, STATUS (und PCLATH) Wiederherstellen
88
}
89
90
#pragma origin 100
91
92
// ***************************************************
93
// SSPBUF löschen, damit kein Overflow entsteht
94
// ***************************************************
95
void clearSSPBUF(void)
96
{
97
char t;
98
    t =  SSPBUF;
99
}
100
    
101
// ***************************************************
102
// Schreibe auf I2C Bus
103
// ***************************************************
104
void WriteI2C(char dat)
105
{
106
    while(BF);
107
    WCOL = 0;
108
    do
109
    {
110
        SSPBUF = dat;
111
    } while(WCOL);
112
        
113
    CKP = 1;
114
}
115
    
116
// ***************************************************
117
// Lese von I2C Bus
118
// ***************************************************
119
char ReadI2C(void)
120
{
121
    return(SSPBUF);
122
}


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

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.