Host Reception (10-bit Address)
#include <xc.h>
#define INIT 0
#define ADDRESS_PHASE_UPPER_10BIT_WRITE 1
#define ADDRESS_PHASE_LOWER_10BIT 2
#define RESTART 3
#define ADDRESS_PHASE_UPPER_10BIT_READ 4
#define DATA_READ 5
unsigned char hostReceived[20], phase;
unsigned char count = 0;
#define mCLIENT_ADDRESS 0x14C
int main(void) {
/*Configure I2C pins as digital*/
/*I2C1 configured as Host */
I2C1LBRG = 38; // 100kHz @ 8MIPS
I2C1HBRG = 38; // 100kHz @ 8 MIPS
/* Configure Bus IDle timeout*/
I2C1CON2bits.BITE = 1;
I2C1BITObits.BITOPR = 76;
/* Configured interrupt enable bits*/
I2C1INTCbits.HACKSIE = 1; // Assert HSTIF on ACK seq
I2C1INTCbits.HDTXIE = 1; // Assert HSTIF on TX
I2C1INTCbits.HDRXIE = 1; // Assert HSTIF on RX
I2C1INTCbits.HSCIE = 1; // Assert HSTIF on start
I2C1INTCbits.HSTIE = 1; // Assert I2CxIF when HSTIF is set
I2C1CON2bits.SMEN = 1; // Smart mode enabled
I2C1CON2bits.ACKC = 0b10; // ACK all the bytes expect last byte
I2C1CON2bits.PSZ = 10; // Packet size
I2C1CON2bits.EOPSC = 0b01; // End of packet will be set after data bytes
I2C1CON1bits.ON = 1; // Enable I2C
IFS2bits.I2C1IF = 0; // Clear I2C general interrupt
IEC2bits.I2C1IE = 1; // Enable I2C general interrupt
/*wait for bus idle */
while (!I2C1STAT2bits.BITO);
phase = ADDRESS_PHASE_UPPER_10BIT_WRITE;
I2C1CON1bits.SEN = 1; // Send Start bit
while (1);
}
void __attribute__((interrupt, no_auto_psv)) _I2C1Interrupt(void) {
IFS2bits.I2C1IF = 0;
switch (phase) {
case ADDRESS_PHASE_UPPER_10BIT_WRITE:
/*Verify if start has been sent*/
if (I2C1STAT2bits.STARTE) {
/* Transmit client address with RW =0 , write client*/
I2C1TRN = ((((mCLIENT_ADDRESS >> 8) & 0x03) << 1) | 0) + 0b11110000;
phase = ADDRESS_PHASE_LOWER_10BIT;
}
break;
case ADDRESS_PHASE_LOWER_10BIT:
/*Verify if the upper 10bit address is ACKed*/
if (I2C1STAT1bits.ACKSTAT == 0) {
I2C1TRN = mCLIENT_ADDRESS & 0xFF;
phase = RESTART;
}
break;
case RESTART:
I2C1CON1bits.RSEN = 1; // Send restart
phase = ADDRESS_PHASE_UPPER_10BIT_READ;
break;
case ADDRESS_PHASE_UPPER_10BIT_READ:
/* Transmit client address with RW =1 , read client*/
I2C1TRN = ((((mCLIENT_ADDRESS >> 8) & 0x03) << 1) | 1) + 0b11110000;
phase = DATA_READ;
break;
case DATA_READ:
/* Set NDA to indicate next byte is data */
if (I2C1CON2bits.NDA != 1) {
I2C1CON2bits.NDA = 1;
/*Enable receive for the 1st time*/
I2C1CON1bits.RCEN = 1;
}
/*Read the received data*/
if (I2C1STAT1bits.RBF) {
hostReceived[count++] = I2C1RCV;
}
/* If Packet size is 0, EOP will be asserted,send STOP on EOP*/
if (I2C1STAT2bits.EOP) {
I2C1CON1bits.PEN = 1;
}
break;
}
}