ds1307 am/pm time setting

Hi... Very quick question..

How do I change the setting to be 12 hour am/pm in the following code snippet?

*hour = bcdToDec(Wire.receive() & 0x7f); //Change this if 12 hour am/pm

*hour = bcdToDec(Wire.receive() & 0x1f);

See getClock and setClock functions:

//clock SDA to analog pin 4   SCL to analog pin 5

#define DEBUG            //compile serial monitor clock display 
#define SETCLOCK     //compile clock setup code

#include "Wire.h"

#define DS1307_I2C_ADDRESS 0x68       //seven bit address
#define MAXLINE 10
#define Mode12 1
#define Mode24 0
#define AM 0
#define PM 1

static char *dayname[] =
{ "Sun",
"Mon",     
"Tue",   
"Wed",  
"Thu",
"Fri",
"Sat"
};

void setup()
{
  Wire.begin();
  Serial.begin(9600);

#ifdef SETCLOCK
  char ans[1]; 
  int serbytes=0;
  Serial.println("Enter 'y' to set clock");
  serbytes = getSerStrWait(ans, 1, 10);
  if (strcmp(ans, "y") == 0) {
    setClock();
  }  
#endif

} 

void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year, ampm;

  getClock(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year, &ampm);

#ifdef DEBUG
  leadzero(hour);
  Serial.print(hour, DEC);
  Serial.print(":");
  leadzero(minute);
  Serial.print(minute, DEC);
  Serial.print(":");
  leadzero(second);
  Serial.print(second, DEC);
  if (ampm != ' ') {                       //not space
    Serial.print(" ");
    Serial.print(ampm);
    Serial.print("M");
  }   
  Serial.print(" ");
  leadzero(month);
  Serial.print(month, DEC);
  Serial.print("/");
  leadzero(dayOfMonth);
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  leadzero(year);
  Serial.print(year, DEC);
  Serial.print(" ");
  Serial.println(dayname[dayOfWeek-1]);
#endif

  delay(1000);
}

void leadzero(byte val) {
  if (val < 10) {
    Serial.print("0");
  }   
}

#ifdef SETCLOCK
void setClock() {
 //prompt for time settings
 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 byte mode = 0;
 byte ampm = 0;
 char ans[1]; 
 char dig2[3];
 int serbytes=0;

 Serial.println("Enter 2 dig year");
 serbytes = getSerStr(dig2, 2);
 year = atoi(dig2); 
 Serial.println("Enter 2 dig month");
 serbytes = getSerStr(dig2, 2);
 month = atoi(dig2); 
 Serial.println("Enter 2 dig day of month (1-31)");
 serbytes = getSerStr(dig2, 2);
 dayOfMonth = atoi(dig2); 

 Serial.println("Enter day of week where 1=SUN 2=MON 3=TUE 4=WED 5=THU 6=FRI 7=SAT");
 serbytes = getSerStr(dig2, 1);
 dayOfWeek = atoi(dig2); 
 
 Serial.println("Enter clock mode - 12 or 24");
 serbytes = getSerStr(dig2, 2);
 if (strcmp(dig2, "12") == 0) {
   mode = Mode12;   
   Serial.println("Enter 'a' or 'p' for AM or PM");
   serbytes = getSerStr(ans, 1);
   if (strcmp(ans, "p") == 0) {
     ampm = PM;  
   } 
 }  
 Serial.print("Enter 2 dig hour ");
 if (mode == Mode12) {
   Serial.println("(1-12)");
 }else{
   Serial.println("(0-23)");
 }  
 serbytes = getSerStr(dig2, 2);
 hour = atoi(dig2); 

 Serial.println("Enter 2 dig minute");
 serbytes = getSerStr(dig2, 2);
 minute = atoi(dig2); 
 second = 0;
 if (mode == Mode12) {
   bitSet(hour,  6);
   if (ampm == PM) { 
      bitSet(hour, 5);
   }  
 }  
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.send(0);
 Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
 Wire.send(decToBcd(minute));
 Wire.send(hour);                                      //already formatted with bits 6 and 5
 Wire.send(decToBcd(dayOfWeek));
 Wire.send(decToBcd(dayOfMonth));
 Wire.send(decToBcd(month));
 Wire.send(decToBcd(year));
 Wire.endTransmission();
}
#endif

// Gets the date and time from the ds1307
void getClock(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year,
          byte *ampm)
{
  byte work;
  byte mode;          //12 or 24 hour
  byte ap_ind;       //am or pm indicator
  
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);      //mask CH bit (bit 7)
  *minute     = bcdToDec(Wire.receive());

