Сделал еще один двухдневный подход к i2c slave на PIC. Сил и нервов уже никаких не осталось. Ладно, к делу. Есть сетап: pic18f25k22 читает байт из i2c, пишет на его место другой байт, читает снова и сверяет записанное и прочитанное.
Функция чтения: старт - байт адреса+бит записи - запись адреса регистра - рестарт - байт адреса+бит чтения - чтение значения регистра - стоп.
Функция записи - старт - байт адреса+бит записи - запись адреса регистра - запись значения в регистр - стоп.
Функции проверены-перепроверены на датчике цвета, предполагается, что этот поллер нормально работает. Когда слейв от него отключен, он спокойно пуляет в пустоту адреса, ничего не получает и т.д. Подключаем слейв - поллер тыркается в него и зависает.
Теперь слейв - pic16f1827. Все на прерываниях, пять условий в соответствии с AN734. В каждом условии сделал выгрузку в УАРТ одного байта. Судя по этой отладочной информации, первое и последнее условие, в которое попадает обработчик прерывания - это условие №3 - STATE 3: MASTER READ, LAST BYTE WAS AN ADDRESS
• S = 1 (Start condition occurred last)
• R/W = 1 (Master reading data from the slave)
• D/A = 0 (Last byte was an address)
А, да, еще важно - включен слейв-режим семибайтный с прерываниями на старте/стопе.
Код сетапа камня слейва:
- Код: Выделить всё • Развернуть
- //-----------------------------------------------------------------
 //-----------------------------------------------------------------
 //i2c setup
 
 //SSP1CON1 = 0b00011110;
 //SSP1CON1bits.WCOL
 //SSP1CON1bits.SSP1OV
 //SSP1CON1bits.SSP1EN
 SSP1CON1bits.CKP = 1; //enable clock
 SSP1CON1bits.SSPM3 = 1; //i2c
 SSP1CON1bits.SSPM2 = 1; //slave
 SSP1CON1bits.SSPM1 = 1; //7-bit address
 SSP1CON1bits.SSPM0 = 0; // w START-STOP interrupts
 
 SSP1ADD = I2C_ADDR;
 
 //SSP1STAT = 0b10000000;
 SSP1STATbits.SMP = 1; //1 = Slew rate control disabled for standard speed mode (100 kHz and 1 MHz)
 SSP1STATbits.CKE = 1; //0 = Disable SM bus� specific inputs
 
 
 //SSP1CON2 = 0x00;
 SSP1CON2bits.GCEN = 1; //0 = General call address disabled
 SSP1CON2bits.SEN = 1; //1 = Clock stretching enabled
 
 //SSP1CON3 = 0b00011000;
 SSP1CON3bits.BOEN = 1; //1 = SSPxBUF is updated and ACK is generated for a received address/data byte, ignoring the
 //state of the SSPxOV bit only if the BF bit = 0.
 SSP1CON3bits.SDAHT = 1; //1 = Minimum of 300 ns hold time on SDAx after the falling edge of SCLx
 SSP1CON3bits.AHEN = 0;
 SSP1CON3bits.DHEN = 0;
 
 //SSP1MSK = 0xFF;
 
 SSP1CON1bits.SSPEN = 1;
 SSP1STAT = 0x00;
 SSP1IF = 0;
 SSP1IE = 1;
 //-----------------------------------------------------------------
 //-----------------------------------------------------------------
 PEIE = 1;
 GIE = 1;
