bool fgI2CStart(byte bDevice)
{
SET_SDA; // make sure SDA released
TimeDelay2us();
SET_SCL; // make sure SCL released
TimeDelay2us();
CLR_SDA; // start condition here
TimeDelay2us();
CLR_SCL; // ready for clocking
TimeDelay2us();
return(fgI2CSend(bDevice)); // slave address & R/W transmission
}
void vI2CStop(void)
{
CLR_SDA; // ready for stop condition
TimeDelay2us();
SET_SCL; // ready for stop condition
TimeDelay2us();
SET_SDA; // stop condition here
TimeDelay2us();
}
bool fgI2CSend(byte bValue)
{
byte bBitMask = 0x80;
// step 1 : 8-bit data transmission
while(bBitMask){
if(bBitMask & bValue){
SET_SDA;
}
else{
CLR_SDA;
}
TimeDelay2us();
SET_SCL; // data clock in
TimeDelay2us();
CLR_SCL; // ready for next clock in
TimeDelay2us();
bBitMask = bBitMask >> 1; // MSB first & timing delay
}
SET_SDA; // release SDA for ACK polling
TimeDelay2us();
SET_SCL; // start ACK polling
TimeDelay2us();
bBitMask = 200; // time out protection
do{
TimeDelay2us();
}while(IIC_SDA && --bBitMask); // wait for ACK, SDA=0 or bitMask=0->jump to this loop
CLR_SCL; // end ACK polling
TimeDelay2us();
if(!bBitMask)
return FALSE; // return TRUE if ACK detected
return TRUE; // return FALSE if time out
}
void vI2CRead(byte *prValue, bool fgSeq_Read)
{
byte bBitMask = 0x80;
*prValue = 0; // reset data buffer
SET_SDA; // make sure SDA released
TimeDelay2us();
// step 1 : 8-bit data reception
while(bBitMask)
{
SET_SCL; // data clock out
TimeDelay2us();
if(IIC_SDA){
*prValue = *prValue | bBitMask; // Get all data
} // non-zero bits to buffer
CLR_SCL; // ready for next clock out
TimeDelay2us();
bBitMask = bBitMask >> 1; // shift bit mask & clock delay
}
// step 2 : acknowledgement to slave
if(fgSeq_Read){
CLR_SDA; // ACK here for Sequential Read
}
else{
SET_SDA; // NACK here (for single byte read)
}
TimeDelay2us();
SET_SCL; // NACK clock out
TimeDelay2us();
CLR_SCL; // ready for next clock out
TimeDelay2us();
SET_SDA; // release SDA
TimeDelay2us();
}
bool fgI2C_Eeprom_Write(word wAddress, byte bDataCount, byte *pValue)
{
byte addr1,addr2;
addr1 = (byte)(wAddress & 0x00ff);
addr2 = (byte)(wAddress >> 8);
if(!fgI2CStart(EEPROM)) return FALSE;
if(!fgI2CSend(addr2)) return FALSE;
if(!fgI2CSend(addr1)) return FALSE;
do{
if(!fgI2CSend(*pValue++)) return FALSE;
}while(--bDataCount);
vI2CStop();
return TRUE;
}
bool fgI2C_Eeprom_Read(word wAddress, byte bDataCount, byte *pValue)
{
byte addr1,addr2;
addr1 = (byte)(wAddress & 0x00ff);
addr2 = (byte)(wAddress >> 8);
if(!fgI2CStart(EEPROM)) return FALSE;
if(!fgI2CSend(addr2)) return FALSE;
if(!fgI2CSend(addr1)) return FALSE;
if(!fgI2CStart(EEPROM+1)) return FALSE;
do{
if(bDataCount==1){vI2CRead(pValue++,FG_RANDREAD);}
else{ vI2CRead(pValue++,FG_SEQREAD);}
}while(--bDataCount);
vI2CStop();
return TRUE;
}
} |