User Tools

Site Tools


arduino:md_ds3231_set_clock.ino
MD_DS3231_Set_clock.ino
// Example program for the MD_DS3231 library
//
// Test the library and control all aspects of the RTC chip functions
// using from the serial monitor.
 
#include <MD_DS3231.h>
#include <Wire.h>
 
#define PRINTS(s)   Serial.print(F(s))
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
 
void setup()
{
  Serial.begin(9600);
  usage();
  RTC.setAlarm1Callback(cbAlarm1);
  RTC.setAlarm2Callback(cbAlarm2);
}
 
void usage(void)
{
  PRINTS("\n[MD_DS3231_Tester]");
  PRINTS("\n?\thelp - this message");
  PRINTS("\ntw yyyymmdd hhmmss dw\twrite the current date, time and day of week (1-7)");
  PRINTS("\ntr\tread the current time");
  PRINTS("\nrr\tread the IC registers as raw RAM");
  PRINTS("\ns\tstatus of the RTC");
  PRINTS("\nd\tcalculate day of week from current date");
  PRINTS("\n\na1i v\talm 1 interrupt enable (v 0=disabled, 1=enabled)");
  PRINTS("\na1f\talm 1 flag reset");
  PRINTS("\na1t v\talm 1 set type (v 0=all s, 1=s, 2=s+m, 3=s+m+h, 4=s+m+h+dt, 5=s+m+h+dy)");
  PRINTS("\na1z\talm 1 zero all values");
  PRINTS("\na1w t v\talm 1 write type t=(as above) time v=yyyymmdd hhmmss dw");
  PRINTS("\n\na2i v\talm2 interrupt enable (v 0=disabled, 1=enabled)");
  PRINTS("\na2f\talm 2 flag reset");
  PRINTS("\na2t v\talm2 set type (v 0=all m, 1=m, 2=m+h, 3=m+h+dt, 4=m+h+dy)");
  PRINTS("\na2z\talm 2 zero all values");
  PRINTS("\na2w t v\talm 2 write type t=(as above) time v=yyyymmdd hhmmss dw");
  PRINTS("\n\nc n v\tcontrol write value v to status n, where n is");
  PRINTS("\n\t0 - Clock Halt (v 0=run, 1=halt)");
  PRINTS("\n\t1 - BB SQW Enable(v 0=halt, 1=run)");
  PRINTS("\n\t2 - SQ Wave Freq (v 1=1Hz, 2=1khz, 3=4khz, 4=8kHz)");
  PRINTS("\n\t3 - TCXO conversion (v unused)");
  PRINTS("\n\t4 - 12 hour mode (v 0=24h, 1=12h)");
  PRINTS("\n\t5 - Alm interrupt operation (v 0=disabled, 1=enabled)");
  PRINTS("\n\t6 - Reset Halted Flag (v unused)");
  PRINTS("\n\t7 - Enabled 32kHz output (v 0=disabled, 1=enabled)");
  PRINTS("\n\t8 - Set aging register (v hex value)");
}
 
const char *dow2String(uint8_t code)
{
  static const char *str[] = {" ---", " Sun", " Mon", " Tue", " Wed", " Thu", " Fri", " Sat"};
 
  return(str[code]);
}
 
const char *ctl2String(codeRequest_t code)
{
 switch (code)
 {
  case DS3231_CLOCK_HALT: return("CLOCK HALT");
  case DS3231_SQW_ENABLE: return("SQW ENABLE");
  case DS3231_SQW_TYPE:   return("SQW TYPE");
  case DS3231_12H:        return("12H MODE");
  case DS3231_TCONV:      return("TEMP CONV");
  case DS3231_INT_ENABLE: return("INTERRUPT ENABLE");
  case DS3231_A1_INT_ENABLE:return("ALM1 ENABLE");
  case DS3231_A2_INT_ENABLE:return("ALM2 ENABLE");
  case DS3231_HALTED_FLAG:return("HALTED FLAG");
  case DS3231_32KHZ_ENABLE:return("32KHZ ENABLE");
  case DS3231_BUSY_FLAG:  return("BUSY FLAG");
  case DS3231_A1_FLAG:    return("ALM1 FLAG");
  case DS3231_A2_FLAG:    return("ALM2 FLAG");
  case DS3231_AGING_OFFSET:return("AGING OFFSET");
  default: return("??");
 };
}
 
