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

DS1337 RTC Driver

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

DS1337 RTC Driver
PostPosted: Mon Oct 02, 2006 8:57 am     Reply with quote

Here is a driver for the Maxim DS1337 I2C RTC. This is PCM Programmer's PCF8583 driver code from post:

http://www.ccsinfo.com/forum/viewtopic.php?t=27988

That has been modified for the DS1337. The basic functionality has been tested but I can't guarantee that it's 100% error free. I will edit the post with any bug corrections.

The DS1337 is good solution for a simple and small RTC that has alarms, although it may be hard to find.

Version1 10/02/06

Code:

// DS1337.H


/* ---------------------------------------------
Use the following lines or declare in application.

#ifndef DS1337_SDA
#define DS1337_SDA  PIN_C4
#define DS1337_SCL  PIN_C3
#endif

#use i2c(master, sda=DS1337_SDA, scl=DS1337_SCL)
*/

// i2c addresses
#define DS1337_I2C_WRITE_ADDR    0xD0
#define DS1337_I2C_READ_ADDR     0xD1

// DS1337 register addresses
#define DS1337_SECONDS_REG       0x00
#define DS1337_MINUTES_REG       0x01
#define DS1337_HOURS_REG         0x02
#define DS1337_DAY_OF_WEEK_REG   0x03
#define DS1337_DATE_REG          0x04
#define DS1337_MONTH_REG         0x05
#define DS1337_YEAR_REG          0x06
//DS1337 Unique Registers
#define DS1337_ALM1_SECONDS_REG  0x07
#define DS1337_ALM1_MINUTES_REG  0x08
#define DS1337_ALM1_HOURS_REG    0x09
#define DS1337_ALM1_DAYDATE_REG  0x0A
#define DS1337_ALM2_MINUTES_REG  0x0B
#define DS1337_ALM2_HOURS_REG    0x0C
#define DS1337_ALM2_DAYDATE_REG  0x0D
#define DS1337_CONTROL_REG       0x0E
#define DS1337_STATUS_REG        0x0F

//Enable Oscillator, Disable SQWV, Disable Ints
#define DS1337_CTRL_REG_INIT_VAL 0x04

//Clear OSF (Oscillator Stop Flag), A2F (Alarm 2 Flag), and A1F (Alarm 1 Flag)
#define DS1337_CLEAR_STATUS_VAL  0x00


char const weekday_names[7][4] = {  {"Sun"},
                                    {"Mon"},
                                    {"Tue"},
                                    {"Wed"},
                                    {"Thu"},
                                    {"Fri"},
                                    {"Sat"} };

// This structure defines the user's date and time data.
// The values are stored as unsigned integers.  The user
// should declare a structure of this type in the application
// program. Then the address of the structure should be
// passed to the DS1337 read/write functions in this
// driver, whenever you want to talk to the chip.
typedef struct {
   int8 seconds;    // 0 to 59
   int8 minutes;    // 0 to 59
   int8 hours;      // 0 to 23  (24-hour time)
   int8 day;        // 0 = Sunday, 1 = Monday, etc.
   int8 date;       // 1 to 31
   int8 month;      // 1 to 12
   int8 year;       // 00 to 99
} date_time_t;


//----------------------------------------------
void DS1337_write_byte(int8 address, int8 data) {

   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();

   enable_interrupts(GLOBAL);

}

//----------------------------------------------
int8 DS1337_read_byte(int8 address) {

   int8 retval;

   disable_interrupts(GLOBAL);
   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(address);
   i2c_start();
   i2c_write(DS1337_I2C_READ_ADDR);
   retval = i2c_read(0);
   i2c_stop();
   enable_interrupts(GLOBAL);

   return(retval);
}


//----------------------------------------------
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99.

int8 bin2bcd(int8 value) {

   char retval;
   retval = 0;

   while(1)
     {
      // Get the tens digit by doing multiple subtraction
      // of 10 from the binary value.
      if(value >= 10)
        {
         value -= 10;
         retval += 0x10;
        }
      else // Get the ones digit by adding the remainder.
        {
         retval += value;
         break;
        }
      }

   return(retval);

}

//----------------------------------------------
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.

char bcd2bin(char bcd_value) {

   char temp;

   temp = bcd_value;

   // Shifting the upper digit right by 1 is
   // the same as multiplying it by 8.
   temp >>= 1;

   // Isolate the bits for the upper digit.
   temp &= 0x78;

   // Now return: (Tens * 8) + (Tens * 2) + Ones
   return(temp + (temp >> 2) + (bcd_value & 0x0f));

}

