Digital SM Part II: I2C PIC18F4550 Slave and PIC18F4550 continued
In part I, I wrote about the problem with receiving multiple bytes from slave. I rewrote both master and slave and discovered that after the first read, the next reads commands just aren't received by the slave. So I altered both the master and slave code in order to read all PIC18F4550 ports.

I changed the code for the slave. It now uses interrupts. When it receives the 'command byte' F6 from the master, it collects data from PORT A-E and stores it in an internal buffer and it calculates a checksum of 2 bytes. Now each time the master asks to read a byte, it will return a byte from this buffer: PORT A, ... PORT E, checksum high byte, checksum low byte.

#include <p18f4550.h> #include <stdio.h> #include <stdlib.h> #include <i2c.h> #pragma config PLLDIV = 5 // 20 MHz Oscillator #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // 48 MHz CPU-CLK #pragma config FOSC = HSPLL_HS // Highspeed with phase locked loop //#pragma config FOSC = HS // Highspeed, no phase locked loop #pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config DEBUG = OFF //#ifdef __DEBUG #pragma config PWRT = OFF #pragma config WDT = OFF, WDTPS = 1024 //#else // #pragma config PWRT = ON // #pragma config WDT = ON, WDTPS = 32768 //#endif #pragma config BOR = OFF, BORV = 0 #pragma config VREGEN = ON #pragma config MCLRE = OFF #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = OFF #pragma config STVREN = ON #pragma config LVP = OFF #pragma config ICPRT = ON//OFF #pragma config XINST = OFF #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF #pragma config CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTRB = OFF #define _XTAL_FREQ 20000000 //void low_isr (void); void high_isr(void); unsigned char databyte; unsigned char status = 0; unsigned char readIndex = 0; unsigned char writeIndex = 0; unsigned char R_CNT = 0; void delay_sec(unsigned char sec); void delay_msec(unsigned char msec); void leds_test(void); void writeByte(void); unsigned char I2C_Send[7]; unsigned char I2C_Recv[21]; #pragma code low_vector=0x08 //High interrupt priority starts at 0x08 void high_interrupt(void) { _asm GOTO high_isr _endasm } #pragma code #pragma interrupt high_isr void high_isr(void) { unsigned int checksum = 0; unsigned char data = 0; if (PIR1bits.SSPIF) { if (SSPSTATbits.S) // start bit has been detected last { status = 0; if (SSPSTATbits.R_W == 0) // master write operation { if (SSPSTATbits.BF) { data = SSPBUF; if (SSPSTATbits.D_A == 0) //last byte was an address byte { //PORTD = 1; status = 1; readIndex = 0; writeIndex = 0; } else { if (data == 0xF6) { checksum = 0; writeIndex = 0; I2C_Send[0] = 0b11000011; // test data, can be replaced by PORTA; I2C_Send[1] = 0b10011001; // test data, can be replaced by PORTB; I2C_Send[2] = 0b00001111; // test data, can be replaced by PORTB; I2C_Send[3] = 0b11110000; // test data, can be replaced by PORTD; I2C_Send[4] = 0b11100111; // test data, can be replaced by PORTE; checksum += I2C_Send[0]; checksum += I2C_Send[1]; checksum += I2C_Send[2]; checksum += I2C_Send[3]; checksum += I2C_Send[4]; I2C_Send[5] = checksum >> 8; // high byte I2C_Send[6] = (checksum << 8) >> 8; // low byte writeIndex = 0; R_CNT++; } status = 2; //PORTD = 2; if (readIndex < 20) { I2C_Recv[readIndex] = data; //PORTD = I2C_Recv[readIndex]; readIndex++; } } SSPCON1bits.CKP = 1; } } else // master read operation { if (SSPSTATbits.D_A == 0)//last byte was an address byte { if (SSPSTATbits.BF) { data = SSPBUF; } SSPBUF = I2C_Send[writeIndex++]; if(writeIndex >= 7) { writeIndex =0; } //PORTD = 0b11000011; status = 3; SSPCON1bits.CKP = 1; } else if (SSPSTATbits.BF) { data = SSPBUF; status = 4; writeByte(); writeIndex++; SSPCON1bits.CKP = 1; } else if(!SSPCON1bits.CKP){ writeByte(); writeIndex++; SSPCON1bits.CKP = 1; } } } PORTD = R_CNT; PIR1bits.SSPIF = 0; } } void writeByte(void) { PORTD = 0b11110000; SSPCON1bits.WCOL = 0; SSPBUF = 0b11000011; while (SSPCON1bits.WCOL) { SSPCON1bits.WCOL = 0; SSPBUF = 0b10000011; PORTD = 0b11001101; } PORTD = 0b11110011; } /* #pragma code low_vector=0x18 //Low interrupt priority starts at 0x18 void low_interrupt(void) { _asm GOTO low_isr _endasm } #pragma code #pragma interrupt low_isr void low_isr (void) { PORTD = 3; if(PIR1bits.SSPIF) //Timer0 interrupt { PIR1bits.SSPIF = 0; PORTD = 4; } } */ void main(void) { unsigned char sync_mode = 0, slew = 0, add1, status, temp, w, length = 0; unsigned char slaveEvenAddress = 0xA2; unsigned char slaveOddAddress = 0xA2 | 0x01; unsigned char command = 0x00; unsigned char counter = 0x00; unsigned char counter2 = 0x00; unsigned char slaveData = 0x00; unsigned char mask = 0x00; PORTA = 0; TRISA = 0b00000000; // PORTD all outputs PORTA = 0b11111111; /* Two pins are used for data transfer: ? Serial clock (I2C_SCL) ? RB1/AN10/INT1/SCK/I2C_SCL ? Serial data (I2C_SDA) ? RB0/AN12/INT0/FLT0/SDI/I2C_SDA The user must configure these pins as inputs by setting the associated TRIS bits. */ ADCON1 = 0b00001111; //AN0...AN12 as digital I/O TRISB = 0b00000011; //RB0...RB1 as digital inputs, others output PORTB = 0; PORTB = 0b11111100; PORTC = 0; TRISC = 0b00000000; // PORTD all outputs PORTC = 0b11111111; PORTD = 0; TRISD = 0b00000000; // PORTD all outputs PORTD = 0b11111111; PORTE = 0; TRISE = 0b00000000; // PORTD all outputs PORTE = 0b11111111; leds_test(); for (w = 0; w < 20; w++) { I2C_Recv[w] = 0; I2C_Send[w] = 0b11000011; } CloseI2C(); //close i2c if was operating earlier //------------------------INITIALISE THE I2C MODULE FOR MASTER MODE WITH 100KHz --------------------------- SSPCON1 = 0; SSPCON2 = 0; SSPSTAT = 0; SSPSTATbits.SMP = 1; // slew rate is disabled SSPSTATbits.CKE = 1; // enable SM SSPCON1bits.CKP = 1; // Release clock SSPCON2bits.SEN = 1; // 0 =Clock stretching is disabled //SSPCON1 = 0b00101110;// I2C Slave mode, 7-bit address with Start and Stop bit interrupts enabled(2) SSPCON1 = 0b00100110; // I2C Slave mode, 7-bit address SSPSTATbits.SMP = 1; // slew rate is disabled SSPADD = slaveEvenAddress; //initialze slave address PORTD = 1; PIE1bits.SSPIE = 1; //SSPIE: Master Synchronous Serial Port Interrupt Enable bit INTCONbits.PEIE = 1; //Enable all peripheral interrupts INTCONbits.GIE = 1; //Enable global interrupts PORTD = 2; while (1) { } while (1) { PORTD = 2; while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master temp = ReadI2C(); if (temp == slaveEvenAddress) { PORTD = 3; //********************* Data reception from master by slave ********************* do { while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master I2C_Recv[length++] = getcI2C(); // save byte received PORTD = PORTD + 1; } while (length != 20); PORTD = 4; //******************** write sequence from slave ******************************* while (SSPSTATbits.S != 1); //wait untill STOP CONDITION PORTD = 5; //********************* Read the address sent by master from buffer ************** while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master temp = ReadI2C(); if (temp == slaveEvenAddress) { PORTD = 6; command = ReadI2C(); PORTD = command; slaveData++; } while (DataRdyI2C() == 0); //WAIT UNTILL THE DATA IS TRANSMITTED FROM master PORTD = 7; temp = ReadI2C(); if (temp == slaveOddAddress) { PORTD = 8; } else { PORTD = temp; while (1) { } } PORTD = 10; temp = SSPBUF; slaveData = 0b11000011; /* bit 7 SMP: Slew Rate Control bit In Master or Slave mode: 1 = Slew rate control disabled for Standard Speed mode (100 kHz and 1 MHz) 0 = Slew rate control enabled for High-Speed mode (400 kHz) bit 6 CKE: SMBus Select bit In Master or Slave mode: 1 = Enable SMBus specific inputs 0 = Disable SMBus specific inputs bit 5 D/A: Data/Address bit In Master mode: Reserved. In Slave mode: 1 = Indicates that the last byte received or transmitted was data 0 = Indicates that the last byte received or transmitted was address bit 4 P: Stop bit(1) 1 = Indicates that a Stop bit has been detected last 0 = Stop bit was not detected last bit 3 S: Start bit(1) 1 = Indicates that a Start bit has been detected last 0 = Start bit was not detected last bit 2 R/W: Read/Write Information bit(2,3) In Slave mode: 1 = Read 0 = Write In Master mode: 1 = Transmit is in progress 0 = Transmit is not in progress bit 1 UA: Update Address bit (10-Bit Slave mode only) 1 = Indicates that the user needs to update the address in the SSPADD register 0 = Address does not need to be updated bit 0 BF: Buffer Full Status bit In Transmit mode: 1 = SSPBUF is full 0 = SSPBUF is empty In Receive mode: 1 = SSPBUF is full (does not include the ACK and Stop bits) 0 = SSPBUF is empty (does not include the ACK and Stop bits) */ //movf Temp,W ; //andlw b'00101100' ; Mask BF bit in SSPSTAT //xorlw b'00001100' mask = 0b00001100; status = SSPSTAT; while (status) { PORTD = status; status = SSPSTAT & 0b00101100; // Mask BF bit in SSPSTAT status = status ^ mask; // mask sspstat } SSPBUF = 0b11000011; while (SSPCON1bits.WCOL) { SSPCON1bits.WCOL = 0; PORTD = 0b11010011; SSPBUF = 0b11000011; } for (counter = 1; counter < 20; counter++) { mask = 0b00101100; status = SSPSTAT; //S = 1, D_A = 1, R_W = 1, BF = 0 while (status) { PORTD = status; status = SSPSTAT & 0b00101100; // Mask BF bit in SSPSTAT status = status ^ mask; // mask sspstat } SSPBUF = 0b11000011; while (SSPCON1bits.WCOL) { SSPCON1bits.WCOL = 0; PORTD = 0b11010011; SSPBUF = 0b11000011; } } //if (SSPSTAT & 0x04) //check if master is ready for reception // while (putsI2C(I2C_Send)); // send the data to master PORTD = 0b01010101; while (1) { } } else { PORTD = temp; } } //-------------TERMINATE COMMUNICATION FROM MASTER SIDE--------------- CloseI2C(); //close I2C module } void delay_sec(unsigned char sec) { unsigned char counter1 = 0; unsigned char counter2 = 0; unsigned char counter3 = 0; unsigned char counter4 = 0; for (counter1 = 0; counter1 < sec; counter1++) { for (counter2 = 0; counter2 < 50; counter2++) { for (counter3 = 0; counter3 < 100; counter3++) { for (counter4 = 0; counter4 < 100; counter4++) { Nop(); // (5 * 2) * 100 * 100 * 100 } } } } } void delay_msec(unsigned char msec) { unsigned char counter1 = 0; unsigned char counter2 = 0; unsigned char counter3 = 0; for (counter1 = 0; counter1 < msec; counter1++) { for (counter2 = 0; counter2 < 50; counter2++) { for (counter3 = 0; counter3 < 10; counter3++) { Nop(); // (5 * 2) * 100 * 100 * 100 } } } } void leds_test(void) { PORTD = 0b11111111; delay_msec(100); PORTD = 0b00000001; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_msec(100); PORTD = PORTD << 1; delay_sec(1); }

