We are trying to write an I2C driver for the ST10F276 (ST10F276Z5T3 - working at 40Mhz) and we encounterd the following problem: we use the function below to send the start bit, but it doesn't work ( I2CSR1 bit 0 does not rise )without the delay of about 100uSec between the the assignment of I2C_START value to the I2CCR register and querying of the I2CSR1 register. Is there a reason for this delay? we copied this driver from a prior product which used ST10F276 also but worked at 64Mhz and no delay was needed there. thanks in advance, Dvir //------------------------------------------------------------------------ #define I2C_START ((unsigned char)0x08) #define I2C_SB 0x0001 byte I2C_TransmitStartBit(void) { word wSavedTime; word wIndex; I2CCR |= I2C_START; wSavedTime = INT_dwGetTime(); // 1mSec resolution //************************************************************************ // ~100uSec delay for (wIndex = 0; wIndex < 150 ; wIndex++ ) { _nop(); } //************************************************************************ if ((I2CSR1 & I2C_SB) == 0) { if (( INT_dwGetTime() - wSavedTime ) > 3) { return(FALSE); } } return(TRUE); } //------------------------------------------------------------------------
After the Start condition is sent by setting bit I2C_START in I2CCR register, a wait until the I2C_SB in I2CSR1 register is set, must be done because the SB bit is not set immediately after sending the start condition. Could you please use the following code instead the delay. // Check if START condition is generated correctly while (!(SR1 & I2C_SB)) I2CCheckError(); with: #define I2C_BERR ((unsigned char)0x02) void I2CCheckError(void) { if( SR2 & I2C_BERR ) _nop(); } You said that this code works well at 64MHz. May be the duration of the instructions following the launching of the start condition was sufficent for the SB bit to be set. Could You please tell me how it goes? If you want, I can provide you working I2C routines. Best regards, Najoua.
I tried your suggested solution, but i got stuck endlessly inside the '' while (!(SR1 & I2C_SB)) I2CCheckError(); '' loop. It seems like reading SR1 frequently while the start is being produced causes the problem, but that's just a guess. If you have I2C routines that work on 40Mhz MCU, I'll be happy to get them. Thanks for your help, Dvir