 |
 |
View previous topic :: View next topic |
Author |
Message |
JAM2014
Joined: 24 Apr 2014 Posts: 140
|
Porting DS3231 RTC code to an 18F26Q24 device... |
Posted: Wed Jul 30, 2025 2:03 pm |
|
|
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
|
|
Posted: Fri Aug 01, 2025 12:11 pm |
|
|
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
|
|
Posted: Fri Aug 01, 2025 2:31 pm |
|
|
When you do get it 'up and running' ,please post in the 'library' for others. |
|
 |
|
|
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
|