The master code had to be changed too. It sends the F6 command to the slave, then it sends repeated start sequences for every byte it wants to receive. After receiving all data, it calculates a checksum and compares it with the received checksum. If they don't match, the program halts and displays the received data (byte by byte): Port A-E, checksum high byte, checksum low byte. Otherwise it will just repeat the whole process.

/* * File: main.c * Author: erwin_000 * * Created on December 30, 2013, 8:07 PM */ #include <p18f4550.h> #include <stdio.h> #include <stdlib.h> #include <i2c.h> #pragma config PLLDIV = 5 // 20 MHz Oscillator #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // 48 MHz CPU-CLK #pragma config FOSC = HSPLL_HS // Highspeed with phase locked loop //#pragma config FOSC = HS // Highspeed, no phase locked loop #pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config DEBUG = OFF //#ifdef __DEBUG #pragma config PWRT = OFF #pragma config WDT = OFF, WDTPS = 1024 //#else // #pragma config PWRT = ON // #pragma config WDT = ON, WDTPS = 32768 //#endif #pragma config BOR = OFF, BORV = 0 #pragma config VREGEN = ON #pragma config MCLRE = OFF #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = OFF #pragma config STVREN = ON #pragma config LVP = OFF #pragma config ICPRT = ON//OFF #pragma config XINST = OFF #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF #pragma config CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTRB = OFF #define _XTAL_FREQ 20000000 #define SCL TRISBbits.TRISB1 // I2C bus #define SDA TRISBbits.TRISB0 #define SCL_IN PORTBbits.RB1 // #define SDA_IN PORTBbits.RB0 // const unsigned char PORTA_DATA = 0; const unsigned char PORTB_DATA = 1; const unsigned char PORTC_DATA = 2; const unsigned char PORTD_DATA = 3; const unsigned char PORTE_DATA = 4; const unsigned char CHECKSUM_LO = 5; const unsigned char CHECKSUM_HI = 6; void delay_sec(unsigned char sec); void delay_msec(unsigned char msec); void leds_test(void); void sendStartSequence(void); void sendStopSequence(void); void sendRepeatedStartSequence(void); void writeAddressOfSlave(unsigned char add1, unsigned char modus); void sendReadAcknowledge(void); void sendReadNotAcknowledge(void); unsigned char sendReadCommand(void); unsigned char I2C_Send[21] = "MICROCHIP:I2C_MASTER"; unsigned char I2C_Recv[7]; unsigned char status = 0; unsigned char data = 0; //************ I2C MASTER **************************** void main(void) { unsigned char add1, w; unsigned char counter = 0; unsigned char loopcounter = 0; unsigned int received_checksum=0; unsigned int calculated_checksum=0; PORTA = 0; TRISA = 0b00000000; // PORTD all outputs PORTA = 0b11111111; /* Two pins are used for data transfer: ? Serial clock (I2C_SCL) ? RB1/AN10/INT1/SCK/I2C_SCL ? Serial data (I2C_SDA) ? RB0/AN12/INT0/FLT0/SDI/I2C_SDA The user must configure these pins as inputs by setting the associated TRIS bits. */ ADCON1 = 0b00001111; //AN0...AN12 as digital I/O TRISB = 0b00000011; //RB0...RB1 as digital inputs, others output PORTB = 0; PORTB = 0b11111100; PORTC = 0; TRISC = 0b00000000; // PORTD all outputs PORTC = 0b11111111; PORTD = 0; TRISD = 0b00000000; // PORTD all outputs PORTD = 0b11111111; PORTE = 0; TRISE = 0b00000000; // PORTD all outputs PORTE = 0b11111111; leds_test(); for (w = 0; w < 7; w++) { I2C_Recv[w] = 0; } status = 0; add1 = 0xA2; //address of the device (slave) under communication SSPCON1 = 0; SSPCON2 = 0; SSPADD = 0x63; // 0x63 = 100kHz Baud clock(9) @20MHz SSPSTATbits.SMP = 1; // slew rate is disabled SSPSTATbits.CKE = 1; // enable SM SSPCON1bits.SSPM3 = 1; // 1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) SSPCON1bits.SSPM2 = 0; SSPCON1bits.SSPM1 = 0; SSPCON1bits.SSPM0 = 0; SSPCON1bits.SSPEN = 1; // enable I2C SSPCON2bits.SEN = 0; // Clock stretching is disabled while (1) { while (SSPCON1bits.SSPOV) { SSPCON1bits.SSPOV = 0; } while (SSPCON1bits.WCOL) { SSPCON1bits.WCOL = 0; } /* 1. Send a start sequence 2. Send the I2C address of the slave with the R/W bit low (even address) 3. Send the internal register number you want to write to 4. Send the data byte 5. [Optionally, send any further data bytes] 6. Send the stop sequence. */ sendStartSequence(); PORTD = 1; writeAddressOfSlave(add1, 0x00); PORTD = 2; for (counter = 0; counter < 20; counter++) { I2C_Send[counter] = 0b11100111; } while (putsI2C(I2C_Send) != 0); //write string of data to be transmitted to slave PORTD = 3; sendStopSequence(); PORTD = 4; /* 1. Send a start sequence 2. Send the I2C address of the slave with the R/W bit low (even address) 3. Send 0xF6 command 4. Send a start sequence again (repeated start) 5. Send the I2C address of the slave with the R/W bit high (odd address) 6. Read data byte from slave 7. Send the stop sequence. */ while (1) { sendStartSequence(); PORTD = 5; IdleI2C(); writeAddressOfSlave(add1, 0x00); PORTD = 6; WriteI2C(0xF6); SSPCON1bits.SSPOV = 0; while (SSPSTATbits.BF) { data = SSPBUF; } for (counter = 0; counter < 7; counter++) { PORTD = 9; sendRepeatedStartSequence(); writeAddressOfSlave(add1, 0x01); data = sendReadCommand(); PORTD = data; if (SSPCON2bits.ACKSTAT) { PORTD = 0b11111111; } I2C_Recv[counter] = data; if (counter < 6) { PORTD = 13; IdleI2C(); sendReadAcknowledge(); } else { PORTD = 14; IdleI2C(); sendReadNotAcknowledge(); } } PORTD = 14; sendStopSequence(); PORTD = 0b10101010; calculated_checksum = I2C_Recv[0]; calculated_checksum += I2C_Recv[1]; calculated_checksum += I2C_Recv[2]; calculated_checksum += I2C_Recv[3]; calculated_checksum += I2C_Recv[4]; received_checksum = I2C_Recv[5]; received_checksum <<= 8; received_checksum += I2C_Recv[6]; if(I2C_Recv[0] != 0b11000011 || (calculated_checksum != received_checksum)) { while(1){ PORTD = 0b10101010; delay_sec(1); for (counter = 0; counter < 7; counter++) { PORTD = 0b11111111; delay_sec(1); PORTD = I2C_Recv[counter]; delay_sec(1); } } } for (counter = 0; counter < 7; counter++) { delay_msec(25); PORTD = I2C_Recv[counter]; } if(loopcounter==255) { delay_sec(2); } loopcounter++; } } } void sendStartSequence(void) { PORTD = 0b10000001; data = SSPBUF; //read any previous stored content in buffer to clear buffer full status SSPCON2bits.SEN = 1; // send a start sequence while (SSPCON2bits.SEN) { }// wait for end of start sequence PORTD = 0b11000001; } void sendRepeatedStartSequence(void) { IdleI2C(); PORTD = 0b10000010; data = SSPBUF; //read any previous stored content in buffer to clear buffer full status SSPCON2bits.RSEN = 1; // send a repeated start sequence while (SSPCON2bits.RSEN) { }// wait for end of repeated start sequence while (SSPSTATbits.R_NOT_W) { }// transmit is in progress PORTD = 0b11000010; } unsigned char sendReadCommand(void) { IdleI2C(); PORTD = 0b10000110; SSPCON2bits.RCEN = 1; // send a read command sequence while (SSPCON2bits.RCEN) { }// wait for end of read command sequence while (!SSPSTATbits.BF) { } data = SSPBUF; PORTD = 0b11000110; return data; } void writeAddressOfSlave(unsigned char add1, unsigned char modus) { PORTD = 0b10000011; do { status = WriteI2C(add1 | modus); //write the address of slave if (status == -1) //check if bus collision happened { PORTD = 0b10000001; data = SSPBUF; //upon bus collision detection clear the buffer, SSPCON1bits.WCOL = 0; // clear the bus collision status bit } } while (status != 0); //write untill successful communication PORTD = 0b11000011; } void sendStopSequence(void) { PORTD = 0b10000100; SSPCON2bits.PEN; // initiate stop sequence while (SSPCON2bits.PEN) { } PORTD = 0b11000100; } void sendReadAcknowledge(void) { PORTD = 0b10000101; SSPCON2bits.ACKDT = 0; SSPCON2bits.ACKEN; // initiate read ACK while (SSPCON2bits.ACKEN) { } PORTD = 0b11000101; } void sendReadNotAcknowledge(void) { PORTD = 0b10000110; SSPCON2bits.ACKDT = 1; SSPCON2bits.ACKEN; // initiate read NAK while (SSPCON2bits.ACKEN) { } PORTD = 0b11000110; } void delay_sec(unsigned char sec) { unsigned char counter1 = 0; unsigned char counter2 = 0; unsigned char counter3 = 0; unsigned char counter4 = 0; for (counter1 = 0; counter1 < sec; counter1++) { for (counter2 = 0; counter2 < 50; counter2++) { for (counter3 = 0; counter3 < 100; counter3++) { for (counter4 = 0; counter4 < 100; counter4++) { Nop(); // (5 * 2) * 100 * 100 * 100 } } } } } void delay_msec(unsigned char msec) { unsigned char counter1 = 0; unsigned char counter2 = 0; unsigned char counter3 = 0; for (counter1 = 0; counter1 < msec; counter1++) { for (counter2 = 0; counter2 < 50; counter2++) { for (counter3 = 0; counter3 < 10; counter3++) { Nop(); // (5 * 2) * 100 * 100 * 100 } } } } void leds_test(void) { PORTD = 0b11111111; delay_msec(250); PORTD = 0b00000000; delay_msec(250); PORTD = 0b11111111; delay_msec(250); PORTD = 0b00000001; delay_msec(250); PORTD = PORTD << 1; delay_msec(250); PORTD = PORTD << 1; delay_msec(250); PORTD = PORTD << 1; delay_msec(250); PORTD = PORTD << 1; delay_msec(250); PORTD = PORTD << 1; delay_msec(250); PORTD = PORTD << 1; delay_msec(250); PORTD = PORTD << 1; delay_sec(1); }

