DS1307 adrress register help !

Hi, I don't see "0x7F" or "0x3F" in the timekeeper register . What do they mean? Thx!

0x7F indicate HEX format for 7F, (0111 1111), or decimal 127
0x3F indicate HEX format for 3F, (0011 1111), or decimal 63

Often times it helps to see the numbers that way, especially when the upper 4 bits are indicating something different than the lower 4 bits.
Say perhaps the lower 4 only represented 0-9, and the upper 4 represented 0-5 (000-101) and the 4th bit was some else altogether.

Here is a simple sketch I wrote to set the registers in a DS1307.

To send commands, open the Serial Monitor.
The sketch requests an update every 5 seconds.
Use the following commands:
F0xx [enter] where xx is the high nibble (4 bits) and low nibble per the data sheet.
Seconds starts from power- off as 80, the high bit indicates time is not running.

/*
Test of RTC DS1307 via I2C.
 Counts 
 Seconds, 
 Minutes, 
 Hours, 
 Date of the Month, 
 Month, 
 Day of the week, and 
 Year with Leap-Year
 
 56 bytes battery backed RAM
 Square Wave Output: Off, 1Hz, and 3 higher frequencies
 */

#include <Wire.h>

//variables
byte seconds_address = 0x00;
byte seconds; // bit 7 = Clock Halt, Enabled = 0, Halt = 1
// bits 6-5-3 = tens of seconds 0-6,  bits 3-2-1-0 = units of seconds, 0-9
byte minutes_address = 0x01;
byte minutes;  // bits 6-5-4 = tens of minutes, bits 3-2-1-0 = units of minutes
byte hours_address = 0x02; 
byte hours;  // 7=0. 6 = 1 for 12 hr, 0 for 24 hr.
// bit 5: 12 hr mode = AM(0)/PM(1). 24 hr mode = upper tens of hrs
// bit 4 =  lower tens of hrs, bits 3-2-1-0 = units of hours (0-9)
byte day_week_address = 0x03; 
byte day_week = 0; // range 01-07
byte date_month_address = 0x04;
byte date_month = 0; // range 01-31
byte month_address = 0x05;
byte month = 0; // range 01-12
byte year_address = 0x06;
int year = 0; // upper byte 0-9, lower byte 0-9
byte square_address = 0x07;
byte sqwe = 0;  // square wave enable
// Out-0-0-Sqwe-0-0-RS1-RS0
// Out, Sqwe = 0/0 - Square wave output = 0
// Out, Sqwe = 1/0 - Square wave output = 1
// Out, Sqwe = 0/1 or 1/1 - Square wave output per RS1/RS0
// RS1/RS0 = 00 = 1 Hz
// RS1/RSo = 01 = 4 KHz
// RS1/RS0 = 10 = 8 KHz
// RS1/RS0 = 11 = 32 KHz
byte RTC_ram_address = 0x08; //range = 08-63, 0x08-0x3F

int RTC_address = 0x68; // 1101 000 

byte incomingCommand = 0;
byte RTC_write_command = 0;
byte RTC_read_command = 0;
byte RTC_ram_command = 0;
// use F0xx, F1xx,F2xx, F3xx, F4xx, F5xx, F6xx, F7xx
// to send one register write commands
// use E0xx to read registers back   << not coded yet, reads them all back every time
// use C0xx to read RAM back           << not coded yet
byte incomingRegister = 0;
byte RTC_register = 0;
byte incomingData = 0;
byte new_data = 0;
byte outgoingData = 0;
int delay_time = 100;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
unsigned long duration = 5000;

void setup() {
  Wire.begin(); // no address, we are master
  Serial1.begin (57600);  
  Serial1.flush();
  currentMillis = millis();  
}

