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 CCS Technical Support

Porting DS3231 RTC code to an 18F26Q24 device...

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



Joined: 24 Apr 2014
Posts: 140

View user's profile Send private message

Porting DS3231 RTC code to an 18F26Q24 device...
PostPosted: Wed Jul 30, 2025 2:03 pm     Reply with quote

Hi All,



I've used the DS3231 RTC for a number of years with great success. I have a new project, and I'm porting some driver code used on a PIC 18F46K22 device to the new PIC. The I2C commands I've used in the past with the old device are not supported on the newer PIC, so I'm trying to get the old code working with the i2c_transfer function. So far, it's not working as expected!

Device: PIC 18F26Q24 powered at 3.3V
Compiler PCH v5.120
Peripheral: DS3231 RTC with 3K pull-ups & powered at 3.3V

The new device is a PPS part, so I'll start there. Here is my setup code:

Code:

#pin_select SCL1OUT = RTC_SCL
#pin_select SCL1IN  = RTC_SCL

#pin_select SDA1OUT = RTC_SDA
#pin_select SDA1IN  = RTC_SDA

#use i2c(Master,I2C1, Stream = DS3231)


I believe this is correct as I'm seeing clock activity on the SCL line and data activity on the SDA line with a scope.

DS3231 Config Function
Code:

void ConfigDS3231(void){
//This subroutine keeps the RTC oscillator ON while on Vbat, and enables the DS3231 Square Wave output at 1 Hz on pin #3.
//Note: This routine now uses the new 'i2c_transfer' function.....
     //i2c_start();
     //i2c_write(WRITE_CNTRL);
     //i2c_write(CONTROL_REG);
     //i2c_write(CONTROL_INIT_VAL); //value is 0x00
     //i2c_stop();
   wI2C_Data[0] = CONTROL_REG;
   wI2C_Data[1] = CONTROL_INIT_VAL;
   i2c_transfer(DS3231, WRITE_CNTRL, wI2C_Data, 2);
}


This seems to be working as I'm getting a 1Hz square wave on the DS3231 square wave output pin.

Date/Time Set Code
Code:

void Set_DS3231SN_Time(void){
//This subroutine 'syncs' the time & date registers in the DS3231 RTC with data derived from GNSS time!
 
      char i;
/*
      DS3231SN_regs[SECONDS_REG]     = TempSecond;   // seconds (always zero!)
      DS3231SN_regs[MINUTES_REG]     = TempMinute;   // minutes
      DS3231SN_regs[HOURS_REG]       = TempHour;      // hour 0 to 12 or 0 to 24
      DS3231SN_regs[DAY_OF_WEEK_REG] = 2;          // not used
      DS3231SN_regs[DATE_REG]        = TempDay;      // date
      DS3231SN_regs[MONTH_REG]       = TempMonth;      // month
      DS3231SN_regs[YEAR_REG]        = TempYear;      // year
*/

// Temporary Test Data
      DS3231SN_regs[SECONDS_REG]     = 0;      // seconds (always zero!)
      DS3231SN_regs[MINUTES_REG]     = 10;   // minutes
      DS3231SN_regs[HOURS_REG]       = 11;   // hour 0 to 12 or 0 to 24
      DS3231SN_regs[DAY_OF_WEEK_REG] = 2;    // not used
      DS3231SN_regs[DATE_REG]        = 30;   // date
      DS3231SN_regs[MONTH_REG]       = 7;      // month
      DS3231SN_regs[YEAR_REG]        = 25;   // year

   for(i=0; i<7; i++){
        DS3231SN_regs[i] = BINtoBCD(DS3231SN_regs[i]);
      }

      // write 7 bytes of BCD time/date data to DS3231
      //i2c_start();
      //i2c_write(WRITE_CNTRL);

      // start at seconds register
      //i2c_write(SECONDS_REG);

      // write 7 bytes to registers 0 to 6
      //for(i=0; i<7; i++)
      //{
         //i2c_write(DS3231SN_regs[i]);
      //}
      //i2c_stop();

    wI2C_Data[0] = DS3231SN_regs[SECONDS_REG];      // seconds (always zero!)
      wI2C_Data[1] = DS3231SN_regs[MINUTES_REG];        // minutes
      wI2C_Data[2] = DS3231SN_regs[HOURS_REG];          // hour 0 to 12 or 0 to 24
      wI2C_Data[3] = DS3231SN_regs[DAY_OF_WEEK_REG];    // not used
      wI2C_Data[4] = DS3231SN_regs[DATE_REG];           // day
      wI2C_Data[5] = DS3231SN_regs[MONTH_REG];          // month
      wI2C_Data[6] = DS3231SN_regs[YEAR_REG];           // year
    i2c_transfer(DS3231, WRITE_CNTRL, wI2C_Data, 7);
}


Not sure if this is correct or not?

Date/Time Read Code
Code:

