DS1307 with PIC16F877A

Status
Not open for further replies.

neelam29

New Member
hi i'm trying to interface DS1307RTC with PIC16f877. I had done interfacing of ds1307 with 89c51 and was sucessful. i have modified the same code a bit for PIC16f877 but this isn't working i'm unable to find out the problem, please help me.
One thing more, in 89c51 code i had written " unsigned char ReadI2Crtc(bit ACK_Bit)" but in pic it gave error: "bit variable must be global or static" so i changed it to "unsigned char ReadI2Crtc(unsigned char ACK_Bit)" is this causing the problem. Please help me....It's really very urgent.

thanks a lot.



#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))

static bit SDA @ PORTBIT(PORTB,7);
static bit SCL @ PORTBIT(PORTB,6);




/////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////


//-------------------------------
// StartRTC I2C
//-------------------------------
void StartRTC(void)
{
SDA = 1;
SCL = 1;
DelayUs(5);DelayUs(5);
SDA = 0;
DelayUs(5);DelayUs(5);
SCL = 0;
DelayUs(5);DelayUs(5);
}

//-------------------------------
// StopRTC I2C
//-------------------------------
void StopRTC(void)
{
SDA = 0;
DelayUs(5);DelayUs(5);
SCL = 1;
DelayUs(5);DelayUs(5);
SDA = 1;
}

//-------------------------------
// Write I2C
//-------------------------------
void WriteI2Crtc(unsigned char Data)
{

for (i3=0;i3<8;i3++)
{
SDA = (Data & 0x80) ? 1:0;
SCL=1;SCL=0;
Data<<=1;
}

SCL = 1;
DelayUs(5);DelayUs(5);
SCL = 0;

}

//-------------------------------
// Read I2C
//-------------------------------
unsigned char ReadI2Crtc(unsigned char ACK_Bit)
{

unsigned char Data=0;

SDA = 1;
for (i3=0;i3<8;i3++)
{
SCL = 1;
Data<<= 1;
Data = (Data | SDA);
SCL = 0;
DelayUs(5);
}

if (ACK_Bit == 1)
SDA = 0; // Send ACK
else
SDA = 1; // Send NO ACK

DelayUs(5);DelayUs(5);
SCL = 1;
DelayUs(5);DelayUs(5);
SCL = 0;

return Data;
}

//-------------------------------
// Read 1 byte form I2C
//-------------------------------
unsigned char ReadRTC(unsigned int Addr)
{
unsigned char Data;
StartRTC();
WriteI2Crtc(0xD0);
//WriteI2Crtc((unsigned char)(Addr>>8)&0xFF); // ....not valid for small EEPROMs
WriteI2Crtc((unsigned char)Addr&0xFF);
StartRTC();
WriteI2Crtc(0xD1);
Data = ReadI2Crtc(NO_ACK);
StopRTC();
return(Data);
}

//-------------------------------
// Write 1 byte to I2C
//-------------------------------
void WriteRTC(unsigned int Addr,unsigned char Data)
{
StartRTC();
WriteI2Crtc(0xD0);
//WriteI2Crtc((unsigned char)(Addr>>8)&0xFF); // send address high....not valid for small EEPROMs
WriteI2Crtc((unsigned char)Addr&0xFF); // send address low
WriteI2Crtc(Data);
StopRTC();
}





void ReadAllRTC(void)
{


Minutes=ReadRTC(0x01);
Minutes=((Minutes & 0xF0)>>4)* 10 + (Minutes & 0x0F);

Hours=ReadRTC(0x02) & 0x1F;
Hours=((Hours & 0xF0)>>4)* 10 + (Hours & 0x0F);

AmPm=(ReadRTC(0x02) & 0x20)>>5;




}
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////



main()
.
.
.
.
.
.

ReadAllRTC();
.
.
.
.
.
 
Written With **broken link removed**

The DS1307 is a great piece of kit, it provides real time date and clock values, and interfaces with the PIC micro via I2C. The values it holds for date/time are, Secs, Mins, Hours, Day, Date, Month and Year

Example of interfacing with a DS1307. Note that on the DS1037 Pin 8 is connected to 5V, Pin 4 is connected to GND and Pin 3 is connected to ground if no backup battery is used!
**broken link removed**
**broken link removed**

Code:
Device = 16F876
Xtal = 4
ALL_DIGITAL = True
PORTB_PULLUPS = True

' Setup the LCD
LCD_DTPIN = PORTB.4
LCD_RSPIN = PORTB.2
LCD_ENPIN = PORTB.3
LCD_INTERFACE = 4
LCD_LINES = 2
LCD_TYPE = 0
 

' Define I2C bus ports
SDA_Pin = PORTA.0 'DS1307 SDA pin
SCL_PIN =PORTA.1 'DS1307 SCL pin

Dim Temp1 As Byte
Dim Temp2 As Byte
Dim TempVal As Byte

Dim Secs As Byte
Dim Mins As Byte
Dim Hrs As Byte
Dim day As Byte
Dim Date As Byte
Dim Month As Byte
Dim Year As Byte
Dim Ctrl As Byte

Dim Secs_last As Byte

'Initialize LCD

Delayms 100
Cls

' Set initial DS1307 time / Date

Secs = 0                     ' Set seconds
Mins = 30                    ' Set minutes
Hrs = 12                      ' Set hours

