As advised by my fellow stackers in my previous post, I tested the "Write_to_slave" function in Proteus as well in real time, by sending bytes to the RTC and the slave is responding appropriately with an acknowledge bit for each byte it receives, therefore the write operation is working fine. However, now I am having issues with my "Read_from_slave" function. The problem is that, during the read sequence, until the sending of the "Slave address + Read" i.e 0xD1, it works fine and also receives an acknowledgement from the slave, but the problem arises after the execution of the I2C_restart function. The data read from the SSPBUF or the data received from the slave is FF while it should be the seconds counting from 0 to 60 (and displays 63 on the LCD), followed by a NACK. And after sending the NACK, the I2C_stop() should end the transaction while that is not happening as you can see in Proteus snapshot . Below is the code, I have performed just one read operation to read the seconds register to check if my method is working, but unfortunately it isn't :
void Wait_MSSP()
{
while(SSPIF==0);
SSPIF = 0;
}
void check_ACK_Master_Transmit()
{
if(SSPCON2bits.ACKDT == 0) //If ACKDT is 0, ACK has been recieved
arraydisp("ACK success");
else if (SSPCON2bits.ACKDT == 1) //If ACKDT is 1, ACK has not been recieved
arraydisp("ACK fail");
}
unsigned char Read_from_slave(unsigned char addr)
{
unsigned char x;
I2C_start();
SSPBUF = RTC_ADDRW;
Wait_MSSP(); //Slave address+Write
SSPBUF = addr;
Wait_MSSP(); ////RTC register to be read
I2C_restart();
SSPBUF = RTC_ADDRR;
Wait_MSSP();
SSPCON2bits.RCEN = 1; //Enable Master to receive data from slave
x = SSPBUF; //Read the SSPBUF
SSPCON2bits.ACKDT = 1; //send NACK after receiving the data
SSPCON2bits.ACKEN = 1; //Enable Acknowledge sequence on SDA and SCL
I2C_stop(); //Wait until stop operation is completed
return(x);
}
void Write_to_slave(unsigned char addr, unsigned char data)
{
I2C_start();
SSPBUF = RTC_ADDRW; //Slave address + Write
Wait_MSSP();
check_ACK_Master_Transmit(); //Checks the
SSPBUF = addr; // RTC Registor location address to be written
Wait_MSSP();
check_ACK_Master_Transmit();
SSPBUF = data; //data to be writen to the address location
Wait_MSSP();
check_ACK_Master_Transmit();
I2C_stop();
Wait_MSSP();
}
void I2C_write(unsigned char addr)
{
PIR1bits.SSPIF = 0;
SSPBUF = addr;
while(PIR1bits.SSPIF == 0);
return;
}
void Reset_time()
{
I2C_start();
I2C_write(RTC_ADDRW);
I2C_write(0x00);
I2C_write(0x00);
I2C_write(0x00);
I2C_write(0x01);
I2C_write(0x01);
I2C_write(0x01);
I2C_write(0x01);
I2C_write(0x00);
I2C_stop();
return;
}
void Set_time()
{
Write_to_slave(0x00,0x00); //Write data 0x00 to address 00H (Seconds) of RTC (CH = 0)
Write_to_slave(0x01,0x30); //Write data 0x00 to address 01H(Minutes) of the RTC
Write_to_slave(0x02,0x10); //Write data 0x00 to address 02H(HOUR) of the RTC
Write_to_slave(0x03,0x06); //Write data 0x01 to address 03H (DAY) of the RTC
Write_to_slave(0x04,0x01); //Write data 0x01 to address 04H (Date) of the RTC
Write_to_slave(0x05,0x01); //Write data 0x01 to address 05H (Month) of the RTC
Write_to_slave(0x06,0x16); //Write data 0x00 to address 06H (Year) of the RTC
}
void main()
{
TRISCbits.TRISC0 = 0;
TRISCbits.TRISC1 = 0;
TRISCbits.TRISC2 = 0;
TRISD = 0;
char16x2LCDInit();
I2C_Init();
Reset_time();
Set_time();
while(1)
{
sec = Read_from_slave(0x00);
__delay_ms(10);
Write_Command(0xC0);
LCDWriteInt(BCD2Lowerch(sec),1);
LCDWriteInt(BCD2Upperch(sec),1);
}
}
Just for a clear picture of the transactions happening on the I2C bus, I have attached a snap shot of the I2C Debugger window displaying the I2C operations during the simulation in Proteus. First sequence is as follows: S = start, D0 = Slave address + Write, A = Acknowledgement from slave, 05 = Register address in the RTC, A = Acknowledgement from slave, 01 = data written to 05H, A = Acknowledgement from slave, P = Stop. Similarly for other write cycles and also read, while in read there is "Sr" i.e. I2C_restart followed by "N" NACK and as we can see there is no "P" i.e. stop after NACK. I have also attached the picture of the hardware. I re-read the slave as transmitter mode in DS1307 datasheet, but I do not find anything wrong with the "Read_from _slave" sequence.
Sorry for the tedious message, as any further advise or direction regarding my approach to performing the read operation or identification of any issues with the methods would be of great help. Thanks again!
Regards ~VD