const char *sts2String(codeStatus_t code, boolean bHexValue = false)
{
  if (!bHexValue)
  {
    switch (code)
    {
      case DS3231_ERROR:    return("ERROR");
      case DS3231_ON:       return("ON");
      case DS3231_OFF:      return("OFF");
      case DS3231_SQW_1HZ:  return("1Hz");
      case DS3231_SQW_1KHZ: return("1KHz");
      case DS3231_SQW_4KHZ: return("4KHz");
      case DS3231_SQW_8KHZ: return("8KHz");
      default: return("??");
    }
  }          
  else
  {
    static char sz[5];
 
    sprintf(sz, "0x%02x", code);
    return(sz);    
  }
}
 
const char *alm2String(almType_t alm)
{
  switch (alm)
  {
    case DS3231_ALM_ERROR:return("ALM_ERROR");
    case DS3231_ALM_SEC:  return("ALM_SEC");
    case DS3231_ALM_S:    return("ALM_S");
    case DS3231_ALM_MIN:  return("ALM_MIN");
    case DS3231_ALM_M:    return("ALM_M");
    case DS3231_ALM_MS:   return("ALM_MS");
    case DS3231_ALM_HM:   return("ALM_HM");
    case DS3231_ALM_HMS:  return("ALM_HMS");
    case DS3231_ALM_DTHM: return("ALM_DTHM");
    case DS3231_ALM_DTHMS:return("ALM_DTHMS");
    case DS3231_ALM_DDHM: return("ALM_DDHM");
    case DS3231_ALM_DDHMS:return("ALM_DDHMS");
    default: return("??");
  };
}
 
uint8_t htoi(char c)
{
  c = toupper(c);
 
  if (c >= '0' && c <= '9')
      return(c - '0');
  else if (c >= 'A' && c <= 'F')
      return(c - 'A' + 10);
  else
      return(0);
}
 
uint8_t i2dig(uint8_t mode)
// input 2 digits in the specified base
{
  uint8_t  v = 0;
  char    c[3] = "00";
 
  c[0] = readNext();
  c[1] = readNext();
 
  switch (mode)
  {
    case DEC: v = atoi(c);  break;
    case HEX: v = (htoi(c[0]) << 4) + htoi(c[1]); ;  break;
  }
 
  return(v);
}
 
char *p2dig(uint8_t v, uint8_t mode)
// 2 digits leading zero
{
  static char s[3];
  uint8_t i = 0;
  uint8_t n = 0;
 
  switch(mode)
  {
    case HEX: n = 16;  break;
    case DEC: n = 10;  break;
  }
 
  if (v < n) s[i++] = '0';
  itoa(v, &s[i], n);
 
  return(s);
}
 
void showStatus()
{
  PRINTS("\n>- Settings -<");
  PRINT("\n/EOSC Halt Enabled:\t", sts2String(RTC.status(DS3231_CLOCK_HALT)));
  PRINT("\nBBSQW Sq Wave Enable:\t", sts2String(RTC.status(DS3231_SQW_ENABLE)));
  PRINT("\nRS1_2 Sq Wave Freq:\t", sts2String(RTC.status(DS3231_SQW_TYPE)));
  PRINT("\nCONV  Temp Convert:\t", sts2String(RTC.status(DS3231_TCONV)));
  PRINT("\nINTCN Int enable:\t", sts2String(RTC.status(DS3231_INT_ENABLE)));
  PRINT("\n      12h mode:\t\t", sts2String(RTC.status(DS3231_12H)));
  PRINT("\nEN32k 32kHz enabled:\t", sts2String(RTC.status(DS3231_32KHZ_ENABLE)));
  PRINT("\nAGING Aging Offset:\t", sts2String(RTC.status(DS3231_AGING_OFFSET), true));
 
  PRINTS("\n\n>- Status -<");
  PRINT("\nBSY  Busy Flag:\t\t", sts2String(RTC.status(DS3231_BUSY_FLAG)));
  PRINT("\nOSF  Halted Flag:\t", sts2String(RTC.status(DS3231_HALTED_FLAG)));
  #if ENABLE_TEMP_COMP
  PRINT("\nTEMP Temp register:\t", RTC.readTempRegister());
  #endif
 
  PRINTS("\n\n>- Alarm 1 at ");
  showAlarm1();
  PRINT("\nA1IE   Intrpt:\t", sts2String(RTC.status(DS3231_A1_INT_ENABLE)));
  PRINT("\nA1F    Flag:\t", sts2String(RTC.status(DS3231_A1_FLAG)));
  PRINT("\nA1M1_4 Type:\t", alm2String(RTC.getAlarm1Type()));
 
  PRINTS("\n\n>- Alarm 2 at ");
  showAlarm2();
  PRINT("\nA2IE   Intrpt:\t", sts2String(RTC.status(DS3231_A2_INT_ENABLE)));
  PRINT("\nA2F    Flag:\t", sts2String(RTC.status(DS3231_A2_FLAG)));
  PRINT("\nA2M2_4 Type:\t", alm2String(RTC.getAlarm2Type()));
}
 
