Host Transmission (7-bit Address)
#include <xc.h>
#define mCLIENT_ADDRESS 0x4C
#define INIT 0
#define ADDRESS_PHASE 1
#define DATA_WRITE 2
#define PACKET_SIZE 10
unsigned char phase = INIT;
unsigned char hostTransmit[PACKET_SIZE] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA};
unsigned char transmittedCount = 0;
int main(void) {
/*Configure I2C pins as digital*/
//I2C module has Host and Client functionality which may both be active at the same time.
//In this example, Host functionality will be configured and used.
//Configure baud rate for SCL @ 100kHz from 1/2 bus UPB clock @ 4MHz
I2C2LBRG = 16; //Set low-time baud rate
I2C2HBRG = 16; //Set high-time baud rate
/* Configure Bus IDle timeout*/
I2C2CON2bits.BITE = 1;
I2C2BITObits.BITOTMR = 76;
/* Configured interrupt enable bits*/
I2C2INTCbits.HACKSIE = 1; // Assert HSTIF on ACK seq
I2C2INTCbits.HDTXIE = 1; // Assert HSTIF on TX
I2C2INTCbits.HSCIE = 1; // Assert HSTIF on start
I2C2INTCbits.HSTIE = 1; // Assert I2CxIF when HSTIF is set
I2C2CON2bits.PSZ = PACKET_SIZE; // Packet size
I2C2CON2bits.EOPSC = 0b01; // End of packet will be set after data bytes
I2C2CON1bits.ON = 1; // Enable I2C
IFS2bits.I2C2IF = 0; // Clear I2C general interrupt
IEC2bits.I2C2IE = 1; // Enable I2C general interrupt
/*wait for bus idle */
while (!I2C2STAT2bits.BITO);
phase = ADDRESS_PHASE;
I2C2CON1bits.SEN = 1; // Send Start bit
while (1) {
//Once data transmission is complete, repeat the operation.
if ((transmittedCount >= PACKET_SIZE) && (I2C2STAT2bits.STOPE)) {
I2C2STAT2bits.STOPE = 0; //Clear STOPE flag to detect next STOP
I2C2STAT2bits.STARTE = 0; //Clear STARTE flag since last START condition
transmittedCount = 0; //Start transmitting from start of data buffer
I2C2CON2bits.NDA = 0; //Will send address first, next byte is not data
I2C2STAT2bits.EOP = 0; //Clear end of packet bit
I2C2CON2bits.PSZ = 10; //Re-initialize packet size
//Wait for bus idle
while (!I2C2STAT2bits.BITO);
phase = ADDRESS_PHASE;
I2C2CON1bits.SEN = 1; // Send Start bit
}
}
}
void __attribute__((interrupt, no_auto_psv)) _I2C2Interrupt(void) {
IFS2bits.I2C2IF = 0;
switch (phase) {
case ADDRESS_PHASE: {
/*Verify if start has been sent*/
if (I2C2STAT2bits.STARTE) {
/* Transmit client address with RW =0 , writing to client*/
I2C2TRN = (mCLIENT_ADDRESS << 1) | 0;
phase = DATA_WRITE;
}
break;
}
case DATA_WRITE: {
/* Set NDA to indicate next byte is data */
if (I2C2CON2bits.NDA != 1) {
I2C2CON2bits.NDA = 1;
}
/* If Packet size is 0, EOP will be asserted,send STOP on EOP*/
if (I2C2STAT2bits.EOP) {
I2C2CON1bits.PEN = 1;
}
else {
if ((I2C2STAT1bits.ACKSTAT == 0) && (!I2C2STAT1bits.TBF) && (!I2C2STAT1bits.TRSTAT)) {
I2C2TRN = hostTransmit[transmittedCount++]; // Send data to client
}
}
break;
}
}
}