// Copyright May 2017 Enoch Hwang
// This is the master controller for the DS1307 Real-Time Clock (RTC) chip
// using the I2S protocol. The RTC chip is the slave
// This is a raw bit bang low-level code
//
// Connections:
// DS1307 Arduino Description
// pin 1 and 2 32.768kHz crystal
// pin 3 (optional) connect to battery +3v. connect to GND if no battery
// pin 4 connect to GND
// pin 5 SDA analog pin A4 SDA (4.7K ohm pull-up resistor between SDA and VCC)
// pin 6 SCL analog pin A5 SCL (4.7K ohm pull-up resistor between SCL and VCC)
// must use one of the analog pins. the digital pins won't work
// pin 7 (optional) 1K ohm pull-up resistor to VCC and connect to LED+. LED- to GND thru 150 ohm resistor
// pin 8 5V
//
// for debugging:
// SDA connected to VCC will display 255:255:255
// SDA connected to GND or no connection will display 0:0:0
// sometimes need to wiggle the SDA wire to get it to work
#define SDA A4
#define SCL A5
const byte DS1307_ADDR_R = 0xD1; // the DS1307 7-bit address 1101000 with READ bit (1) = 11010001 = D1
const byte DS1307_ADDR_W = 0xD0; // the DS1307 7-bit address 1101000 with WRITE bit (0) = 11010000 = D0
void sendStart(byte addr) {
pinMode(SDA, OUTPUT);
digitalWrite(SDA, HIGH);
digitalWrite(SCL, HIGH);
digitalWrite(SDA, LOW);
// send out the 8 bits
for (int i=7; i>=0; i--) {
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,i));
digitalWrite(SCL, HIGH);
}
digitalWrite(SCL, LOW); // must have this last LOW
}
/*
void sendStart(byte addr) {
pinMode(SDA, OUTPUT);
digitalWrite(SDA, HIGH);
digitalWrite(SCL, HIGH);
digitalWrite(SDA, LOW);
// send out the 8 bits
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,7));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,6));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,5));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,4));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,3));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,2));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,1));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(addr,0));
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW); // must have this last LOW
}
*/
// this also works using the shiftOut command
void sendStart_works(byte addr) {
pinMode(SDA, OUTPUT);
digitalWrite(SDA, HIGH);
digitalWrite(SCL, HIGH);
digitalWrite(SDA, LOW);
digitalWrite(SCL, LOW);
shiftOut(SDA, SCL, MSBFIRST, addr); // send out the 8 bits
}
void sendStop() {
pinMode(SDA, OUTPUT);
digitalWrite(SDA, LOW);
digitalWrite(SCL, HIGH);
digitalWrite(SDA, HIGH);
pinMode(SDA, INPUT);
}
void sendNack() {
pinMode(SDA, OUTPUT);
digitalWrite(SCL, LOW);
digitalWrite(SDA, HIGH);
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
pinMode(SDA, INPUT);
}
void sendAck() {
pinMode(SDA, OUTPUT);
digitalWrite(SCL, LOW);
digitalWrite(SDA, LOW);
digitalWrite(SCL, HIGH);
digitalWrite(SCL, LOW);
pinMode(SDA, INPUT);
}
byte waitForAck() {
pinMode(SDA, INPUT);
digitalWrite(SCL, HIGH);
byte ack = digitalRead(SDA); //ACK bit should be LOW
digitalWrite(SCL, LOW);
return ack;
}
byte readByte() {
pinMode(SDA, INPUT);
byte value = 0;
byte currentBit = 0;
for (int i = 0; i < 8; ++i) {
digitalWrite(SCL, HIGH);
currentBit = digitalRead(SDA);
value |= (currentBit << 7-i);
delayMicroseconds(1);
digitalWrite(SCL, LOW);
}
return value;
}
void writeByte(byte value) {
pinMode(SDA, OUTPUT);
// send out the 8 bits
for (int i=7; i>=0; i--) {
digitalWrite(SCL, LOW);
digitalWrite(SDA, bitRead(value,i));
digitalWrite(SCL, HIGH);
}
digitalWrite(SCL, LOW); // must have this last LOW
}
// this also works using the shiftOut command
void writeByte2(byte value) {
pinMode(SDA, OUTPUT);
shiftOut(SDA, SCL, MSBFIRST, value);
}
byte readRegister(byte reg) {
byte readValue=0;
sendStart(DS1307_ADDR_W); // set write mode
waitForAck();
writeByte(reg); // send register address to read from
waitForAck();
sendStop();
sendStart(DS1307_ADDR_R); // change to read mode
waitForAck();
readValue = readByte(); // read data from register
sendNack();
sendStop();
return readValue;
}
void writeRegister(byte reg, byte value) {
sendStart(DS1307_ADDR_W);
waitForAck();
writeByte(reg); // send register address
waitForAck();
writeByte(value); // send data to store in register
waitForAck();
sendStop();
}
byte decToBcd(byte val) {
return ((val/10*16) + (val%10));
}
byte bcdToDec(byte val) {
return ((val/16*10) + (val%16));
}
void setup() {
Serial.begin(9600);
Serial.println("DS1307");
pinMode(SCL, OUTPUT);
//pinMode(SDA, OUTPUT); // set in the low-level functions
writeRegister(0x00,0x00); // set the seconds register
// note: reset bit 7 of register 0 to 0 to enable the clock
writeRegister(0x01,decToBcd(15)); // set the minutes register
writeRegister(0x02,decToBcd(8)); // set the hours register
writeRegister(0x07,0x10); // set control register to enable SQW to 1Hz output
Serial.println(readRegister(0x07));
}
void loop() {
Serial.print(bcdToDec(readRegister(2)));
Serial.print(":");
Serial.print(bcdToDec(readRegister(1)));
Serial.print(":");
Serial.println(bcdToDec(readRegister(0)));
delay(1000);
}