/********************************************************************* * * _I2C_RepeatStart() * * Description: * Generates a start condition on I2C when bus is free. * Master mode will also automatically be entered. * * Note: After a stop condition, you may need a bus free time before you * can generate a new start condition. */ static unsigned char _I2C_RepeatStart(void) { unsigned char Status = 0; unsigned char r = 0; // // Issue a start condition // I20CONSET |= (1 << 5); // STA = 1, set start flag I20CONCLR = (1 << 3); // Clear SI flag // // Wait until START transmitted // while (1) { Status = _I2C_CheckStatus(); if ((Status == 0x08) || (Status == 0x10)) { r = I2C_CODE_OK; // Start transmitted break; } else if (Status != 0xF8) { r = Status; // Error break; } else { I20CONCLR = (1 << 3); // Clear SI flag } } I20CONCLR = (1 << 5); // Clear start flag return r; }
/********************************************************************* * * _I2C_WaitTransmit() */ static unsigned char _I2C_WaitTransmit(void) { unsigned char Status = 0; // // Wait till data transmitted // while(1) { Status = _I2C_CheckStatus(); // // SLA+W transmitted, ACK received or // data byte transmitted, ACK received // if ((Status == 0x18) || (Status == 0x28)) { return I2C_CODE_OK; // Data transmitted and ACK received } else if (Status != 0xF8) { return I2C_CODE_ERROR; // Error, no relevant status information } } }
/********************************************************************* * * I2C_PCA9532_WriteRead() */ unsigned char I2CPCA9532_WriteRead(unsigned char * pData, unsigned short NumBytesToWrite, unsigned char * pBuf, unsigned short NumBytesToRead) { unsigned char r = 0; unsigned char Status = 0; unsigned short i = 0; r = _I2C_Start(); // Generate Start condition if(r != I2C_CODE_OK) { goto STOPWRITE; } r = _I2C_WriteWithWait(0xC0); // Write PCA9532 address if (r != I2C_CODE_OK) { goto STOPWRITE; } // // Write data // for (i = 0; i < NumBytesToWrite; i++) { r = _I2C_WriteWithWait(*pData); if (r != I2C_CODE_OK) { goto STOPWRITE; } pData++; } STOPWRITE: if (NumBytesToRead > 0) { r = _I2C_RepeatStart(); // Generate Start condition // // Transmit device address // if (r == I2C_CODE_OK) { r = _I2C_PutChar(0xc0 + 0x01); // Write SLA+R while(r == I2C_CODE_BUSY) { r = _I2C_PutChar(0xc0 + 0x01); } } // // Wait until SLA+R transmitted // while (1) { Status = _I2C_CheckStatus(); if (Status == 0x40) { // Data transmitted and ACK received break; } else if (Status != 0xF8) { // Error r = I2C_CODE_ERROR; break; } } if (r == I2C_CODE_OK) { // // Wait until address transmitted and receive data // for (i = 1; i <= NumBytesToRead; i++) { // // Wait until data transmitted // while (1) { Status = _I2C_CheckStatus(); if ((Status == 0x40) || (Status == 0x48) || (Status == 0x50 )) { // Data received // // Set generate NACK // if (i == NumBytesToRead) { r = _I2C_GetChar(I2C_MODE_ACK1, pBuf); } else { r = _I2C_GetChar(I2C_MODE_ACK0, pBuf); } r = _I2C_GetChar(I2C_MODE_READ, pBuf); // Read data while (r == I2C_CODE_EMPTY) { r = _I2C_GetChar(I2C_MODE_READ, pBuf); } pBuf++; break; } else if (Status != 0xF8) { // Error i = NumBytesToRead; r = I2C_CODE_ERROR; break; } } } } } _I2C_Stop(); // Generate Stop condition return r; }
/********************************************************************* * * _Read * * Function description * Reads from a device on I2C. */ static U8 _Read(U8 Addr, U8 * pData, U16 NumBytesToRead, U8 PartOfWriteRead) { U16 i; U8 Status; U8 r; // // Generate start condition // if (PartOfWriteRead) { r = _I2C_RepeatStart(); // Generate Start condition } else { r = _I2C_Start(); // Generate Start condition } // // Transmit device address // if (r == I2C_CODE_OK) { r = _I2C_PutChar(Addr + 0x01); // Write address (SLA+R) while (r == I2C_CODE_BUSY) { r = _I2C_PutChar(Addr + 0x01); } } // // Wait until SLA+R transmitted // while (1) { Status = _I2C_CheckStatus(); if (Status == 0x40) { // Data transmitted and ACK received break; } else if (Status != 0xF8) { // Error r = I2C_CODE_ERROR; break; } } if (r == I2C_CODE_OK) { // // Wait until address transmitted and receive data // for (i = 1; i <= NumBytesToRead; i++) { // // Wait until data transmitted // while (1) { Status = _I2C_CheckStatus(); if ((Status == 0x40) || (Status == 0x48) || (Status == 0x50)) { // Data received // // Set generate NACK // if (i == NumBytesToRead) { r = _I2C_GetChar(I2C_MODE_ACK1, pData); } else { r = _I2C_GetChar(I2C_MODE_ACK0, pData); } r = _I2C_GetChar(I2C_MODE_READ, pData); // Read data while (r == I2C_CODE_EMPTY) { r = _I2C_GetChar(I2C_MODE_READ, pData); } pData++; break; } else if (Status != 0xF8) { // Error i = NumBytesToRead; r = I2C_CODE_ERROR; break; } } } } _I2C_Stop(); // Generate Stop condition return r; }