# PIC18, I2C Master Receive, Cant Read from SSPBUF to a Variable

I am using a Master PIC18F4620, Slave DS1307. All I am doing is setting the seconds to (0) at the beginning of the program, then I read it. I can't seem to read correctly, the value that is being returned from the SSPBUF register is the Slave+Writebit Address.

Everything is perfect on HW & Simulation, how is so? I used an I2C Debugger on Proteus and it is all working fine, I am indeed writing and reading CORRECT values, I then checked using my PicKit3 Debugger HW, and I found out something very interesting. The SSPBUF DOES transmit and receive, therefore its value changes, but the assignment statement from the SSPBUF to a variable FAILS.

#include "18F4620_Config.h"
#include "I2C.h"
#include "Generic_LCD.h"
#include "stdio.h"

#define _XTAL_FREQ 16e6
#define _RTC_WRITE 0xD0
#define CONTROL 0x07       // Address to access Ds1307 CONTROL register

unsigned char seconds;
char myString[6] = {0};

void main(void)
{
LCD_Init();
LCD_Clear();

I2C_Master_Init();

DS1307_Set_Seconds(35);
while (1)
{

LCD_Goto(6, 1);
sprintf(myString,"%x ",seconds);
LCD_Print(myString);

__delay_ms(1000);
}
}


As for the two used functions.

void DS1307_Set_Seconds(unsigned char secs)
{
if (secs <= 60)
{
unsigned char higher = (secs / 10) << 4;
unsigned char lower = (secs % 10);
unsigned data = higher | lower;
I2C_Start();
I2C_Write(_RTC_WRITE);
I2C_Write(0x00);
I2C_Write(data);
I2C_Stop();
}
}

{
unsigned char sec;
I2C_Start();
I2C_Write(_RTC_WRITE);
I2C_Restart();
I2C_NACK();
I2C_Stop();
return (sec);
}


The only thing that is being printed right now is (D1) on the LCD. I noticed another strange behavior, if instead of assigning SSPBUF value to a variable, I pass the SSPBUF as a parameter to the sprintf function, IT WORKS!. Like this

while (1)
{

LCD_Goto(6, 1);
sprintf(myString,"%x ",SSPBUF);
LCD_Print(myString);

__delay_ms(1000);
}


Edit 1: Solution As mentioned in the comments, the solution is to read from the SSPBUF AFTER the I2C Communication has stopped entirely.

Therefore these are the code changes

void I2C_Read_Byte(void)
{
//---[ Receive & Return A Byte ]---
RCEN = 1; // Enable & Start Reception
while (!SSPIF); // Wait Until Completion
SSPIF = 0; // Clear The Interrupt Flag Bit
}

{
I2C_Start();
I2C_Write(_RTC_WRITE);
I2C_Restart();
I2C_NACK();
I2C_Stop();
return (SSPBUF);
}

while (1)
{

LCD_Goto(6, 1);
sprintf(myString, "%x ", seconds);
LCD_Print(myString);

__delay_ms(1000);
}

• Can you pinpoint the problem a bit more? Are you sure that the var “sec” gets filled with the i2c data, or is that the question? – Ananas_hoi Sep 19 '20 at 7:23
• The problem is that the var "sec" gets filled with the I2C Slave Address? The question is why? – Abd-AlRahman Muhammad Sep 19 '20 at 13:03