void printTime()
{
  PRINT("", RTC.yyyy);
  PRINT("-", p2dig(RTC.mm, DEC));
  PRINT("-", p2dig(RTC.dd, DEC));
  PRINT(" ", p2dig(RTC.h, DEC));
  PRINT(":", p2dig(RTC.m, DEC));
  PRINT(":", p2dig(RTC.s, DEC));
  if (RTC.status(DS3231_12H) == DS3231_ON)
    PRINT("", RTC.pm ? " pm" : " am");
  PRINT("", dow2String(RTC.dow));
}
 
void showTime()
{
  RTC.readTime();
  PRINTS("\nTime - ");
  printTime(); 
}
 
void showAlarm1()
{
  RTC.readAlarm1();
  printTime();
}
 
void showAlarm2()
{
  RTC.readAlarm2();
  printTime();
}
 
void showRAM()
{
  #define  MAX_READ_BUF  (DS3231_RAM_MAX / 8)  // do 8 lines
 
  uint8_t  k, regCount = 0;
  uint8_t  buf[MAX_READ_BUF];
 
  PRINTS("\n\n--------");
  for (uint8_t i=0; i<DS3231_RAM_MAX; i+=MAX_READ_BUF)
  {
    RTC.readRAM(i, buf, MAX_READ_BUF);
 
    PRINT("\n", p2dig(i, HEX));
    PRINTS(": ");
    for (uint8_t j=0; j<MAX_READ_BUF; j++)
    {
      if (regCount < DS3231_RAM_MAX)
      {
        PRINT("", p2dig(buf[j], HEX));
        PRINTS(" ");
        k = j;  // save this index for the next loop
        regCount++;
      } else
        PRINTS("   ");
    } 
    PRINTS("  ");
    for (uint8_t j=0; j<=k; j++)
    {
      if (isalnum(buf[j]) || ispunct(buf[j]))
      {
        PRINT("", (char) buf[j]);
      } else {
        PRINTS(".");
      }      
      PRINTS(" ");
    } 
  }
  PRINTS("\n--------");
}
 
void inputTime(void)
{
  RTC.yyyy = i2dig(DEC)*100 + i2dig(DEC);
  RTC.mm = i2dig(DEC);
  RTC.dd = i2dig(DEC);
 
  RTC.h = i2dig(DEC);
  RTC.m = i2dig(DEC);
  RTC.s = i2dig(DEC);
 
  RTC.dow = i2dig(DEC);
}  
 
void showDoW(void)
{
  RTC.readTime();
  PRINT("\nCalculated DoW is", dow2String(RTC.calcDoW(RTC.yyyy, RTC.mm, RTC.dd)));
}
 
void cbAlarm1()
// callback function for Alarm 2
{
  showTime();
  PRINTS("\t-> Alarm 1");  
}
 
void cbAlarm2()
// callback function for Alarm 2
{
  showTime();
  PRINTS("\t-> Alarm 2");
}
 