Код обработчика прерывания:
- Код: Выделить всё • Развернуть
- if (SSP1IF && SSP1IE)
 {
 // unsigned char SSPSTAT_TEMP = SSPSTAT & 0b00101101;
 if ((SSP1STATbits.S) && (!SSP1STATbits.R_nW) && (!SSP1STATbits.D_nA) && (SSP1STATbits.BF))
 //if (!(0b00001001 ^ SSPSTAT_TEMP))
 //STATE 1: MASTER WRITE, LAST BYTE WAS AN ADDRESS
 {
 while (!TXIF);
 TXREG = 'A';
 SSP1IF = 0;
 unsigned char xxxx = SSPBUF;
 if (!SSP1CON1bits.CKP) SSP1CON1bits.CKP = 1;
 i2c_set_register = 1;
 while (!TXIF);
 TXREG = '.';
 }
 /* else if ((SSP1STATbits.S) && (!SSP1STATbits.R_nW) && (SSP1STATbits.D_nA) && (SSP1STATbits.BF))
 //else if (!(0b00101001 ^ SSPSTAT_TEMP))
 //STATE 2: MASTER WRITE, LAST BYTE WAS DATA
 {
 while (!TXIF);
 TXREG = 'B';
 SSP1IF = 0;
 if (i2c_set_register)
 {
 i2c_register = SSPBUF;
 i2c_set_register = 0;
 } else
 {
 if (i2c_register < sizeof(CONTROL_REG))
 CONTROL_REG[i2c_register] = SSPBUF;
 }
 if (!SSP1CON1bits.CKP) SSP1CON1bits.CKP = 1;
 while (!TXIF);
 TXREG = ',';
 }
 else if ((SSP1STATbits.S) && (SSP1STATbits.R_nW) && (!SSP1STATbits.D_nA))
 //else if (!(0b00001100 ^ (SSPSTAT_TEMP & 00101100)))
 //STATE 3: MASTER READ, LAST BYTE WAS AN ADDRESS
 {
 while (!TXIF);
 TXREG = 'C';
 SSP1IF = 0;
 unsigned char xxxxx = SSP1BUF;
 //while (SSP1STATbits.BF) SSPBUF;
 while (SSP1CON1bits.WCOL)
 {
 SSP1CON1bits.WCOL = 0;
 SSPBUF = 0x11;//CONTROL_REG[i2c_register];
 }
 SSP1BUF = 'T';
 SSP1CON1bits.CKP = 1;
 //if (!SSP1CON1bits.CKP) SSP1CON1bits.CKP = 1;
 while (!TXIF);
 TXREG = '-';
 }
 else if ((SSP1STATbits.S) && (SSP1STATbits.R_nW) && (SSP1STATbits.D_nA) && (!SSP1STATbits.BF))
 //else if (!(0b00101100 ^ SSPSTAT_TEMP))
 //STATE 4: MASTER READ, LAST BYTE WAS DATA
 {
 while (!TXIF);
 TXREG = 'D';
 SSP1IF = 0;
 //while (SSP1STATbits.BF) SSPBUF;
 while (SSP1CON1bits.WCOL)
 {
 SSP1CON1bits.WCOL = 0;
 SSPBUF = 0x11;//CONTROL_REG[i2c_register];
 }
 if (!SSP1CON1bits.CKP) SSP1CON1bits.CKP = 1;
 while (!TXIF);
 TXREG = ';';
 }
 else if ((SSP1STATbits.S) && (SSP1STATbits.D_nA) && (!SSP1STATbits.BF) && (SSP1CON1bits.CKP))
 //else if ((!(0b00101000 ^ (SSPSTAT_TEMP & 00101001))) && SSP1CON1bits.CKP)
 //STATE 5: MASTER NACK
 {
 while (!TXIF);
 TXREG = 'E';
 SSP1IF = 0;
 //SSPBUF;
 i2c_register = 0x00;
 if (!SSP1CON1bits.CKP) SSP1CON1bits.CKP = 1;
 while (!TXIF);
 TXREG = '#';
 }
 else if ((SSP1STATbits.P))
 //STATE 6: STOP
 {
 while (!TXIF);
 TXREG = 'F';
 SSP1IF = 0;
 //SSPBUF;
 i2c_register = 0x00;
 if (!SSP1CON1bits.CKP) SSP1CON1bits.CKP = 1;
 while (!TXIF);
 TXREG = '/';
 }
 else
 {
 while (!TXIF);
 TXREG = 'G';
 SSP1CON1bits.SSPEN = 0;
 SSP1IF = 0;
 SSP1CON1bits.SSPEN = 1;
 while (!TXIF);
 TXREG = '&';
 }*/
 }
Ребят, помогите, а то уже застрелиться охота. Спасибо заранее.




 ))
))