N.B. my example code has hard coded values for PORT A-E for testing purposes, but as the comment shows, you can just change it to have the real data in it. Every pin is currently defined as output So don't forget to define the right inputs as well! Part IIIis about connecting the PIC18F4550 (slave) to a Raspberry Pi (master).
On 2015-06-22, Blake wrote:

comment=Hello%2C+I+am+trying+to+follow+your+code+but+I+am+having+some+difficulty+with+that.+Is+it+possible+to+add+some+additional+code%3F

On 2015-06-23, Eeuwe Vandyke wrote:

comment=Hi+Blake%2C%0D%0A%0D%0AWhich+part(s)+of+the+code+do+need+some+more+comments%2Fexplanation%3F%0D%0AIf+you+can+narrow+your+question%2C+it+will+be+easier+for+me+to+answer+your+question.

On 2015-06-23, Blake wrote:

comment=Hello+Erwin%2C%0D%0A%0D%0AThank+you+for+the+quick+response%2C+I+am+building+a+master+and+a+slave+i2c+where+in+the+slave+I+want+to+send+a+data+from+PORTD+to+the+master+upon+request%2C+so+I'm+your+code+can+help.+I'm+also+including+a+ISR+interrupt.%0D%0A%0D%0AI'm+not+really+a+software+guy+more+hardware+so+please+excuse+all+the+questions.%0D%0A%0D%0AI'm+a+little+confused+about+what+these+are+and+what+they+are+doing%3A%0D%0Aunsigned+char+I2C_Send+%5B7%5D%0D%0Aunsigned+char+I2C_Recv+%5B21%5D%0D%0AreadIndex%0D%0AwriteIndex%0D%0AR_CNT.%0D%0A%0D%0AI'm+not+sure+what+this+is+doing+SSPBUF+%3D+I2C_Send+%5BwriteIndex%2B%2B%5D.%0D%0A%0D%0AThank+you+again+Erwin.%0D%0A%0D%0ABlake.%0D%0A