//  *hour = bcdToDec(Wire.receive());
  work = Wire.receive();                                                // get hour byte
  mode =  bitRead(work, 6);                                         // if bit  6  set,  running 12 hour mode
  if (mode == Mode12) {
    ap_ind = bitRead(work, 5);                                      // if bit 5 set,  time is PM 
    *hour = bcdToDec(work & 0x1f);                             // mask bits 5 thru 7 for 12 hour clock
    if (ap_ind == PM) {
      *ampm = 'P'; 
    }else{
      *ampm = 'A'; 
    }  
  }else{  
    *hour = bcdToDec(work & 0x3f);                             // mask bits 6 and 7 for 24 hour clock
    *ampm = ' ';  
  }  

  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

#ifdef SETCLOCK
int getSerStr(char line[], int lim) {
  int bytesread=0;
  int val=0;
  Serial.flush();  
  while(bytesread<lim) {              
    if( Serial.available() > 0) { 
      val = Serial.read(); 
      if((val == 10) || (val == 13) || (val == '*')) {         
        break;                               // stop reading 
      } 
      line[bytesread] = val;             // add the digit           
      bytesread++;                     // ready to read next character  
    } 
   } 
   line[bytesread] = '\0';                              //terminate string  
   return(bytesread);
} 

int getSerStrWait(char line[], int lim, int waitsecs) {
  int bytesread=0;
  int val=0;
  unsigned long waitms = 1000 * waitsecs;
  unsigned long start = millis();
  Serial.flush();  
  while(bytesread<lim) {              
    if( Serial.available() > 0) { 
      val = Serial.read(); 
      if((val == 10) || (val == 13) || (val == '*')) {         
        break;                               // stop reading 
      } 
      line[bytesread] = val;             // add the digit           
      bytesread++;                     // ready to read next character  
    }
    if (millis() - start > waitms) {
      Serial.flush();
      line[0] = '\0';
      return(0);
    }  
   } 
   line[bytesread] = '\0';                              //terminate string  
   return(bytesread);
} 
#endif

//BCD to decimal conversion: decVal =(bcdVal.NIB1 * 10) + bcdVal.NIB0
//decimal to BCD conversion: bcdVal = (decVal / 10 <<4) + bcdVal // 10

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// Stops the DS1307, but it has the side effect of setting seconds to 0
// Probably only want to use this for testing
/*void stopDs1307()
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(0x80);
  Wire.endTransmission();
}*/

Thanks much for replying and providing the code...

I ran the code to see how it would work.. I entered 11:59 am and waited a minute or so... Then it rolled over to 04:00 am.... I reran the test several times - just to be safe...

I guess I might be missing something... I expected 12:00 pm....

Can you run the example and see if it does the same thing?

Hi... I'm still breaking my head over how to set the hour time 12/24...

I've tried various things including using 0x1f - but it doesn't effect the output... I still reports things back in military / 24 hours... I'm setting the time at 12:59 pm and then it becomes 13:00 instead of 1:00..

*hour = bcdToDec(Wire.receive() & 0x1f); //originally 0x3f

Please let me know what I am doing wrong...

Thanks much.

Here is the corrected code. When I was tweaking it, I forgot to convert from dec to bcd when setting the hour.
Good luck!

//clock SDA to analog pin 4   SCL to analog pin 5

#define DEBUG            //compile serial monitor clock display
#define SETCLOCK     //compile clock setup code

#include "Wire.h"

#define DS1307_I2C_ADDRESS 0x68       //seven bit address
#define MAXLINE 10
#define Mode12 1
#define Mode24 0
#define AM 0
#define PM 1

static char *dayname[] =
{ "Sun",
"Mon",    
"Tue",  
"Wed",  
"Thu",
"Fri",
"Sat"
};

void setup()
{
  Wire.begin();
  Serial.begin(9600);

#ifdef SETCLOCK
  char ans[1];
  int serbytes=0;
  Serial.println("Enter 'y' to set clock");
  serbytes = getSerStrWait(ans, 1, 10);
  if (strcmp(ans, "y") == 0) {
    setClock();
  }  
#endif

}

void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year, ampm;

  getClock(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year, &ampm);

#ifdef DEBUG
  leadzero(hour);
  Serial.print(hour, DEC);
  Serial.print(":");
  leadzero(minute);
  Serial.print(minute, DEC);
  Serial.print(":");
  leadzero(second);
  Serial.print(second, DEC);
  if (ampm != ' ') {                       //not space
    Serial.print(" ");
    Serial.print(ampm);
    Serial.print("M");
  }  
  Serial.print(" ");
  leadzero(month);
  Serial.print(month, DEC);
  Serial.print("/");
  leadzero(dayOfMonth);
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  leadzero(year);
  Serial.print(year, DEC);
  Serial.print(" ");
  Serial.println(dayname[dayOfWeek-1]);
#endif

  delay(1000);
}

void leadzero(byte val) {
  if (val < 10) {
    Serial.print("0");
  }  
}

