CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

DS1307 to PIC18F452

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Andrew



Joined: 12 Aug 2004
Posts: 7

View user's profile Send private message

DS1307 to PIC18F452
PostPosted: Thu Aug 12, 2004 2:08 pm     Reply with quote

Hello

I'm going to be using a real-time clock in a project and the DS1307 RTC looked to be the best one. I can't seem to read from or write to it very reliably though.
My test program is set up to read address 0x00 (the seconds register) from the DS1307 once each second. However, the value is usually read incorrectly or not read at all. For example, I read the values (one per second) 29 30 31 18 FF 00 over a six second period. The 29 30 31 values show that the DS1307 is accurately keeping the time but the 18 FF 00 indicate trouble. Another test program indicated that the DS1307 wasn't always acknowledging the write/read commands.
I've searched this forum (and other places) for example code and stuff but haven't found anything to help.
I'm using 4.7k pull-up resistors on the I2C bus, I have an I2C EEPROM chip (24LC256) on the same bus (the results seem to be the same whether the EEPROM is in its socket or not though), I have a 3.3V regulator attached to the Vbat pin on the DS1307 to simulate a battery, and I'm using a PIC18F452 running at 20MHz as the I2C master.
Here's the test program I'm using:

Code:

// main.h

#include <18F452.h>
#device adc=8
#use delay(clock=20000000,RESTART_WDT)
#fuses HS, BROWNOUT, BORV20, PUT, STVREN
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,restart_wdt)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,restart_wdt,force_hw)
  #USE DYNAMIC_MEMORY


Code:

// main.c

#include "main.h"
  #ZERO_RAM

unsigned int read_rtc(unsigned int adr);
unsigned int read_eeprom(unsigned int adr);

void main()
{
    disable_interrupts(global);
   
    output_float(PIN_C3);
    output_float(PIN_C4);
   
    i2c_start();
    i2c_write(0xd0);
    i2c_write(0x00);
    i2c_write(0x00);
    i2c_stop();
   
    printf("\fStarting...\r\n");
    while(1)
    {
       printf("%x %x\r\n", read_rtc(0), read_eeprom(0));
       delay_ms(1000);
    }
}

unsigned int read_rtc(unsigned int adr)
{
    unsigned int data;
   
    i2c_start();
    i2c_write(0xd0);
    i2c_write(adr);

    i2c_start();
    i2c_write(0xd1);
    data = i2c_read(0);
   
    i2c_stop();
   
    return data;
}

unsigned int read_eeprom(unsigned int adr)
{
    unsigned int data;
   
    i2c_start();
    i2c_write(0xa0);
    i2c_write(adr);
   
    i2c_start();
    i2c_write(0xa1);
    data = i2c_read(0);
   
    i2c_stop();

    return data;
}


Also, if I use 'Slow' in the '#use i2c' instead of 'Fast', I only read FF. If I remove the 'force_hw', I read mostly jibberish or FF.
Is there something I'm overlooking? Something I'm doing incorrectly? Any suggestions (or solutions) would be greatly appreciated.

Thanks in advance,
Andrew
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 12, 2004 2:23 pm     Reply with quote

Does the EEPROM always give you the correct value?

You should probably specify the NOLVP flag in the fuses if you are not using the low voltage programming. It is bound to byte you in the butt if you don't.
Andrew



Joined: 12 Aug 2004
Posts: 7

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 2:43 pm     Reply with quote

I've decided to keep the EEPROM out of its socket for now and focus solely on getting the RTC to interface correctly. The EEPROM did, however, function as expected (with or without the DS1307 on the bus).
I also added the NOLVP flag as you suggested even though I disable low-voltage programming via the PIC programmer (EPIC from microEngineering Labs, Inc.)
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 12, 2004 2:48 pm     Reply with quote

What voltage are you running the DS1307 at?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 2:55 pm     Reply with quote

Quote:
Also, if I use 'Slow' in the '#use i2c' instead of 'Fast', I only read FF

The ds1307 is a Standard (slow) speed device. It only runs at 100 KHz,
max. You can't use "Fast" speed with it. See page 3 of the data sheet.
http://pdfserv.maxim-ic.com/en/ds/DS1307.pdf
Andrew



Joined: 12 Aug 2004
Posts: 7

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 3:05 pm     Reply with quote

Mark:
The DS1307 (along with everything else) is being run at 5V.
Following your post, I grounded the Vbat pin just to be sure the DS1307 wasn't switching over to battery power and disallowing access. Unfortunately this didn't affect the problem and the results were still the same (eg. 01 27 01 04 05 06 07 FF)

PCM Programmer:
Quote:
Also, if I use 'Slow' in the '#use i2c' instead of 'Fast', I only read FF.