void Read_DS3231SN_Time(void){
   int8 iIndex = 0;

   //i2c_start();
   //i2c_write(WRITE_CNTRL);

   // start i2c read at seconds register
   //i2c_write(SECONDS_REG);

   //i2c_start();
   //i2c_write(READ_CNTRL);

   // read the 7 bytes from the DS3231SN. Mask off the unused bits - JAM Need to reformat these using rI2C_Data!
   //DS3231SN_regs[SECONDS_REG]     = i2c_read() & 0x7f;
   //DS3231SN_regs[MINUTES_REG]     = i2c_read() & 0x7f;
   //DS3231SN_regs[HOURS_REG]       = i2c_read() & 0x7f;   
   //DS3231SN_regs[DAY_OF_WEEK_REG] = i2c_read() & 0x07;
   //DS3231SN_regs[DATE_REG]        = i2c_read() & 0x3f;
   //DS3231SN_regs[MONTH_REG]       = i2c_read() & 0x1f;
   //DS3231SN_regs[YEAR_REG]        = i2c_read(0);
   //i2c_stop();
   
   //wI2C_Data[0] = SECONDS_REG;
   //wI2C_Data[1] = READ_CNTRL;
   //i2c_transfer(DS3231, WRITE_CNTRL, wI2C_Data, 2, rI2C_Data, 7);

     wI2C_Data[0] = SECONDS_REG;
     i2c_transfer(DS3231, WRITE_CNTRL, wI2C_Data, 1);
     i2c_transfer(DS3231, READ_CNTRL, wI2C_Data, 0, rI2C_Data, 7);

   // read the 7 bytes from the DS3231SN. Mask off the unused bits - JAM Need to reformat these using rI2C_Data!
   DS3231SN_regs[SECONDS_REG]     = rI2C_Data[0] & 0x7f;
   DS3231SN_regs[MINUTES_REG]     = rI2C_Data[1] & 0x7f;
   DS3231SN_regs[HOURS_REG]       = rI2C_Data[2] & 0x7f;   
   DS3231SN_regs[DAY_OF_WEEK_REG] = rI2C_Data[3] & 0x07;
   DS3231SN_regs[DATE_REG]        = rI2C_Data[4] & 0x3f;
   DS3231SN_regs[MONTH_REG]       = rI2C_Data[5] & 0x1f;
   DS3231SN_regs[YEAR_REG]        = rI2C_Data[6];

// Here we look at bit #6 of the hour register to determine if we are in 12 or 24 hour
// mode. For 24 hour mode, we look at bit #0 to bit #5 to determine the hour. In 12 mode,
// we look at bit #0 to bit #4 to determine the hour, and bit #5 to determine AM/PM.

   if ((DS3231SN_regs[HOURS_REG] & 0x40) == 0x40)   //12 hour mode
   {
      AM_PM = bit_test(DS3231SN_regs[HOURS_REG], 5);   
         DS3231SN_regs[HOURS_REG] = (DS3231SN_regs[HOURS_REG] & 0x1f);
      Use12HFormat = 1;
   }
   else                                 //24 hour mode   
   {                                 
      DS3231SN_regs[HOURS_REG] = (DS3231SN_regs[HOURS_REG] & 0x3f);
      Use12HFormat = 0;
   }

   //Here we convert the BCD data in the DS3231 registers to binary for display!
   for(iIndex=0; iIndex<7; iIndex++)
      {
      DS3231SN_regs[iIndex] = BCDtoBin(DS3231SN_regs[iIndex]);
      }
}


Not sure if this is correct or not?

I'd appreciate it if someone could look at these functions and offer some comments on what I might be doing wrong!

Thanks,

Jack
JAM2014



Joined: 24 Apr 2014
Posts: 140

View user's profile Send private message

PostPosted: Fri Aug 01, 2025 12:11 pm     Reply with quote

Hi All,

Well, I've made some progress! My time set routine was not sending the required number of bytes. You must lead with the address of the SECONDS_REG, and then write 7 bytes of time data. I was only sending 7 bytes total, not the required 8!

Code:

void Set_DS3231SN_Time(void){
//This subroutine 'syncs' the time & date registers in the DS3231 RTC with data derived from GNSS time!
 
      unsigned int8  i;
/*
      DS3231SN_regs[SECONDS_REG]     = TempSecond;   // seconds (always zero!)
      DS3231SN_regs[MINUTES_REG]     = TempMinute;   // minutes
      DS3231SN_regs[HOURS_REG]       = TempHour;      // hour 0 to 12 or 0 to 24
      DS3231SN_regs[DAY_OF_WEEK_REG] = 2;          // not used
      DS3231SN_regs[DATE_REG]        = TempDay;      // date
      DS3231SN_regs[MONTH_REG]       = TempMonth;      // month
      DS3231SN_regs[YEAR_REG]        = TempYear;      // year
*/

// Temporary Test Data
      DS3231SN_regs[SECONDS_REG]     = 0;      // seconds (always zero!)
      DS3231SN_regs[MINUTES_REG]     = 10;   // minutes
      DS3231SN_regs[HOURS_REG]       = 11;   // hour 0 to 12 or 0 to 24
      DS3231SN_regs[DAY_OF_WEEK_REG] = 2;    // not used
      DS3231SN_regs[DATE_REG]        = 30;   // date
      DS3231SN_regs[MONTH_REG]       = 7;      // month
      DS3231SN_regs[YEAR_REG]        = 25;   // year

   for(i=0; i<7; i++){
        DS3231SN_regs[i] = BINtoBCD(DS3231SN_regs[i]);
      }

     wI2C[0] = SECONDS_REG;
    wI2C_Data[1] = DS3231SN_regs[SECONDS_REG];      // seconds (always zero!)
      wI2C_Data[2] = DS3231SN_regs[MINUTES_REG];        // minutes
      wI2C_Data[3] = DS3231SN_regs[HOURS_REG];          // hour 0 to 12 or 0 to 24
      wI2C_Data[4] = DS3231SN_regs[DAY_OF_WEEK_REG];    // not used
      wI2C_Data[5] = DS3231SN_regs[DATE_REG];           // day
      wI2C_Data[6] = DS3231SN_regs[MONTH_REG];          // month
      wI2C_Data[7] = DS3231SN_regs[YEAR_REG];           // year
    i2c_transfer(DS3231, WRITE_CNTRL, wI2C_Data, 8);




Everything else seems to be working, but I haven't done any extensive testing. I'll update this thread if I find any other issues!

Jack
temtronic



Joined: 01 Jul 2010
Posts: 9560
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Aug 01, 2025 2:31 pm     Reply with quote

When you do get it 'up and running' ,please post in the 'library' for others.
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