//----------------------------------------------
void DS1337_set_datetime(date_time_t *dt) {

   int8 bcd_sec;
   int8 bcd_min;
   int8 bcd_hrs;
   int8 bcd_day;
   int8 bcd_date;
   int8 bcd_mon;
   int8 bcd_year;

   // Convert the input date/time into BCD values
   // that are formatted for the DS1337 registers.
   bcd_sec  = bin2bcd(dt->seconds);
   bcd_min  = bin2bcd(dt->minutes);
   bcd_hrs  = bin2bcd(dt->hours);    //default to 24 hour mode
   bcd_day  = bin2bcd(dt->day);
   bcd_date = bin2bcd(dt->date);
   bcd_mon  = bin2bcd(dt->month);    //ignore century bit
   bcd_year = bin2bcd(dt->year);

   // Write to the date and time registers.  Disable interrupts
   // so they can't disrupt the i2c operations.
   disable_interrupts(GLOBAL);

   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(DS1337_SECONDS_REG);   // Start at seconds register
   i2c_write(bcd_sec);
   i2c_write(bcd_min);
   i2c_write(bcd_hrs);
   i2c_write(bcd_day);
   i2c_write(bcd_date);
   i2c_write(bcd_mon);
   i2c_write(bcd_year);
   i2c_stop();

   enable_interrupts(GLOBAL);

}

//----------------------------------------------
// Read the Date and Time from the hardware registers
// in the DS1337.
void DS1337_read_datetime(date_time_t *dt) {

   int8 bcd_sec;
   int8 bcd_min;
   int8 bcd_hrs;
   int8 bcd_day;
   int8 bcd_date;
   int8 bcd_mon;
   int8 bcd_year;

   // Disable interrupts so the i2c process is not disrupted.
   disable_interrupts(GLOBAL);

   // Read the date/time registers from the DS1337.
   i2c_start();
   i2c_write(DS1337_I2C_WRITE_ADDR);
   i2c_write(DS1337_SECONDS_REG);   // Start at seconds register
   i2c_start();
   i2c_write(DS1337_I2C_READ_ADDR);

   bcd_sec  = i2c_read();
   bcd_min  = i2c_read();
   bcd_hrs  = i2c_read();
   bcd_day  = i2c_read();
   bcd_date = i2c_read();
   bcd_mon  = i2c_read();
   bcd_year = i2c_read(0);
   i2c_stop();

   enable_interrupts(GLOBAL);

   // Convert the date/time values from BCD to
   // unsigned 8-bit integers. Unpack bits in
   // DS1337 registers where required.
   dt->seconds = bcd2bin(bcd_sec  & 0x7F);
   dt->minutes = bcd2bin(bcd_min  & 0x7F);
   dt->hours   = bcd2bin(bcd_hrs  & 0x3F);
   dt->day     = bcd2bin(bcd_day  & 0x07);
   dt->date    = bcd2bin(bcd_date & 0x3F);
   dt->month   = bcd2bin(bcd_mon  & 0x1F);
   dt->year    = bcd2bin(bcd_year);

}

//----------------------------------------------
//If there has been an oscillator failure since last
//init, then init DS1337. A default time and date is set as well.
void DS1337_init(void) {

    int8 temp = 0;

    //Read the status register to see if the oscillator has failed.
    temp = DS1337_read_byte(DS1337_STATUS_REG);
    //Unpack OSF bit
    temp = temp >> 7;

    //If oscillator has failed then init DS1337
    if(temp) {
      disable_interrupts(GLOBAL);
      i2c_start();
      i2c_write(DS1337_I2C_WRITE_ADDR);
      i2c_write(DS1337_SECONDS_REG);
      i2c_write(0x00);                     //seconds
      i2c_write(0x00);                     //minutes
      i2c_write(0x40);                     //hours & 12/24 hour mode
      i2c_write(0x00);                     //day
      i2c_write(0x01);                     //date
      i2c_write(0x01);                     //month
      i2c_write(0x06);                     //year
      i2c_write(0x00);                     //alm1 seconds
      i2c_write(0x00);                     //alm1 minutes
      i2c_write(0x00);                     //alm1 hours
      i2c_write(0x00);                     //alm1 day/date
      i2c_write(0x00);                     //alm2 minutes
      i2c_write(0x00);                     //alm2 hours
      i2c_write(0x00);                     //alm2 day/date
      i2c_write(DS1337_CTRL_REG_INIT_VAL); //Turn off the squarewave output pin.
      i2c_write(DS1337_CLEAR_STATUS_VAL);  //Clear the status registers
      i2c_stop();
      enable_interrupts(GLOBAL);
   }
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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