void doAlarm1()
{
  char  c = readNext();
  codeRequest_t item;
  codeStatus_t  value;
  almType_t alm;
 
  switch (toupper(c))
  {
    case 'I': // interrupt enable
      item = DS3231_A1_INT_ENABLE;
      c = readNext();
      switch (toupper(c))
      {
        case '0': value = DS3231_OFF;  break;
        case '1': value = DS3231_ON;  break;
        default: goto error;
      }
 
      PRINT("\nAlarm 1 ", ctl2String(item));
      PRINT(" value ", sts2String(value));
      PRINT(" result ", RTC.control(item, value));
      break;
 
    case 'F': // alarm flag
      item = DS3231_A1_FLAG;
      value = DS3231_OFF;
      PRINT("\nAlarm 1 ", ctl2String(item));
      PRINT(" value ", sts2String(value));
      PRINT(" result ", RTC.control(item, value));
      break;
 
    case 'T': // alarm type
      c = readNext();
      switch (toupper(c))
      {
        case '0': alm = DS3231_ALM_SEC;   break;
        case '1': alm = DS3231_ALM_S;     break;
        case '2': alm = DS3231_ALM_MS;    break;
        case '3': alm = DS3231_ALM_HMS;   break;
        case '4': alm = DS3231_ALM_DTHMS; break;
        case '5': alm = DS3231_ALM_DDHMS; break;
        default: goto error;
      }
      PRINT("\nAlarm 1 set type ", alm2String(alm));
      PRINT(" result ", RTC.setAlarm1Type(alm));
      break;
 
    case 'Z': // zero all values
      RTC.yyyy = RTC.mm = RTC.dd = 0;
      RTC.h = RTC.m = RTC.s = 0;
      RTC.dow = RTC.pm = 0;
      RTC.writeAlarm1(DS3231_ALM_DTHMS);
      showAlarm1();
      break;
 
    case 'W': // write alarm setting
      c = readNext();
      switch (toupper(c))
      {
        case '0': alm = DS3231_ALM_SEC;   break;
        case '1': alm = DS3231_ALM_S;     break;
        case '2': alm = DS3231_ALM_MS;    break;
        case '3': alm = DS3231_ALM_HMS;   break;
        case '4': alm = DS3231_ALM_DTHMS; break;
        case '5': alm = DS3231_ALM_DDHMS; break;
        default: goto error;
      }
      inputTime();
      RTC.writeAlarm1(alm);
      showAlarm1();
      break;
 
    default:
error:
    PRINTS("\nBad control element or parameter");
    return;
  }
 
  return;
}
 
void doAlarm2()
{
  char  c = readNext();
  codeRequest_t item;
  codeStatus_t  value;
  almType_t alm;
 
  switch (toupper(c))
  {
    case 'I': // interrupt enable
      item = DS3231_A2_INT_ENABLE;
      c = readNext();
      switch (toupper(c))
      {
        case '0': value = DS3231_OFF;  break;
        case '1': value = DS3231_ON;  break;
        default: goto error;
      }
      PRINT("\nAlarm 2 ", ctl2String(item));
      PRINT(" value ", sts2String(value));
      PRINT(" result ", RTC.control(item, value));
      break;
 
    case 'F': // alarm flag
      item = DS3231_A2_FLAG;
      value = DS3231_OFF;
      PRINT("\nAlarm 2 ", ctl2String(item));
      PRINT(" value ", sts2String(value));
      PRINT(" result ", RTC.control(item, value));
      break;
 
    case 'T': // alarm type
      c = readNext();
      switch (toupper(c))
      {
        case '0': alm = DS3231_ALM_MIN;   break;
        case '1': alm = DS3231_ALM_M;     break;
        case '2': alm = DS3231_ALM_HM;    break;
        case '3': alm = DS3231_ALM_DTHM;  break;
        case '4': alm = DS3231_ALM_DDHM;  break;
        default: goto error;
      }
      PRINT("\nAlarm 2 set type ", alm2String(alm));
      PRINT(" result ", RTC.setAlarm2Type(alm));
      break;
 
    case 'Z': // zero all values
      RTC.yyyy = RTC.mm = RTC.dd = 0;
      RTC.h = RTC.m = RTC.s = 0;
      RTC.dow = RTC.pm = 0;
      RTC.writeAlarm2(DS3231_ALM_DTHM);
      showAlarm2();
      break;
 
    case 'W': // write alarm setting
      c = readNext();
      switch (toupper(c))
      {
        case '0': alm = DS3231_ALM_MIN;   break;
        case '1': alm = DS3231_ALM_M;     break;
        case '2': alm = DS3231_ALM_HM;    break;
        case '3': alm = DS3231_ALM_DTHM;  break;
        case '4': alm = DS3231_ALM_DDHM;  break;
        default: goto error;
      }
      inputTime();
      RTC.writeAlarm2(alm);
      showAlarm2();
      break;
 
    default:
error:
      PRINTS("\nBad control element or parameter");
      return;
  }
 
  return;
}
 
