Если кому будет интересно. Проблема решилась.
Оказалось, что ошибка была в примере работы с I2C из HI-TECH, который я взял за основу. В нем ф-ция после записи байта не отпускала линию SCL тем самым не завершался импульс тактирования Acknowledge-а. В итоге это приводило к тому, что линия SDA оставалась притянутой к нулю и не формировался сигнал Stop (к сожалению я не сразу на это обратил внимание, хотя на осциллографе это было хорошо видно). Ну а как следствие всего этого, запись в EEPROM не происходила.
Чтобы было понято, приведу кусок кода из HI-TECH (можно найти в папке samples\i2c\):
Код
signed char i2c_PutByte(unsigned char data)
{
if(i2c_SendByte(data))
return I2C_ERROR;
return i2c_ReadAcknowledge(); /* returns ack, ~ack */
}
signed char i2c_ReadAcknowledge(void)
{
unsigned char ack;
SCL_LOW(); /* make clock is low */
SDA_DIR = I2C_INPUT; /* disable data line - listen for ack */
DelayUs(I2C_TM_SCL_TO_DATA); /* SCL low to data out valid */
SCL_DIR = I2C_INPUT; /* float clock high */
DelayUs(I2C_TM_DATA_SU);
ack = SDA; /* read the acknowledge */
/* wait for slave to release clock line after processing byte */
if(i2c_WaitForSCL())
return I2C_ERROR;
return ack;
}
unsigned char i2c_SendByte(unsigned char byte)
{
signed char i;
for(i=7; i>=0; i--)
{
SCL_LOW(); /* drive clock low */
SDA_DIR = ((byte>>i)&0x01);
if ((byte>>i)&0x01) { /* bit to send */
SDA_HIGH();
}else {
SDA_LOW();
}
DelayUs(I2C_TM_DATA_SU);
SCL_DIR = I2C_INPUT; /* float clock high */
if(i2c_WaitForSCL()) /* wait for clock release */
return TRUE; /* bus error */
DelayUs(I2C_TM_SCL_HIGH); /* clock high time */
}
return FALSE;
}
После добавления в ф-цию i2c_ReadAcknowledge команды SCL_LOW() перед выходом из нее все прекрасно заработало.
Всем откликнувшися спасибо.
P.S. В коде, который я приводил в первом сообщении, ф-ции I2CReadAck() соответствует ф-ция i2c_ReadAcknowledge() из примера HI-TECH, SendByteI2C() - i2c_SendByte().
P.S.S. На эту ошибку указал
dynaco на форуме microchip.ru еще в 2005 году (см.
последнее сообщение на странице)