On 2015-06-25, Eeuwe Vandyke wrote:

comment=Hi+Blake%2C%0D%0ANo+problem.+The+unsinged+char+I2C_Send%5B7%5D+declares+an+array+in+which+you+can+store+7+bytes+of+data+(unsigned+characters)+with+a+value+%5B0...255%5D%0D%0ASame+for+the+I2C_Recv%2C+Only+this+array+can+hold+21+bytes.+The+readindex+indicates+the+read+position+with+the+I2C_Recv+array%2Fbuffer.+The+writeindex+indicates+the+write+position+in+the+I2C_Send+array%2Fbuffer.+R_CNT+is+just+a+read+counter.+It+counts+the+total+number+of+bytes+read+and+the+value+is+displayed+at+Port+D.+Hope+this+answers+your+question.+%0D%0AKind+regards%2C%0D%0AErwin

On 2015-06-29, Blake wrote:

comment=Hello+Erwin%2C%0D%0AThank+you+for+clearing%2C+it+makes+great+sense.+Since+I+will+only+be+sending+from+one+port%2C+I+am+understanding+there+would+not+be+any+need+for+that.+Thank+you+for+your+response.%0D%0A%0D%0ASorry+about+all+the+questions+but+I+have+another+question.+In+the+Slave+code%2C+I+see+that+you+are+masking+bits.+%0D%0ASlavedata+%3D+0b11000011%3B%0D%0Amask+%3D+0b00001100%3B%0D%0Astatus+%3D+SSPSTAT%3B%0D%0A%0D%0AWhat+is+the+purpose+of+doing+this%3F+And+what+is+'slavedata'+representing%3F+%0D%0A%0D%0AAlso+what+is+the+writeByte+functions+accomplishing%3F%0D%0A%0D%0AThank+you+Erwin%2C+you've+been+very+helpful.+As+a+Hardware+engineer%2C+I+am+a+little+over+my+head+so+thank+you+for+the+assistance.+%0D%0ABlake.++%0D%0A

