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