Day = 1                       ' Set day of week value

Date = 30                     ' Day of month value
Month = 11                   ' Month value
Year = 6                       ' Year value

Ctrl = 0                        ' Set the control byte (leave as 0 in this example)


' The DS1307 works with data in BCD format, so convert BIN to BCD

TempVal=Secs
GoSub BIN_TO_BCD
Secs=TempVal

TempVal=Mins
GoSub BIN_TO_BCD
Mins=TempVal

TempVal=Hrs
GoSub BIN_TO_BCD
Hrs=TempVal

TempVal=Day
GoSub BIN_TO_BCD
Day=TempVal

TempVal=Date
GoSub BIN_TO_BCD
Date=TempVal

TempVal=Month
GoSub BIN_TO_BCD
Month=TempVal

TempVal=Year
GoSub BIN_TO_BCD
Year=TempVal

BStart

' The datasheet specifies the first byte is 1101000x where x is read(1) or write(0).
' The second byte tells the DS 1307 where to start reading, 0 is at the start.
' The Ctrl byte contains advanced features, read the datasheet for more info
Busout 11010000, 0, [Secs, Mins, Hrs, day, Date, Month, Year, Ctrl] 'Write initial values for time / Date

BStop

Delayms 20

Main:

BStart

' The datasheet specifies the first byte is 1101000x where x is read(1) or write(0).
' The second byte tells the DS 1307 where to start reading, 0 is at the start.
BusIn 11010001, 0, [Secs, Mins, Hrs, day, Date, Month, Year, Ctrl]

BStop

' The DS1307 sends it data in BCD, therefore it must be changed to
' BIN so that it can be easily used (eg, print onto an LCD)

TempVal=Secs
GoSub BCD_TO_BIN
Secs=TempVal

TempVal=Mins
GoSub BCD_TO_BIN
Mins=TempVal

TempVal=Hrs
GoSub BCD_TO_BIN
Hrs=TempVal

TempVal=Date
GoSub BCD_TO_BIN
Date=TempVal

TempVal=Month
GoSub BCD_TO_BIN
Month=TempVal

TempVal=Year
GoSub BCD_TO_BIN
Year=TempVal


 

If Secs - Secs_last = 0 Then Goto Main                'If there is update in Secs, display time and Date

' The Dec2 modifier makes sure that each value will have 2 characters, eg 1 becomes 01
Print At 1,1,"Time: ",Dec2 Hrs, ":", Dec2 Mins,":", Dec2 Secs
Print At 2,1,"Date: ", Dec2 Date, "-", Dec2 Month, "-", Dec2 Year

Secs_last = Secs

Goto Main

BCD_TO_BIN:                                    ' Convert the BCD values into BIN

     Temp1 = $0F & TempVal                     ' Clear off the top four bits
     Temp1 = DIG Temp1, 0
     Temp2 = TempVal >> 4                       ' Shift down four to read 2 BCD value
     Temp2 = DIG Temp2, 0
     TempVal = Temp2 * 10 + Temp1

     Return

BIN_TO_BCD:

     Temp1 = Dig TempVal, 0                     ' GET THE DEC DIGIT FOR THE FIRST NIBBLE
     Temp2 = Dig TempVal, 1                     ' GET THE DEC DIGIT FOR THE FIRST NIBBLE
     Temp2 = Temp2 << 4                          ' MOVE NUMBER OVER TO 2ND NIBBLE
     TempVal = Temp1 ^ Temp2                  ' XOR THEM TOGTHER TO MAKE THE WHOLE BCD NUMBER
    
     Return
 
What compiler are you using?

Shouldn't SDA and SCL be declared volatile?

Can't you define a static bit something like,
static byte flags;
static bit ACK_bit @ &flags*8+0;
static bit Other_bit @ &flags*8+1;

Mike.
 
Thanks a Lot Mike for replying. I'm using hitech picc. I tried defining sda and scl as:
volatile bit SDA @ PORTBIT(PORTB,7);
volatile bit SCL @ PORTBIT(PORTB,6);

&

#define NO_ACK 0
#define ACK 1


but still nothing is happening. If i set PORTB=0x00 i get minutes = 0 and if i set PORTB=0xFF i get minutes = 165.........i'm helpless please help me out.....Thankss once again
 
Last edited:
I think your problem is that you converted code from 8051. Unlike the 8051, when using the pic you have to change the data direction register in order to receive bytes.

Have you looked at the i2c example that comes with PICC Lite?

Mike.
 
OK. Yes i went through i2c example but couldn't use it i found it bit difficult.I'm almost new to pic. And what is data direction register. can you please share some code with me. thanks for replying
 
Last edited:
Read the datasheet! - like I said above though, you really need a reasonable knowledge of assembler to use a C compiler - you can't expect to move to a PIC (or any new controller) without studying the datasheet, and having some knowledge of what you're doing. You might try loking at PIC C sites?, presumably the manufacturer of your compiler has one?, check their examples - but you will only blindly be following something you don't understand!.
 
neelam29 said:
anybody with some helpful and sensible reply please....m in very much need of this code....

I may have written a fully functional example in PIC Basic, but it is well commented, have you even considered it?
 
what kinda compiler are you using that you've written your own i2c routines? I know microchip C18 has libraries with hardware and software i2c routines, and so does MikroC
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…