On 2015-06-29, Eeuwe Vandyke wrote:

comment=Hi+Blake.%0D%0A%0D%0AQuestion+1%3A+Slavedata+%3D+0b11000011%3B%0D%0ADo+you+see+the+while(1)+%7B+%7D+at+line+384%3F%0D%0AThere+end+the+actual+main+loop.+The+actual+slave+is+now+handling+master+requests+in+the+interrupt+handler.+All+code+in+the+'main+loop'+end+here.+I+can+remove+it%2C+but+I+already+stated+this+in+the+comment+above+the+code.++So+the+code+%22slaveData+%3D+0b11000011%3B%22+is+never+executed.+I+think+I+will+remove+it+anyway+

On 2015-06-29, Eeuwe Vandyke wrote:

comment=Question+2%3A+mask+%3D+0b00001100%3B%0D%0A+and+status+%3D+SSPSTAT%0D%0AThe+SSPSTAT+register+contains+information+about+I2C+when+I2C+mode+is+enabled.+(see+datasheet%2C+for+details.)%0D%0AFirst+I'm+AND-ing+the+status+register+with+0b00101100+so+only+bits+2%2C+3+and+5+are+used.%0D%0ASo+the+variable+'status'+has+only+bits+2%2C+3+and%2For+5+set+if+these+bits+are+set+in+the+STATUS+register.+All+other+bits+are+0.%0D%0AIf+bit+2+of+the+status+register+is+1%2C+this+means+'read'+in+slave+mode%0D%0AIf+bit+3+of+the+status++register+is+1%2C+this+means++a+Start+bit+has+been+detected+last%0D%0AIf+bit+5+of+the+status+register+is+1%2C+this+means++that+the+last+byte+received+or+transmitted+was+data.%0D%0AThe+resulting+value+is+stored+in+'status'+and+XOR-ed+with+the+mask+0b00001100.%0D%0AAs+long+as+the+resulting+value+is+not+'0'%2C+the+system+waits+(reads+STATUS+again).%0D%0AWhen+is+status+not+0%3F+If+bit+5+of+the+status+register+%3D+1+or+bit+2+or+3+is+0.%0D%0ADo+you+know+how+XOR+works%3F+If+two+bytes+are+XOR-ed.+The+bytes+are+compared+bitwise.+%0D%0AExample.+If+byte1+%3D+0b00001111+and+byte2+%3D+0b11001100+then+the+resulting+byte+will+be%3A+0b11000011.%0D%0AEach+resulting+bit+is+only+'1'+if+only+one+compared+bit+is+'1'.

On 2015-07-01, Blake wrote:

comment=Hello+Erwin%2C%0D%0A%0D%0AThanks+again+for+clarifying+that.+I+think+I've+made+all+the+proper+changes+to+my+code+now+and+I'm+confident+it+will+execute+as+I+plan+thanks+to+you.+Thanks+again+Erwin%2C+you've+been+extremely+helpful%2C+much+appreciated!%0D%0ABlake

On 2015-07-05, Eeuwe Vandyke wrote:

comment=Hi+Blake%2C%0D%0AYou're+welcome.++Helping+out+someone+is+one+of+the+main+reasons+that+I+blog.%0D%0A%0D%0AKind+regards%2C%0D%0AErwin.

Back to List

All form fields are required.
A confirmation mail for the comments will be send to you.