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 | }
|