1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

DS1302 shows alternating null data?

Discussion in 'Arduino' started by halleffector, Jun 21, 2016.

  1. halleffector

    halleffector Member

    Joined:
    Jan 30, 2016
    Messages:
    98
    Likes:
    0
    I know the DS1302 is not the best RTC, but mine shows the following serial output:

    Code (text):

    DS1302 RTC test.
    00:00:00
    16:07:01
    00:00:00
    16:07:03
    00:00:00
    16:07:05
    00:00:00
    16:07:07
    00:00:00
    16:07:09
     
    As can be seen from the output, it appears to keep accurate time, just that every other read returns garbage!

    I tried to change the latency to nothing, but then all reads are garbage. I also tried changing the latency to 2 seconds, but this also results in all reads becoming garbage.

    Is this normal behavior from the DS1302? Is it simply that bad?

    I'm using the following code, which I simply found online, it was originally intended to drive an LCD, but I've simply modified it to serial output:

    Code (text):


    // DS1302:  RST pin  -> Arduino Digital 4
    //  DATA pin  -> Arduino Digital 3
    //  CLK pin  -> Arduino Digital 2

    #include <DS1302.h>
    #include <Wire.h>

    DS1302 rtc(4, 3, 2);

    void setup()
    {
      Serial.begin(9600);
      Serial.println("DS1302 RTC test.");
     
      // Set the clock to run-mode, and disable the write protection
      rtc.halt(false);
      rtc.writeProtect(false);

      // The following lines can be commented out to use the values already stored in the DS1302
      rtc.setDOW(WEDNESDAY);  // Set Day-of-Week to FRIDAY
      rtc.setTime(16, 7, 0);  // Set the time to 12:00:00 (24hr format)
      rtc.setDate(27, 1, 2016);  // Set the date to August 6th, 2010

      rtc.writeProtect(true);
    }

    void loop()
    {
      Serial.println(rtc.getTimeStr());
     
    //  Serial.println(rtc.getDOWStr(FORMAT_SHORT));
     
    //  Serial.println(rtc.getDateStr());

      delay (1000);
    }
     
     
  2. fezder

    fezder Well-Known Member

    Joined:
    Dec 11, 2011
    Messages:
    1,665
    Likes:
    100
    Location:
    Mikkeli, Finland
    Will it show garbage in LCD monitor too?
    I think I have ds1302 RTC module somewhere, I'll see if I can replicate this issue. I've used only ds1307, I2C version.
     
  3. fezder

    fezder Well-Known Member

    Joined:
    Dec 11, 2011
    Messages:
    1,665
    Likes:
    100
    Location:
    Mikkeli, Finland
    There any couple of ds1302 libraries, which did you use?
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. halleffector

    halleffector Member

    Joined:
    Jan 30, 2016
    Messages:
    98
    Likes:
    0

    Sorry for the slow reply.

    I used the following library: https://github.com/iot-playground/Arduino/tree/master/external_libraries/DS1302RTC
     
  6. fezder

    fezder Well-Known Member

    Joined:
    Dec 11, 2011
    Messages:
    1,665
    Likes:
    100
    Location:
    Mikkeli, Finland
    No worries! uysing excact same library helps a lot when troubleshooting, as well same version of IDE, can help. I'll test what I can get, hopefully same result!
     
  7. djsfantasi

    djsfantasi Member

    Joined:
    Mar 15, 2011
    Messages:
    161
    Likes:
    21
    Location:
    Metro Boston
    I didn't use the DS1302; I used the DS1307.

    After defining the rtc structure, the DS1307 required that the rtc object be initialized. I don't see any initialization in your code. Perhaps the DS1302 does not need to be initialized? (I suspect that it does).

    The following lines are excerpts from my code.
    RTC_DS1307 rtc; // define object
    rtc.begin(); // initialize the RTC​
    I do not see an equivalent statement to the second line in your code.
     
  8. fezder

    fezder Well-Known Member

    Joined:
    Dec 11, 2011
    Messages:
    1,665
    Likes:
    100
    Location:
    Mikkeli, Finland
    Hmm, you sure that is library you used? The sketch you provided, calls for :
    Code (c):

    #include <DS1302.h>
    #include <Wire.h>
     
    But, there are no such .h file in the library link you provided (h-file is called DS1302RTC in what youprovided) . Also, when I tested using example setSerial sketch from that library, says that RTC is not running.
    There is slight difference in header files, but I try something...
     
  9. fezder

    fezder Well-Known Member

    Joined:
    Dec 11, 2011
    Messages:
    1,665
    Likes:
    100
    Location:
    Mikkeli, Finland
    This worked well (even it doesn't use libraries!) This sketch sets the time, fill in values in code
    Code (c):

    // Set your own pins with these defines !
    #define DS1302_SCLK_PIN  4  // Arduino pin for the Serial Clock
    #define DS1302_IO_PIN  3  // Arduino pin for the Data I/O
    #define DS1302_CE_PIN  2u  // Arduino pin for the Chip Enable


    // Macros to convert the bcd values of the registers to normal
    // integer variables.
    // The code uses separate variables for the high byte and the low byte
    // of the bcd, so these macros handle both bytes separately.
    #define bcd2bin(h,l)  (((h)*10) + (l))
    #define bin2bcd_h(x)  ((x)/10)
    #define bin2bcd_l(x)  ((x)%10)


    // Register names.
    // Since the highest bit is always '1',
    // the registers start at 0x80
    // If the register is read, the lowest bit should be '1'.
    #define DS1302_SECONDS  0x80
    #define DS1302_MINUTES  0x82
    #define DS1302_HOURS  0x84
    #define DS1302_DATE  0x86
    #define DS1302_MONTH  0x88
    #define DS1302_DAY  0x8A
    #define DS1302_YEAR  0x8C
    #define DS1302_ENABLE  0x8E
    #define DS1302_TRICKLE  0x90
    #define DS1302_CLOCK_BURST  0xBE
    #define DS1302_CLOCK_BURST_WRITE 0xBE
    #define DS1302_CLOCK_BURST_READ  0xBF
    #define DS1302_RAMSTART  0xC0
    #define DS1302_RAMEND  0xFC
    #define DS1302_RAM_BURST  0xFE
    #define DS1302_RAM_BURST_WRITE  0xFE
    #define DS1302_RAM_BURST_READ  0xFF



    // Defines for the bits, to be able to change
    // between bit number and binary definition.
    // By using the bit number, using the DS1302
    // is like programming an AVR microcontroller.
    // But instead of using "(1<<X)", or "_BV(X)",
    // the Arduino "bit(X)" is used.
    #define DS1302_D0 0
    #define DS1302_D1 1
    #define DS1302_D2 2
    #define DS1302_D3 3
    #define DS1302_D4 4
    #define DS1302_D5 5
    #define DS1302_D6 6
    #define DS1302_D7 7


    // Bit for reading (bit in address)
    #define DS1302_READBIT DS1302_D0 // READBIT=1: read instruction

    // Bit for clock (0) or ram (1) area,
    // called R/C-bit (bit in address)
    #define DS1302_RC DS1302_D6

    // Seconds Register
    #define DS1302_CH DS1302_D7  // 1 = Clock Halt, 0 = start

    // Hour Register
    #define DS1302_AM_PM DS1302_D5 // 0 = AM, 1 = PM
    #define DS1302_12_24 DS1302_D7 // 0 = 24 hour, 1 = 12 hour

    // Enable Register
    #define DS1302_WP DS1302_D7  // 1 = Write Protect, 0 = enabled

    // Trickle Register
    #define DS1302_ROUT0 DS1302_D0
    #define DS1302_ROUT1 DS1302_D1
    #define DS1302_DS0  DS1302_D2
    #define DS1302_DS1  DS1302_D2
    #define DS1302_TCS0  DS1302_D4
    #define DS1302_TCS1  DS1302_D5
    #define DS1302_TCS2  DS1302_D6
    #define DS1302_TCS3  DS1302_D7


    // Structure for the first 8 registers.
    // These 8 bytes can be read at once with
    // the 'clock burst' command.
    // Note that this structure contains an anonymous union.
    // It might cause a problem on other compilers.
    typedef struct ds1302_struct
    {
      uint8_t Seconds:4;  // low decimal digit 0-9
      uint8_t Seconds10:3;  // high decimal digit 0-5
      uint8_t CH:1;  // CH = Clock Halt
      uint8_t Minutes:4;
      uint8_t Minutes10:3;
      uint8_t reserved1:1;
      union
      {
      struct
      {
      uint8_t Hour:4;
      uint8_t Hour10:2;
      uint8_t reserved2:1;
      uint8_t hour_12_24:1; // 0 for 24 hour format
      } h24;
      struct
      {
      uint8_t Hour:4;
      uint8_t Hour10:1;
      uint8_t AM_PM:1;  // 0 for AM, 1 for PM
      uint8_t reserved2:1;
      uint8_t hour_12_24:1; // 1 for 12 hour format
      } h12;
      };
      uint8_t Date:4;  // Day of month, 1 = first day
      uint8_t Date10:2;
      uint8_t reserved3:2;
      uint8_t Month:4;  // Month, 1 = January
      uint8_t Month10:1;
      uint8_t reserved4:3;
      uint8_t Day:3;  // Day of week, 1 = first day (any day)
      uint8_t reserved5:5;
      uint8_t Year:4;  // Year, 0 = year 2000
      uint8_t Year10:4;
      uint8_t reserved6:7;
      uint8_t WP:1;  // WP = Write Protect
    };


    void setup()
    {  
      ds1302_struct rtc;


      Serial.begin(9600);
      Serial.println(F("DS1302 Real Time Clock"));
      Serial.println(F("Version 2, March 2013"));


      // Start by clearing the Write Protect bit
      // Otherwise the clock data cannot be written
      // The whole register is written,
      // but the WP-bit is the only bit in that register.
      DS1302_write (DS1302_ENABLE, 0);

      // Disable Trickle Charger.
      DS1302_write (DS1302_TRICKLE, 0x00);

    // Remove the next define,
    // after the right date and time are set.
    #define SET_DATE_TIME_JUST_ONCE
    #ifdef SET_DATE_TIME_JUST_ONCE  

      // Fill these variables with the date and time.
      int seconds, minutes, hours, dayofweek, dayofmonth, month, year;

      // Example for april 15, 2013, 10:08, monday is 2nd day of Week.
      // Set your own time and date in these variables.
      seconds  = 0;
      minutes  = 8;
      hours  = 10;
      dayofweek  = 2;  // Day of week, any day can be first, counts 1...7
      dayofmonth = 15; // Day of month, 1...31
      month  = 4;  // month 1...12
      year  = 2013;

      // Set a time and date
      // This also clears the CH (Clock Halt) bit,
      // to start the clock.

      // Fill the structure with zeros to make
      // any unused bits zero
      memset ((char *) &rtc, 0, sizeof(rtc));

      rtc.Seconds  = bin2bcd_l( seconds);
      rtc.Seconds10  = bin2bcd_h( seconds);
      rtc.CH  = 0;  // 1 for Clock Halt, 0 to run;
      rtc.Minutes  = bin2bcd_l( minutes);
      rtc.Minutes10  = bin2bcd_h( minutes);
      // To use the 12 hour format,
      // use it like these four lines:
      //  rtc.h12.Hour  = bin2bcd_l( hours);
      //  rtc.h12.Hour10 = bin2bcd_h( hours);
      //  rtc.h12.AM_PM  = 0;  // AM = 0
      //  rtc.h12.hour_12_24 = 1; // 1 for 24 hour format
      rtc.h24.Hour  = bin2bcd_l( hours);
      rtc.h24.Hour10 = bin2bcd_h( hours);
      rtc.h24.hour_12_24 = 0; // 0 for 24 hour format
      rtc.Date  = bin2bcd_l( dayofmonth);
      rtc.Date10  = bin2bcd_h( dayofmonth);
      rtc.Month  = bin2bcd_l( month);
      rtc.Month10  = bin2bcd_h( month);
      rtc.Day  = dayofweek;
      rtc.Year  = bin2bcd_l( year - 2000);
      rtc.Year10  = bin2bcd_h( year - 2000);
      rtc.WP = 0;  

      // Write all clock data at once (burst mode).
      DS1302_clock_burst_write( (uint8_t *) &rtc);
    #endif
    }


    void loop()
    {
      ds1302_struct rtc;
      char buffer[80];  // the code uses 70 characters.

      // Read all clock data at once (burst mode).
      DS1302_clock_burst_read( (uint8_t *) &rtc);

      sprintf( buffer, "Time = %02d:%02d:%02d, ", \
      bcd2bin( rtc.h24.Hour10, rtc.h24.Hour), \
      bcd2bin( rtc.Minutes10, rtc.Minutes), \
      bcd2bin( rtc.Seconds10, rtc.Seconds));
      Serial.print(buffer);

      sprintf(buffer, "Date(day of month) = %d, Month = %d, " \
      "Day(day of week) = %d, Year = %d", \
      bcd2bin( rtc.Date10, rtc.Date), \
      bcd2bin( rtc.Month10, rtc.Month), \
      rtc.Day, \
      2000 + bcd2bin( rtc.Year10, rtc.Year));
      Serial.println( buffer);

      delay( 5000);
    }


    // --------------------------------------------------------
    // DS1302_clock_burst_read
    //
    // This function reads 8 bytes clock data in burst mode
    // from the DS1302.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    void DS1302_clock_burst_read( uint8_t *p)
    {
      int i;

      _DS1302_start();

      // Instead of the address,
      // the CLOCK_BURST_READ command is issued
      // the I/O-line is released for the data
      _DS1302_togglewrite( DS1302_CLOCK_BURST_READ, true);  

      for( i=0; i<8; i++)
      {
      *p++ = _DS1302_toggleread();
      }
      _DS1302_stop();
    }


    // --------------------------------------------------------
    // DS1302_clock_burst_write
    //
    // This function writes 8 bytes clock data in burst mode
    // to the DS1302.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    void DS1302_clock_burst_write( uint8_t *p)
    {
      int i;

      _DS1302_start();

      // Instead of the address,
      // the CLOCK_BURST_WRITE command is issued.
      // the I/O-line is not released
      _DS1302_togglewrite( DS1302_CLOCK_BURST_WRITE, false);  

      for( i=0; i<8; i++)
      {
      // the I/O-line is not released
      _DS1302_togglewrite( *p++, false);  
      }
      _DS1302_stop();
    }


    // --------------------------------------------------------
    // DS1302_read
    //
    // This function reads a byte from the DS1302
    // (clock or ram).
    //
    // The address could be like "0x80" or "0x81",
    // the lowest bit is set anyway.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    uint8_t DS1302_read(int address)
    {
      uint8_t data;

      // set lowest bit (read bit) in address
      bitSet( address, DS1302_READBIT);  

      _DS1302_start();
      // the I/O-line is released for the data
      _DS1302_togglewrite( address, true);  
      data = _DS1302_toggleread();
      _DS1302_stop();

      return (data);
    }


    // --------------------------------------------------------
    // DS1302_write
    //
    // This function writes a byte to the DS1302 (clock or ram).
    //
    // The address could be like "0x80" or "0x81",
    // the lowest bit is cleared anyway.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    void DS1302_write( int address, uint8_t data)
    {
      // clear lowest bit (read bit) in address
      bitClear( address, DS1302_READBIT);  

      _DS1302_start();
      // don't release the I/O-line
      _DS1302_togglewrite( address, false);
      // don't release the I/O-line
      _DS1302_togglewrite( data, false);
      _DS1302_stop();  
    }


    // --------------------------------------------------------
    // _DS1302_start
    //
    // A helper function to setup the start condition.
    //
    // An 'init' function is not used.
    // But now the pinMode is set every time.
    // That's not a big deal, and it's valid.
    // At startup, the pins of the Arduino are high impedance.
    // Since the DS1302 has pull-down resistors,
    // the signals are low (inactive) until the DS1302 is used.
    void _DS1302_start( void)
    {
      digitalWrite( DS1302_CE_PIN, LOW); // default, not enabled
      pinMode( DS1302_CE_PIN, OUTPUT);  

      digitalWrite( DS1302_SCLK_PIN, LOW); // default, clock low
      pinMode( DS1302_SCLK_PIN, OUTPUT);

      pinMode( DS1302_IO_PIN, OUTPUT);

      digitalWrite( DS1302_CE_PIN, HIGH); // start the session
      delayMicroseconds( 4);  // tCC = 4us
    }


    // --------------------------------------------------------
    // _DS1302_stop
    //
    // A helper function to finish the communication.
    //
    void _DS1302_stop(void)
    {
      // Set CE low
      digitalWrite( DS1302_CE_PIN, LOW);

      delayMicroseconds( 4);  // tCWH = 4us
    }


    // --------------------------------------------------------
    // _DS1302_toggleread
    //
    // A helper function for reading a byte with bit toggle
    //
    // This function assumes that the SCLK is still high.
    //
    uint8_t _DS1302_toggleread( void)
    {
      uint8_t i, data;

      data = 0;
      for( i = 0; i <= 7; i++)
      {
      // Issue a clock pulse for the next databit.
      // If the 'togglewrite' function was used before
      // this function, the SCLK is already high.
      digitalWrite( DS1302_SCLK_PIN, HIGH);
      delayMicroseconds( 1);

      // Clock down, data is ready after some time.
      digitalWrite( DS1302_SCLK_PIN, LOW);
      delayMicroseconds( 1);  // tCL=1000ns, tCDD=800ns

      // read bit, and set it in place in 'data' variable
      bitWrite( data, i, digitalRead( DS1302_IO_PIN));
      }
      return( data);
    }


    // --------------------------------------------------------
    // _DS1302_togglewrite
    //
    // A helper function for writing a byte with bit toggle
    //
    // The 'release' parameter is for a read after this write.
    // It will release the I/O-line and will keep the SCLK high.
    //
    void _DS1302_togglewrite( uint8_t data, uint8_t release)
    {
      int i;

      for( i = 0; i <= 7; i++)
      {
      // set a bit of the data on the I/O-line
      digitalWrite( DS1302_IO_PIN, bitRead(data, i));  
      delayMicroseconds( 1);  // tDC = 200ns

      // clock up, data is read by DS1302
      digitalWrite( DS1302_SCLK_PIN, HIGH);  
      delayMicroseconds( 1);  // tCH = 1000ns, tCDH = 800ns

      if( release && i == 7)
      {
      // If this write is followed by a read,
      // the I/O-line should be released after
      // the last bit, before the clock line is made low.
      // This is according the datasheet.
      // I have seen other programs that don't release
      // the I/O-line at this moment,
      // and that could cause a shortcut spike
      // on the I/O-line.
      pinMode( DS1302_IO_PIN, INPUT);

      // For Arduino 1.0.3, removing the pull-up is no longer needed.
      // Setting the pin as 'INPUT' will already remove the pull-up.
      // digitalWrite (DS1302_IO, LOW); // remove any pull-up  
      }
      else
      {
      digitalWrite( DS1302_SCLK_PIN, LOW);
      delayMicroseconds( 1);  // tCL=1000ns, tCDD=800ns
      }
      }
    }
     
    After then, this code can be used to actually SEE the time. Cycle power to make sure RTC keeps time with battery backup.
    Code (c):

    // Set your own pins with these defines !
    #define DS1302_SCLK_PIN  4  // Arduino pin for the Serial Clock
    #define DS1302_IO_PIN  3  // Arduino pin for the Data I/O
    #define DS1302_CE_PIN  2u  // Arduino pin for the Chip Enable


    // Macros to convert the bcd values of the registers to normal
    // integer variables.
    // The code uses separate variables for the high byte and the low byte
    // of the bcd, so these macros handle both bytes separately.
    #define bcd2bin(h,l)  (((h)*10) + (l))
    #define bin2bcd_h(x)  ((x)/10)
    #define bin2bcd_l(x)  ((x)%10)


    // Register names.
    // Since the highest bit is always '1',
    // the registers start at 0x80
    // If the register is read, the lowest bit should be '1'.
    #define DS1302_SECONDS  0x80
    #define DS1302_MINUTES  0x82
    #define DS1302_HOURS  0x84
    #define DS1302_DATE  0x86
    #define DS1302_MONTH  0x88
    #define DS1302_DAY  0x8A
    #define DS1302_YEAR  0x8C
    #define DS1302_ENABLE  0x8E
    #define DS1302_TRICKLE  0x90
    #define DS1302_CLOCK_BURST  0xBE
    #define DS1302_CLOCK_BURST_WRITE 0xBE
    #define DS1302_CLOCK_BURST_READ  0xBF
    #define DS1302_RAMSTART  0xC0
    #define DS1302_RAMEND  0xFC
    #define DS1302_RAM_BURST  0xFE
    #define DS1302_RAM_BURST_WRITE  0xFE
    #define DS1302_RAM_BURST_READ  0xFF



    // Defines for the bits, to be able to change
    // between bit number and binary definition.
    // By using the bit number, using the DS1302
    // is like programming an AVR microcontroller.
    // But instead of using "(1<<X)", or "_BV(X)",
    // the Arduino "bit(X)" is used.
    #define DS1302_D0 0
    #define DS1302_D1 1
    #define DS1302_D2 2
    #define DS1302_D3 3
    #define DS1302_D4 4
    #define DS1302_D5 5
    #define DS1302_D6 6
    #define DS1302_D7 7


    // Bit for reading (bit in address)
    #define DS1302_READBIT DS1302_D0 // READBIT=1: read instruction

    // Bit for clock (0) or ram (1) area,
    // called R/C-bit (bit in address)
    #define DS1302_RC DS1302_D6

    // Seconds Register
    #define DS1302_CH DS1302_D7  // 1 = Clock Halt, 0 = start

    // Hour Register
    #define DS1302_AM_PM DS1302_D5 // 0 = AM, 1 = PM
    #define DS1302_12_24 DS1302_D7 // 0 = 24 hour, 1 = 12 hour

    // Enable Register
    #define DS1302_WP DS1302_D7  // 1 = Write Protect, 0 = enabled

    // Trickle Register
    #define DS1302_ROUT0 DS1302_D0
    #define DS1302_ROUT1 DS1302_D1
    #define DS1302_DS0  DS1302_D2
    #define DS1302_DS1  DS1302_D2
    #define DS1302_TCS0  DS1302_D4
    #define DS1302_TCS1  DS1302_D5
    #define DS1302_TCS2  DS1302_D6
    #define DS1302_TCS3  DS1302_D7


    // Structure for the first 8 registers.
    // These 8 bytes can be read at once with
    // the 'clock burst' command.
    // Note that this structure contains an anonymous union.
    // It might cause a problem on other compilers.
    typedef struct ds1302_struct
    {
      uint8_t Seconds:4;  // low decimal digit 0-9
      uint8_t Seconds10:3;  // high decimal digit 0-5
      uint8_t CH:1;  // CH = Clock Halt
      uint8_t Minutes:4;
      uint8_t Minutes10:3;
      uint8_t reserved1:1;
      union
      {
      struct
      {
      uint8_t Hour:4;
      uint8_t Hour10:2;
      uint8_t reserved2:1;
      uint8_t hour_12_24:1; // 0 for 24 hour format
      } h24;
      struct
      {
      uint8_t Hour:4;
      uint8_t Hour10:1;
      uint8_t AM_PM:1;  // 0 for AM, 1 for PM
      uint8_t reserved2:1;
      uint8_t hour_12_24:1; // 1 for 12 hour format
      } h12;
      };
      uint8_t Date:4;  // Day of month, 1 = first day
      uint8_t Date10:2;
      uint8_t reserved3:2;
      uint8_t Month:4;  // Month, 1 = January
      uint8_t Month10:1;
      uint8_t reserved4:3;
      uint8_t Day:3;  // Day of week, 1 = first day (any day)
      uint8_t reserved5:5;
      uint8_t Year:4;  // Year, 0 = year 2000
      uint8_t Year10:4;
      uint8_t reserved6:7;
      uint8_t WP:1;  // WP = Write Protect
    };


    void setup()
    {  
      ds1302_struct rtc;


      Serial.begin(9600);
      Serial.println(F("DS1302 Real Time Clock"));
      Serial.println(F("Version 2, March 2013"));


      // Start by clearing the Write Protect bit
      // Otherwise the clock data cannot be written
      // The whole register is written,
      // but the WP-bit is the only bit in that register.
      DS1302_write (DS1302_ENABLE, 0);

      // Disable Trickle Charger.
      DS1302_write (DS1302_TRICKLE, 0x00);

    // Remove the next define,
    // after the right date and time are set.
    #define SET_DATE_TIME_JUST_ONCE
    #ifdef SET_DATE_TIME_JUST_ONCE  

      // Fill these variables with the date and time.
      int seconds, minutes, hours, dayofweek, dayofmonth, month, year;

      // Example for april 15, 2013, 10:08, monday is 2nd day of Week.
      // Set your own time and date in these variables.
      seconds  = 0;
      minutes  = 8;
      hours  = 10;
      dayofweek  = 2;  // Day of week, any day can be first, counts 1...7
      dayofmonth = 15; // Day of month, 1...31
      month  = 4;  // month 1...12
      year  = 2013;

      // Set a time and date
      // This also clears the CH (Clock Halt) bit,
      // to start the clock.

      // Fill the structure with zeros to make
      // any unused bits zero
      memset ((char *) &rtc, 0, sizeof(rtc));

      rtc.Seconds  = bin2bcd_l( seconds);
      rtc.Seconds10  = bin2bcd_h( seconds);
      rtc.CH  = 0;  // 1 for Clock Halt, 0 to run;
      rtc.Minutes  = bin2bcd_l( minutes);
      rtc.Minutes10  = bin2bcd_h( minutes);
      // To use the 12 hour format,
      // use it like these four lines:
      //  rtc.h12.Hour  = bin2bcd_l( hours);
      //  rtc.h12.Hour10 = bin2bcd_h( hours);
      //  rtc.h12.AM_PM  = 0;  // AM = 0
      //  rtc.h12.hour_12_24 = 1; // 1 for 24 hour format
      rtc.h24.Hour  = bin2bcd_l( hours);
      rtc.h24.Hour10 = bin2bcd_h( hours);
      rtc.h24.hour_12_24 = 0; // 0 for 24 hour format
      rtc.Date  = bin2bcd_l( dayofmonth);
      rtc.Date10  = bin2bcd_h( dayofmonth);
      rtc.Month  = bin2bcd_l( month);
      rtc.Month10  = bin2bcd_h( month);
      rtc.Day  = dayofweek;
      rtc.Year  = bin2bcd_l( year - 2000);
      rtc.Year10  = bin2bcd_h( year - 2000);
      rtc.WP = 0;  

      // Write all clock data at once (burst mode).
      DS1302_clock_burst_write( (uint8_t *) &rtc);
    #endif
    }


    void loop()
    {
      ds1302_struct rtc;
      char buffer[80];  // the code uses 70 characters.

      // Read all clock data at once (burst mode).
      DS1302_clock_burst_read( (uint8_t *) &rtc);

      sprintf( buffer, "Time = %02d:%02d:%02d, ", \
      bcd2bin( rtc.h24.Hour10, rtc.h24.Hour), \
      bcd2bin( rtc.Minutes10, rtc.Minutes), \
      bcd2bin( rtc.Seconds10, rtc.Seconds));
      Serial.print(buffer);

      sprintf(buffer, "Date(day of month) = %d, Month = %d, " \
      "Day(day of week) = %d, Year = %d", \
      bcd2bin( rtc.Date10, rtc.Date), \
      bcd2bin( rtc.Month10, rtc.Month), \
      rtc.Day, \
      2000 + bcd2bin( rtc.Year10, rtc.Year));
      Serial.println( buffer);

      delay( 5000);
    }


    // --------------------------------------------------------
    // DS1302_clock_burst_read
    //
    // This function reads 8 bytes clock data in burst mode
    // from the DS1302.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    void DS1302_clock_burst_read( uint8_t *p)
    {
      int i;

      _DS1302_start();

      // Instead of the address,
      // the CLOCK_BURST_READ command is issued
      // the I/O-line is released for the data
      _DS1302_togglewrite( DS1302_CLOCK_BURST_READ, true);  

      for( i=0; i<8; i++)
      {
      *p++ = _DS1302_toggleread();
      }
      _DS1302_stop();
    }


    // --------------------------------------------------------
    // DS1302_clock_burst_write
    //
    // This function writes 8 bytes clock data in burst mode
    // to the DS1302.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    void DS1302_clock_burst_write( uint8_t *p)
    {
      int i;

      _DS1302_start();

      // Instead of the address,
      // the CLOCK_BURST_WRITE command is issued.
      // the I/O-line is not released
      _DS1302_togglewrite( DS1302_CLOCK_BURST_WRITE, false);  

      for( i=0; i<8; i++)
      {
      // the I/O-line is not released
      _DS1302_togglewrite( *p++, false);  
      }
      _DS1302_stop();
    }


    // --------------------------------------------------------
    // DS1302_read
    //
    // This function reads a byte from the DS1302
    // (clock or ram).
    //
    // The address could be like "0x80" or "0x81",
    // the lowest bit is set anyway.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    uint8_t DS1302_read(int address)
    {
      uint8_t data;

      // set lowest bit (read bit) in address
      bitSet( address, DS1302_READBIT);  

      _DS1302_start();
      // the I/O-line is released for the data
      _DS1302_togglewrite( address, true);  
      data = _DS1302_toggleread();
      _DS1302_stop();

      return (data);
    }


    // --------------------------------------------------------
    // DS1302_write
    //
    // This function writes a byte to the DS1302 (clock or ram).
    //
    // The address could be like "0x80" or "0x81",
    // the lowest bit is cleared anyway.
    //
    // This function may be called as the first function,
    // also the pinMode is set.
    //
    void DS1302_write( int address, uint8_t data)
    {
      // clear lowest bit (read bit) in address
      bitClear( address, DS1302_READBIT);  

      _DS1302_start();
      // don't release the I/O-line
      _DS1302_togglewrite( address, false);
      // don't release the I/O-line
      _DS1302_togglewrite( data, false);
      _DS1302_stop();  
    }


    // --------------------------------------------------------
    // _DS1302_start
    //
    // A helper function to setup the start condition.
    //
    // An 'init' function is not used.
    // But now the pinMode is set every time.
    // That's not a big deal, and it's valid.
    // At startup, the pins of the Arduino are high impedance.
    // Since the DS1302 has pull-down resistors,
    // the signals are low (inactive) until the DS1302 is used.
    void _DS1302_start( void)
    {
      digitalWrite( DS1302_CE_PIN, LOW); // default, not enabled
      pinMode( DS1302_CE_PIN, OUTPUT);  

      digitalWrite( DS1302_SCLK_PIN, LOW); // default, clock low
      pinMode( DS1302_SCLK_PIN, OUTPUT);

      pinMode( DS1302_IO_PIN, OUTPUT);

      digitalWrite( DS1302_CE_PIN, HIGH); // start the session
      delayMicroseconds( 4);  // tCC = 4us
    }


    // --------------------------------------------------------
    // _DS1302_stop
    //
    // A helper function to finish the communication.
    //
    void _DS1302_stop(void)
    {
      // Set CE low
      digitalWrite( DS1302_CE_PIN, LOW);

      delayMicroseconds( 4);  // tCWH = 4us
    }


    // --------------------------------------------------------
    // _DS1302_toggleread
    //
    // A helper function for reading a byte with bit toggle
    //
    // This function assumes that the SCLK is still high.
    //
    uint8_t _DS1302_toggleread( void)
    {
      uint8_t i, data;

      data = 0;
      for( i = 0; i <= 7; i++)
      {
      // Issue a clock pulse for the next databit.
      // If the 'togglewrite' function was used before
      // this function, the SCLK is already high.
      digitalWrite( DS1302_SCLK_PIN, HIGH);
      delayMicroseconds( 1);

      // Clock down, data is ready after some time.
      digitalWrite( DS1302_SCLK_PIN, LOW);
      delayMicroseconds( 1);  // tCL=1000ns, tCDD=800ns

      // read bit, and set it in place in 'data' variable
      bitWrite( data, i, digitalRead( DS1302_IO_PIN));
      }
      return( data);
    }


    // --------------------------------------------------------
    // _DS1302_togglewrite
    //
    // A helper function for writing a byte with bit toggle
    //
    // The 'release' parameter is for a read after this write.
    // It will release the I/O-line and will keep the SCLK high.
    //
    void _DS1302_togglewrite( uint8_t data, uint8_t release)
    {
      int i;

      for( i = 0; i <= 7; i++)
      {
      // set a bit of the data on the I/O-line
      digitalWrite( DS1302_IO_PIN, bitRead(data, i));  
      delayMicroseconds( 1);  // tDC = 200ns

      // clock up, data is read by DS1302
      digitalWrite( DS1302_SCLK_PIN, HIGH);  
      delayMicroseconds( 1);  // tCH = 1000ns, tCDH = 800ns

      if( release && i == 7)
      {
      // If this write is followed by a read,
      // the I/O-line should be released after
      // the last bit, before the clock line is made low.
      // This is according the datasheet.
      // I have seen other programs that don't release
      // the I/O-line at this moment,
      // and that could cause a shortcut spike
      // on the I/O-line.
      pinMode( DS1302_IO_PIN, INPUT);

      // For Arduino 1.0.3, removing the pull-up is no longer needed.
      // Setting the pin as 'INPUT' will already remove the pull-up.
      // digitalWrite (DS1302_IO, LOW); // remove any pull-up  
      }
      else
      {
      digitalWrite( DS1302_SCLK_PIN, LOW);
      delayMicroseconds( 1);  // tCL=1000ns, tCDD=800ns
      }
      }
    }
     
    Could you test these?
     
  10. halleffector

    halleffector Member

    Joined:
    Jan 30, 2016
    Messages:
    98
    Likes:
    0
    Just tried it, sorry for the delay.

    It works great, thanks a lot.

    I don't understand how this circuit works though. I connected the CE pin to my RST pin on the RTC module (it has no CE pin, it only has VCC, GND, CLK, DAT, RST).

    Why is CE defined as "2u" and not just "2"?
     
  11. fezder

    fezder Well-Known Member

    Joined:
    Dec 11, 2011
    Messages:
    1,665
    Likes:
    100
    Location:
    Mikkeli, Finland
    Yeah, sometimes in this IC reset is called CE (chip enable). 2u could be just typo? Didn't notice that earlier.
    Reason for these two tests was to rule out that DS1302 indeed works, so issue is not hardware, Its most likely software fault now...those skethces are just monster to use since they don't rely on libraries.
    And since there was difference in h.file (and .cpp for that matter too) it could be possible that library got installed wrong somehow. You did install ds1302 library, that has DS1302.h and DS1302.cpop files, to sketch->libraries?
    I'm on win7 so path would be:
    C:\Users\username\Documents\Arduino\libraries
    Also, if library has master.something, delete that master portion so library folder name is same as .h file, that is DS1302.
    This is just to rule out that there is no small error happened with libraries.
     

Share This Page