void writeControl()
{
  char  c = readNext();
  codeRequest_t item;
  codeStatus_t  value;
 
  switch (toupper(c))
  {
    case '0':  // halt
      item = DS3231_CLOCK_HALT;
      c = readNext();
      switch (toupper(c))
      {
        case '0': value = DS3231_OFF;  break;
        case '1': value = DS3231_ON;  break;
        default: goto error;
      }
      break;
 
    case '1':  // enable
      item = DS3231_SQW_ENABLE;
      c = readNext();
      switch (toupper(c))
      {
        case '0': value = DS3231_OFF;  break;
        case '1': value = DS3231_ON;   break;
        default: goto error;
      }
      break;
 
    case '2':  // type on
      item = DS3231_SQW_TYPE;
      c = readNext();
      switch (toupper(c))
      {
        case '1': value = DS3231_SQW_1HZ;   break;
        case '2': value = DS3231_SQW_1KHZ;  break;
        case '3': value = DS3231_SQW_4KHZ;  break;
        case '4': value = DS3231_SQW_8KHZ;  break;
        default: goto error;
      }
      break;
 
    case '3':  // tcxo conversion
      item = DS3231_TCONV;
      value = DS3231_ON;
      break;
 
    case '4':  // 12 h mode
      item = DS3231_12H;
      c = readNext();
      switch (toupper(c))
      {
        case '0': value = DS3231_OFF;  break;
        case '1': value = DS3231_ON;   break;
        default: goto error;
      }
      break;
 
    case '5':  // alm interrupt operation
      item = DS3231_INT_ENABLE;
      c = readNext();
      switch (toupper(c))
      {
        case '0': value = DS3231_OFF;  break;
        case '1': value = DS3231_ON;   break;
        default: goto error;
      }
      break;
 
    case '6':  // reset halted flag
      item = DS3231_HALTED_FLAG;
      value = DS3231_OFF;
      break;
 
    case '7':  // enable 32kHz output
      item = DS3231_32KHZ_ENABLE;
      c = readNext();
      switch (toupper(c))
      {
        case '0': value = DS3231_OFF;  break;
        case '1': value = DS3231_ON;   break;
        default: goto error;
      }
      break;
 
    case '8':  // enable 32kHz output
      item = DS3231_AGING_OFFSET;
      value = (codeStatus_t) i2dig(HEX);
      break;
 
    default:
 error:
      PRINTS("\nBad control element or parameter");
      return;
  }
 
  // do it
  PRINT("\nControlling ", ctl2String(item));
  PRINT(" to ", sts2String(value, (item == DS3231_AGING_OFFSET)));
  PRINT(", result ", RTC.control(item, value));
 
  return;
}
 
char readNext()
// Read the next character from the serial input stream, skip whitespace.
// Busy loop that also checks for an alarm occurence.
{
  char  c;
 
  do
  {
    while (!Serial.available())
    {
      RTC.checkAlarm1();
      RTC.checkAlarm2();
    }      
    c = Serial.read();
  } while (isspace(c));
 
  return(c);
}
 
void loop()
{
   char  c;
 
   PRINTS("\n");
   // we need to get the next character to know what command we want to process 
   c = readNext();
   switch (toupper(c))
   {
     case '?':  usage();  break;
 
     case 'S':  showStatus();    break;
     case 'C':  writeControl();  break;
     case 'D':  showDoW();       break;
     case 'A':  
       c = readNext();
       switch(toupper(c))
       {
         case '1': doAlarm1();    break;
         case '2': doAlarm2();    break;
         default: goto no_good;
       }
       break;         
 
     // Read functions
     case 'R':  // Display updates      
       c = readNext();
       switch (toupper(c))
       {
         case 'R': showRAM();   break;
         default: goto no_good;
       }
       break;
 
     // Write functions
     case 'T':  // Display updates      
       c = readNext();
       switch (toupper(c))
       {
         case 'R': 
            showTime();  
            break;
 
         case 'W': 
            inputTime();
            RTC.writeTime();
            showTime();
            break;
 
         default: goto no_good;
       }
       break;
 
       default:  // don't know what to do with this! 
no_good:         // label for default escape when we can't process a character 
        {
          PRINT("\nBad parameter '", c);
          PRINTS("'");
          while (Serial.available())    // flush the buffer
            c = readNext();
        }
        break;
   }  
 }
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
arduino/md_ds3231_set_clock.ino.txt · Last modified: 2019/03/01 11:45 by Ilias Iliopoulos