#ifdef SETCLOCK
void setClock() {
 //prompt for time settings
 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 byte mode = 0;
 byte ampm = 0;
 char ans[1];
 char dig2[3];
 int serbytes=0;

 Serial.println("Enter 2 dig year");
 serbytes = getSerStr(dig2, 2);
 year = atoi(dig2);
 Serial.println("Enter 2 dig month");
 serbytes = getSerStr(dig2, 2);
 month = atoi(dig2);
 Serial.println("Enter 2 dig day of month (1-31)");
 serbytes = getSerStr(dig2, 2);
 dayOfMonth = atoi(dig2);

 Serial.println("Enter day of week where 1=SUN 2=MON 3=TUE 4=WED 5=THU 6=FRI 7=SAT");
 serbytes = getSerStr(dig2, 1);
 dayOfWeek = atoi(dig2);

 Serial.println("Enter clock mode - 12 or 24");
 serbytes = getSerStr(dig2, 2);
 if (strcmp(dig2, "12") == 0) {
   mode = Mode12;  
   Serial.println("Enter 'a' or 'p' for AM or PM");
   serbytes = getSerStr(ans, 1);
   if (strcmp(ans, "p") == 0) {
     ampm = PM;  
   }
 }  
 Serial.print("Enter 2 dig hour ");
 if (mode == Mode12) {
   Serial.println("(1-12)");
 }else{
   Serial.println("(0-23)");
 }  
 serbytes = getSerStr(dig2, 2);
 hour = decToBcd(atoi(dig2));

 Serial.println("Enter 2 dig minute");
 serbytes = getSerStr(dig2, 2);
 minute = atoi(dig2);
 second = 0;
 if (mode == Mode12) {
   bitSet(hour,  6);
   if (ampm == PM) {
      bitSet(hour, 5);
   }  
 }  
 Wire.beginTransmission(DS1307_I2C_ADDRESS);
 Wire.send(0);
 Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
 Wire.send(decToBcd(minute));
 Wire.send(hour);                                      //already formatted with bits 6 and 5
 Wire.send(decToBcd(dayOfWeek));
 Wire.send(decToBcd(dayOfMonth));
 Wire.send(decToBcd(month));
 Wire.send(decToBcd(year));
 Wire.endTransmission();
}
#endif

// Gets the date and time from the ds1307
void getClock(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year,
          byte *ampm)
{
  byte work;
  byte mode;          //12 or 24 hour
  byte ap_ind;       //am or pm indicator
  
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);      //mask CH bit (bit 7)
  *minute     = bcdToDec(Wire.receive());

//  *hour = bcdToDec(Wire.receive());
  work = Wire.receive();                                                // get hour byte
  mode =  bitRead(work, 6);                                         // if bit  6  set,  running 12 hour mode
  if (mode == Mode12) {
    ap_ind = bitRead(work, 5);                                      // if bit 5 set,  time is PM
    *hour = bcdToDec(work & 0x1f);                             // mask bits 5 thru 7 for 12 hour clock
    if (ap_ind == PM) {
      *ampm = 'P';
    }else{
      *ampm = 'A';
    }  
  }else{  
    *hour = bcdToDec(work & 0x3f);                             // mask bits 6 and 7 for 24 hour clock
    *ampm = ' ';  
  }  

  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

#ifdef SETCLOCK
int getSerStr(char line[], int lim) {
  int bytesread=0;
  int val=0;
  Serial.flush();  
  while(bytesread<lim) {              
    if( Serial.available() > 0) {
      val = Serial.read();
      if((val == 10) || (val == 13) || (val == '*')) {        
        break;                               // stop reading
      }
      line[bytesread] = val;             // add the digit          
      bytesread++;                     // ready to read next character  
    }
   }
   line[bytesread] = '\0';                              //terminate string  
   return(bytesread);
}

int getSerStrWait(char line[], int lim, int waitsecs) {
  int bytesread=0;
  int val=0;
  unsigned long waitms = 1000 * waitsecs;
  unsigned long start = millis();
  Serial.flush();  
  while(bytesread<lim) {              
    if( Serial.available() > 0) {
      val = Serial.read();
      if((val == 10) || (val == 13) || (val == '*')) {        
        break;                               // stop reading
      }
      line[bytesread] = val;             // add the digit          
      bytesread++;                     // ready to read next character  
    }
    if (millis() - start > waitms) {
      Serial.flush();
      line[0] = '\0';
      return(0);
    }  
   }
   line[bytesread] = '\0';                              //terminate string  
   return(bytesread);
}
#endif

//BCD to decimal conversion: decVal =(bcdVal.NIB1 * 10) + bcdVal.NIB0
//decimal to BCD conversion: bcdVal = (decVal / 10 <<4) + bcdVal // 10

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// Stops the DS1307, but it has the side effect of setting seconds to 0
// Probably only want to use this for testing
/*void stopDs1307()
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(0x80);
  Wire.endTransmission();
}*/

Wow... It works great... I was able to modify my program as well... Thanks so much for the input!!!

RonC thanks for the excellent sketch, you have saved us a lot of time!