// i2cFunctions.c - to drive I2C2 interface
#define USE_AND_OR
#include "i2c.h"
#include "Hardware.h"
#include "stdio.h"
#include "timer.h"
static int I2C2address=0; // address of I2C2 device
// This routine is used to write a byte to the I2C2 bus. The input parameter data_out is written to the
// I2C2TRN register. If IWCOL bit is set,write collision has occured and -1 is returned,
// if acknowledge timeout return -2, else 0 is returned.
char MasterWriteI2C2(const unsigned char data_out)
{
I2C2TRN = data_out; // write data byte
if(I2C2STATbits.BCL)
{ printf("I2C Master bus collision detect %0x\n", I2C2STAT); return -1; } /* If write collision occurs,return -1 */
if(I2C2STATbits.IWCOL)
{ printf("I2C write collision detect %0x\n", I2C2STAT); return -1; } /* If write collision occurs,return -1 */
int timeOutCount=10000;
while(I2C2STATbits.TBF || I2C2CONbits.SEN || I2C2CONbits.PEN || I2C2CONbits.RCEN || I2C2CONbits.ACKEN || I2C2STATbits.TRSTAT || I2C2STATbits.ACKSTAT)
if(!timeOutCount--) { printf("\n\rMasterWriteI2C2 address %#x timeout config %#x status %#x \n\r", I2C2address, I2C2CON, I2C2STAT); return -2; }
// printf(" %0x ", I2C2STAT);
return 0;
}
// This routine is used to write out an array to the
// I2C2 bus.If write collision occurs,-3 is sent.If
// Nack is received, -2 is sent.If arrayis written 0 is returned.
static unsigned int MasterPutArrayI2C2(const unsigned char * wrptr, int count)
{
int i=0;
while(count--) //transmit data
{
if((i=MasterWriteI2C2(*wrptr)) < 0) return i; // write a byte - return on error
wrptr++;
}
return 0;
}
// write to I2C2 address array wrptr of length, if sendStop is 1 send a STOP at end
int writeI2C2(const int address, const unsigned char *wrptr, int length, int sendStop)
{
unsigned int i2cbrg=((SYSCLK/100000L)-(SYSCLK/1111111L))-1; /* Baud rate is set for 100 Khz */
unsigned int config1 = (I2C_ON | I2C_IDLE_CON | I2C_CLK_HLD /* Configure I2C for 7 bit address mode */
| I2C_IPMI_DIS | I2C_7BIT_ADD | I2C_SLW_DIS | I2C_SM_DIS |
I2C_GCALL_DIS | I2C_STR_DIS | I2C_NACK | I2C_ACK_DIS | I2C_RCV_DIS |
I2C_STOP_DIS | I2C_RESTART_DIS | I2C_START_DIS);
// problem with Master bus colision on PIC24s, see
// http://forum.microchip.com/tm.aspx?m=271183&mpage=1&key=
TRISAbits.TRISA3=0;
LATAbits.LATA3 = 0; //where LATBx = the SDAx pin
LATAbits.LATA3 = 1;
OpenI2C2(config1,i2cbrg); /* open the I2C2 device */
//printf("\nwrite I2C2 %#x %0x %0x I2C stat %0x \n", address,config1,i2cbrg,I2C2STAT);
IdleI2C2();
StartI2C2(); /* send START */
while(I2C2CONbits.SEN ); /* Wait till Start sequence is completed */
if(MasterWriteI2C2(I2C2address=address) < 0) return -1; /* Write Slave address and set master for transmission */
if(MasterPutArrayI2C2(wrptr, length) < 0) return -1; /* Transmit string of data */
if(!sendStop) return 0;
StopI2C2(); /* send STOP */
while(I2C2CONbits.PEN); /* Wait till stop sequence is completed */
CloseI2C2();
return 0;
}
// read from I2C2 device address
// initially send tx_data (length tx_length), restart and read rx_length bytes into rs_data
int readI2C2(int address, unsigned char *tx_data, int tx_length, unsigned char * rx_data, int rx_length)
{
//int i;
unsigned int i2c_data_wait= 11152;
//printf("\n\rread I2C2 %#x ", address);
writeI2C2(address,tx_data, tx_length, 0); // send address and register number etc
RestartI2C2(); // send RESTART ready for a read!
while(I2C2CONbits.RSEN ); // wait for restart complete
if(MasterWriteI2C2(address+1)<0)return -1; /* Write Slave address and set master for read */
if(MastergetsI2C2(rx_length, rx_data, i2c_data_wait)!=0)return -1; // read data from slave
// uart2_puts("\n\rread ");
// for(i=0;i<rx_length;i++) { printHex(rx_data[i],uart2_putchar); uart2_putchar(' ');}
StopI2C2(); /* send stop */
while(I2C2CONbits.PEN); /* Wait till stop sequence is completed */
CloseI2C2(); // close I2C2 device
return 0;
}