void loop() {

  if (Serial1.available() >1){
    incomingCommand = Serial1.read();
    //incomingRegister = Serial.read();
    incomingData = Serial1.read();
    Serial1.print ("command ");
    Serial1.println (incomingCommand & 0xF0, HEX);
    Serial1.print ("register ");
    Serial1.println(incomingCommand & 0x0F, HEX);
    Serial1.print ("data ");
    Serial1.println (incomingData, HEX);
  }
  // *******************************************
  RTC_write_command = incomingCommand & 0xF0;  // mask off high byte
  if (RTC_write_command == 0xF0){  // check for Write command
    RTC_register = incomingCommand & 0x0F;  // mask off low btye
    incomingCommand = 0;
    new_data = incomingData;
    Serial1.print (" Sending a command ");
    switch (RTC_register){
    case 0: // write seconds
        Serial1.println ("Seconds ");
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(seconds_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
      delay (delay_time);
      break;
    case 1: // write minutes
    Serial1.print ("Minutes ");
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(minutes_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
      delay (delay_time);
      break;
    case 2: // write hours
        Serial1.print ("Hours ");
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(hours_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
     delay (delay_time);
      break;
    case 3: // write day
        Serial1.print ("Day ");
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(day_week_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
     delay (delay_time);
      break;
    case 4: // write date of month
        Serial1.print ("Day of Month ");
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(date_month_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
     delay (delay_time);
      break;
    case 5: // write month
        Serial1.print ("Month ");
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(month_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
     delay (delay_time);
      break;
    case 6: // write year
        Serial1.print ("Year ");
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(year_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
     delay (delay_time);
      break;
    case 7: // write square wave
        Serial1.print ("Square Wave ");
    Serial1.println (RTC_register, HEX);
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(square_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
     delay (delay_time);
      break;
    case 8: // write RAM
        Serial1.print ("RAM ");
    Serial1.println (RTC_register, HEX);
      Wire.beginTransmission(RTC_address); // select device
      Wire.send(RTC_ram_address);          // queue the register
      Wire.send(new_data);                  // queue data
      Wire.endTransmission();            // send it
     delay (delay_time);
      break;
      // all others,do nothing
      Serial.println ("Invalid command ");
    }  // end Switch
  } // end if command == F
  // ************************************

  currentMillis = millis();
  if ( (currentMillis - previousMillis) >= duration){
    previousMillis = currentMillis;  
    // Reset the register pointer  
    Wire.beginTransmission(RTC_address);  
    Wire.send(0x00);  
    Wire.endTransmission();   

    Wire.requestFrom(RTC_address,8 );  
    seconds = Wire.receive();  
    minutes = Wire.receive();  
    hours = Wire.receive();  
    day_week = Wire.receive();  
    date_month = Wire.receive();  
    month = Wire.receive();  
    year = Wire.receive();  
    sqwe = Wire.receive();

    // Seconds 
    // bit 7 = Clock Halt, Enabled = 0, Halt = 1
    // bits 6-5-3 = tens of seconds 0-6,  bits 3-2-1-0 = units of seconds, 0-9 

    // Hours
    // 7=0. 6 = 1 for 12 hr, 0 for 24 hr.
    // bit 5: 12 hr mode = AM(0)/PM(1). 24 hr mode = upper tens of hrs
    // bit 4 =  lower tens of hrs, bits 3-2-1-0 = units of hours (0-9)

    Serial1.print ("Hrs " );
    Serial1.print (hours, HEX);
    Serial1.print (" Mins ");
    Serial1.print (minutes, HEX);
    Serial1.print (" Secs ");
    Serial1.print (seconds, HEX);
    Serial1.print (" Day ");
    Serial1.print (day_week, HEX);
    Serial1.print (" Date ");
    Serial1.print (date_month, HEX);
    Serial1.print (" Month ");
    Serial1.print (month, HEX);
    Serial1.print (" Year 20");
    Serial1.print (year, HEX);
    Serial1.print (" Square Wave ");
    Serial1.println (sqwe, HEX);

  }
}
    Wire.beginTransmission(0x68); // activate DS1307
    Wire.send(0); // where to begin
    Wire.send(0x00);          //seconds
    Wire.send(minutes);          //minutes
    Wire.send(0x80 | hours);    //hours (24hr time)
    Wire.send(0x06);  // Day 01-07
    Wire.send(0x01);  // Date 0-31
    Wire.send(0x05);  // month 0-12
    Wire.send(0x09);  // Year 00-99
    Wire.send(0x10); // 
    Wire.endTransmission();
}

Oh, you set every address with the datasheet info, that´s good, now I can understand that part, but why does in this sketch, the address of every bit is not the same? must it be 0x7F and 0x3F or can they be other numbers?

It does not need to be in HEX format, it just makes it easier to see. For example, to set the seconds, you might think just send over a decimal 57 for example. However, those decimal numbers get converted to binary by the compiler when the code is created; decimal 57 is 11 1001 in binary, which is HEX 39 (0x39) (use your windows calculator in Scientific view mode to see this - enter a number in one format, and click the circle of other formats). But if you were to send over 0x39 to the DS1307, your seconds would be set to 39, because the DS1307 uses the upper 4 bits (3) and the lower 4 bits (9) independently. So instead what you have to send over is 0x57 (0101, decimal 5, and 0111, decimal 7). 0x57 is decimal 87. So the hex representation (0x##) is convenient to use in certain cases.

Serial1 was not declare in this escope?

In your sketch you´r doing a bitwise AND: IncomingCommand & 0x0F, why?

Change Serial1 to just Serial, I was testing my board that has 2 serial port, regular USB and added RS232

Here’s my double serial ported board
http://www.crossroadsfencing.com/BobuinoRev17/

RTC_register = incomingCommand & 0x0F; // mask off low btye
incomingCommand = 0;
new_data = incomingData;
Serial1.print (" Sending a command ");
switch (RTC_register){ << bitwise And force the command to be 00, 01, 02…08 for the command selection here.
case 0: // write seconds << I suppose these could easily have been case (0xF0): as well.

It´s prety cool you´r board! bitwise AND makes any value 00, 01, 02......08, it is the address that I can send from the serial monitor !

Thanks!

And yes. Iwasn't sending from the IDE serial monitor, I don't know if that sends out straight hex like that. You may have to tweak the command break apart code some.

Try it and see.

Good night!

what are you using to send the commands?

I made this sketch but it didn’t work, I’m just a beginner! :~

#include <Wire.h>
#include <LiquidCrystal.h>

byte hrs, mins, secs;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}

void setup(){
  Wire.begin();
  lcd.begin(16,2);  
        
}

void setDS1307(){
  Wire.beginTransmission(0x68);
  Wire.send(0);
  Wire.send(decToBcd(hrs)); 
  Wire.send(decToBcd(mins));
  Wire.send(decToBcd(secs));
  Wire.endTransmission();
}

void requestDS1307(byte hours,
byte minutes,
byte seconds){  
  Wire.beginTransmission(0x68);
  Wire.send(0);
  Wire.endTransmission();  
  
  Wire.requestFrom(0x68,3);
  hours=bcdToDec(Wire.receive());
  minutes=bcdToDec(Wire.receive());
  seconds=bcdToDec(Wire.receive());
}
  
void loop(){ 
  
  lcd.setCursor(0,0);
  lcd.print(" ");
  lcd.print(hrs, DEC);
  lcd.print(":");
  lcd.print(" ");
  lcd.print(mins, DEC);
  lcd.print(":");
  lcd.print(" ");
  lcd.print(secs, DEC);
}

I had a serial monitor program called RS232 http://www.evmsoft.com/ Your sketch is more complex than mine.

What didn't work? I would skip the dectobcd stuff, just do everything in hex so you can that the upper nibble and lower nibble have the right data.

What is the purpose of the square wave?

Whatever you'd like. Some folks use the 1Hz as a steady interrupt to do something every second. Your imagination is the limit for the higher speeds - maybe to have interrupts at faster rates for more precise timing control.

I´m trying to do a watering controller, I wanna set time/date via switch and that shows the info in a LCD, I read that the square wave output drain the battery faster, what do if I don´t defined it in the code? Is it possible to use a specific time to activate and deactivate a relay like a time alarm using I2C?

Write 0 to the Square waver register, that will turn it off. On the other hand, the RTV only draws 1.5mA. You can use the 1/Sec pulse to wake up the uc once a second to check the time, if not the time you want, go back into power down sleep mode until the next 2nd. Keep going until you reach the turn on/turn off time.

This is what it shows the serial monitor, is it right? I´m sending data in hex but nothing changes !

Post the code you are running, lets see if we can get some other software help here.
I only ever wrote the one sketch, was my first code ever for getting data back over I2C also.

It´s the same code that you gave me, I wanna see what it does to put in order my ideas

halejandro, Do you have 10K pullup resistors on the SCL/SDA lines? And they are connected to the SCL/SDA lines on the microprocessor? It should be connected like this (but without C12, that was for experimenting)

Yes sir, it's connected like that, Arduino pin 4, 5 !

Pullup resisters too? They are needed.