I've kept using 'Fast' because it seems to be the only way to get any sort of valid response from the DS1307. I've also tried running the 18F452 at 4MHz to slow the bus speed down and used both 'Fast' and 'Slow', but the results were the same (ie. 'Fast' lead to some valid data, 'Slow' lead to all FF's)
Am I using the 'Slow' option incorrectly? It seems like using 'Slow' should make a positive difference but that's not the case, which only confuses me more.


Last edited by Andrew on Thu Aug 12, 2004 3:10 pm; edited 1 time in total
LomasS
Guest







PostPosted: Thu Aug 12, 2004 3:10 pm     Reply with quote

I have a DS1307 but I am using 18F252 so similar to your setup, my clock is at 3.6864MHz though.
I tried your code after changing the #include to <18F252.h> and the
#use delay(clock=3686400,RESTART_WDT).
With these changes & no EEPROM, your code works OK with seconds changing by 1 without a hiccough.

Hope this helps.
Steve.
Andrew



Joined: 12 Aug 2004
Posts: 7

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 3:29 pm     Reply with quote

Alright thinking along the lines of the write command not being acknowledged, I modified the read_rtc() to wait for an ack...

Code:

unsigned int read_rtc(unsigned int adr)
{
    unsigned int data;
    short ackbit;
   
    do
    {
        i2c_start();
        ackbit = i2c_write(0xd0);
    } while(ackbit);
    i2c_write(adr);
   
    i2c_start();
    i2c_write(0xd1);
    data = i2c_read(0);
   
    i2c_stop();

    return data;
}


That seems to fix the problem, both at 20MHz and 4MHz. I'd used something similar to that 'wait-for-ack' code before, but that seemed to hang the 18F452 sometimes and using a timeout variable was as non-productive as before.

However, I still use 'Fast' in the #use i2c directive, 'Slow' continues to cause only FF to be read. Am I missing something? Using 'Slow' seems like it should be the correct one (especially at 20MHz), but it's not.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 3:33 pm     Reply with quote

I see another problem. Your EEPROM code is incorrect.
It looks like you're writing your routines as if an "int" is 16-bits.
The problem with this is, in CCS an int is 8-bits. Also, the
CCS i2c routines expect 8-bit parameters. You're using them
as if they accept 16-bit values.

So your code is not sending the proper number of bytes to
the EEPROM. I don't know what problems this will cause, but
it might screw up the i2c bus. See the CCS driver file, 24256.C,
for sample routines. The file can be found in this folder:
c:\Program Files\Picc\Drivers
Andrew



Joined: 12 Aug 2004
Posts: 7

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 4:40 pm     Reply with quote

I never really used the EEPROM part of the code to do serious reading/writing, I just wrote a value to address 0x0000, verified that it read back correctly several times, and shifted my focus to the DS1307. I'll be sure to correct the code and addressing and stuff when I actually use it, thanks for bringing that to my attention.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 4:45 pm     Reply with quote

In a test program, all possible sources of error should be removed.
Routines that are known to be incorrect should not be included in
the program. Also, interface speeds that are known to be out of
spec should not be used. If you want to do such things, you are
on your own.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 12, 2004 6:07 pm     Reply with quote

You should always do the ack check or else your data might not be valid.

I have a function like this

Code:

/* *************************************************************************
  DESCRIPTION:  This function checks to see if an i2c device will ACK

  RETURN: TRUE if device ACKed otherwise FALSE

  ALGORITHM:  none

  NOTES:  none
 *************************************************************************** */
static BOOLEAN I2C_Device_Ready(
  UINT8 id) /* Address of I2C device */
{
  do
  {
    /* Important to clear these bits before we attempt to write */
    PIR2bits.BCLIF = 0;
    SSPCON1bits.WCOL = 0;
    I2C_IDLE();             /* ensure module is idle */
    I2C_START();
  } while (PIR2bits.BCLIF);

  I2C_WRITE(id);

  if (!SSPCON2bits.ACKSTAT) /* test for ACK condition, if received */
    return (TRUE);
  return (FALSE);
}


Note that the I2C_????() functions are my own and not CCS's
John Morley



Joined: 09 Aug 2004
Posts: 97

View user's profile Send private message

PostPosted: Thu Aug 12, 2004 9:00 pm     Reply with quote

Hi,

Here is a link to a project that uses the DS1307 RTC with CCS C. The URL for the project (a talking clock) is:

http://www.rentron.com/CCS_C/SERLED_C.htm
_________________
John Morley
Andrew



Joined: 12 Aug 2004
Posts: 7

View user's profile Send private message

PostPosted: Fri Aug 13, 2004 2:38 pm     Reply with quote

Alright so I got a simple interface to the DS1307 working. It reads the time from the DS1307 and relays it out the serial port to display the time in hyperterminal.
However, it seems like the initialization code (simply write_rtc(0x00, 0x00); write_rtc(0x07, 0x10); ) hangs and it can require several watchdog-timeout restarts before the initialization goes through and the program gets to the main loop. My guess is it's stalling in the do...while(ackbit) loop.

Code:

void main()
{
    unsigned int v;
    unsigned char c;

    printf("\r\n\nInit...\r\n");
    disable_interrupts(global);

    output_float(PIN_C3);
    output_float(PIN_C4);

    write_rtc(0x00, 0x00);
    write_rtc(0x07, 0x10);

    printf("Starting...\r\n");

    while(1)
    {
        printf("%x:%02x:%02x\r\n", read_rtc(2), read_rtc(1), read_rtc(0));
        delay_ms(1000);
    }

}


Code:

void write_rtc(unsigned int address, unsigned int data)
{
    short ackbit;

    do
    {
        i2c_start();
       ackbit = i2c_write(0xd0);
    } while(ackbit);
    i2c_write(address);
    i2c_write(data);
    i2c_stop();

    return;
}


Any ideas why sometimes it stalls and others it doesn't? Once it's initialized it runs and runs just fine until I stop it.
Here's one example...
Code:


Init...


Init...
Starting...
02:53:00
02:53:01
02:53:02
02:53:03
02:53:04


Suggestions, comments, everything is appreciated.

Andrew
Gabriel Caffese



Joined: 09 Oct 2003
Posts: 39
Location: LA PLATA, ARGENTINA

View user's profile Send private message Visit poster's website MSN Messenger

PostPosted: Fri Aug 13, 2004 4:04 pm     Reply with quote

Andrew,

Canīt you use Timer1, for using the micro as a RTC, too ?
A few months ago, I was involved in a project where costs should be cut off. One thing Iīve done, was replacing DS1307, and doing same thing with the same micro.
Itīs a very, very simple task, wich takes nearly nothing of your micro processing time.

Gabriel.-
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group