Ds1307 keeps resetting to 00:00:00

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello!

I have a very beginner,very frequent question.I am building a LED wall clock with a Xplained mini328p dev.board(64 LEDs show the seconds around a 4 digit 7 segment display).And I want to keep the time when VCC is off. So I use a DS1307+ and when I pull out the USB cable the RTC just keeps forgetting the time and starts from 00:00:00. I use 2 4.7k pullup resistors on SCL SDA lines, the battery is connected and it's 3.07 volts, the oscillator is a 32.6 kHz oscillator. So in theory it should work.
The code:
 

 //Author : Bruce E. Hall  -> source
//GLOBAL DEFINES
#define F_CPU 16000000L // run CPU at 16 MHz
#define ClearBit(x,y) x &= ~_BV(y) // equivalent to cbi(x,y)
#define SetBit(x,y) x |= _BV(y) // equivalent to sbi(x,y)

//INCLUDES
#include <avr/io.h> // deal with port registers
#include <util/delay.h> // used for _delay_ms function
#include <string.h> // string manipulation routines
#include <stdlib.h>

#ifndef NDEBUG
volatile
#endif

uint8_t Byte1=0x00;
uint8_t Byte2=0x00;

#define HC595_PORT   PORTB
#define HC595_DDR    DDRB
#define HC595_DS_POS PORTB4     //Data pin (DS) pin location
#define HC595_SH_CP_POS PORTB3     //Shift Clock (SH_CP) pin location
#define HC595_ST_CP_POS PORTB2      //Store Clock (ST_CP) pin location

typedef uint8_t byte; // I just like byte & sbyte better
typedef int8_t sbyte;

#define DIGIT0 0b00010001
#define DIGIT1 0b11111001
#define DIGIT2 0b00011100
#define DIGIT3 0b01011000
#define DIGIT4 0b11110000
#define DIGIT5 0b01010010
#define DIGIT6 0b00010010
#define DIGIT7 0b01111001
#define DIGIT8 0b00010000
#define DIGIT9 0b01010000
#define DIGITPONT 0b11101111

//DS1307 RTC ROUTINES
#define DS1307 0xD0 // I2C bus address of DS1307 RTC
#define SECONDS_REGISTER 0x00
#define MINUTES_REGISTER 0x01
#define HOURS_REGISTER 0x02
#define DAYOFWK_REGISTER 0x03
#define DAYS_REGISTER 0x04
#define MONTHS_REGISTER 0x05
#define YEARS_REGISTER 0x06
#define CONTROL_REGISTER 0x07
#define RAM_BEGIN 0x08
#define RAM_END 0x3F

//I2C (TWI) ROUTINES

/*On the AVRmega series, PA4 is the data line (SDA) and PA5 is the clock (SCL
The standard clock rate is 100 KHz, and set by I2C_Init. It depends on the AVR osc. freq.*/
#define F_SCL 100000L // I2C clock speed 100 KHz
#define READ 1
#define TW_START 0xA4 // send start condition (TWINT,TWSTA,TWEN)
#define TW_STOP 0x94 // send stop condition (TWINT,TWSTO,TWEN)
#define TW_ACK 0xC4 // return ACK to slave
#define TW_NACK 0x84 // don't return ACK to slave
#define TW_SEND 0x84 // send data (TWINT,TWEN)
#define TW_READY (TWCR & 0x80) // ready when TWINT returns to logic 1.
#define TW_STATUS (TWSR & 0xF8) // returns value of status register
#define I2C_Stop() TWCR = TW_STOP // inline macro for stop condition

void msDelay(int delay) // put into a routine
{ // to remove code inlining
	for (int i=0;i<delay;i++) // at cost of timing accuracy
	_delay_ms(1);
}

void I2C_Init()
//at 16 MHz, the SCL frequency will be 16/(16+2(TWBR)), assuming prescalar of 0.
//so for 100KHz SCL, TWBR = ((F_CPU/F_SCL)-16)/2 = ((16/0.1)-16)/2 = 144/2 = 72.

{
	TWSR = 0; // set prescalar to zero
	TWBR = ((F_CPU/F_SCL)-16)/2; // set SCL frequency in TWI bit register
}
byte I2C_Detect(byte addr)
//look for device at specified address; return 1=found, 0=not found
{
	TWCR = TW_START; // send start condition
	while (!TW_READY); // wait
	TWDR = addr; // load device's bus address
	TWCR = TW_SEND; // and send it
	while (!TW_READY); // wait
	return (TW_STATUS==0x18); // return 1 if found; 0 otherwise
}
byte I2C_FindDevice(byte start)
//returns with address of first device found; 0=not found
{
	for (byte addr=start;addr<0xFF;addr++) // search all 256 addresses
	{
		if (I2C_Detect(addr)) // I2C detected?
		return addr; // leave as soon as one is found
	}
	return 0; // none detected, so return 0.
}
void I2C_Start (byte slaveAddr)
{
	I2C_Detect(slaveAddr);
}
byte I2C_Write (byte data) // sends a data byte to slave
{
	TWDR = data; // load data to be sent
	TWCR = TW_SEND; // and send it
	while (!TW_READY); // wait
	return (TW_STATUS!=0x28);
}
byte I2C_ReadACK () // reads a data byte from slave
{
	TWCR = TW_ACK; // ack = will read more data
	while (!TW_READY); // wait
	return TWDR;
	//return (TW_STATUS!=0x28);
}
byte I2C_ReadNACK () // reads a data byte from slave
{
	TWCR = TW_NACK; // nack = not reading more data
	while (!TW_READY); // wait
	return TWDR;
	//return (TW_STATUS!=0x28);
}
void I2C_WriteByte(byte busAddr, byte data)
{
	I2C_Start(busAddr); // send bus address
	I2C_Write(data); // then send the data byte
	I2C_Stop();
}
void I2C_WriteRegister(byte busAddr, byte deviceRegister, byte data)
{
	I2C_Start(busAddr); // send bus address
	I2C_Write(deviceRegister); // first byte = device register address
	I2C_Write(data); // second byte = data for device register
	I2C_Stop();
}
byte I2C_ReadRegister(byte busAddr, byte deviceRegister)
{
	byte data = 0;
	I2C_Start(busAddr); // send device address
	I2C_Write(deviceRegister); // set register pointer
	I2C_Start(busAddr+READ); // restart as a read operation
	data = I2C_ReadNACK(); // read the register data
	I2C_Stop(); // stop
	return data;
}

void DS1307_GetTime(byte *hours, byte *minutes, byte *seconds) //returns hours, minutes, and seconds in BCD format
{
	*hours = I2C_ReadRegister(DS1307,HOURS_REGISTER);
	*minutes = I2C_ReadRegister(DS1307,MINUTES_REGISTER);
	*seconds = I2C_ReadRegister(DS1307,SECONDS_REGISTER);
	if (*hours & 0x40) // 12hr mode:
	*hours &= 0x1F; // use bottom 5 bits (pm bit = temp & 0x20)
	else *hours &= 0x3F; // 24hr mode: use bottom 6 bits
}

void SetTimeDate()
//simple, hard-coded way to set the date.
{

	I2C_WriteRegister(DS1307,HOURS_REGISTER, 0x18); // add 0x40 for PM
	I2C_WriteRegister(DS1307,MINUTES_REGISTER, 0x51);
	I2C_WriteRegister(DS1307,SECONDS_REGISTER, 0x34);
}

void shiftInit()
{
	//Make the Data(DS), Shift clock (SH_CP), Store Clock (ST_CP) lines output
	HC595_DDR|=((1<<HC595_SH_CP_POS)|(1<<HC595_ST_CP_POS)|(1<<HC595_DS_POS));
}

//change data (DS)lines
#define HC595DataHigh() (HC595_PORT|=(1<<HC595_DS_POS))
#define HC595DataLow() (HC595_PORT&=(~(1<<HC595_DS_POS)))

//Sends a clock pulse on SH_CP line
void shiftPulse()
{
	//Pulse the Shift Clock
	HC595_PORT|=(1<<HC595_SH_CP_POS);//HIGH
	HC595_PORT&=(~(1<<HC595_SH_CP_POS));//LOW
}

//Sends a clock pulse on ST_CP line
void shiftLatch()
{
	//Pulse the Store Clock
	HC595_PORT|=(1<<HC595_ST_CP_POS);//HIGH
	_delay_loop_1(1);
	HC595_PORT&=(~(1<<HC595_ST_CP_POS));//LOW
	_delay_loop_1(1);
}
void shiftWrite(byte data)
{
	//Send each 8 bits serially
	//Order is MSB first
	for(uint8_t i=0;i<8;i++)
	{
		//Output the data on DS line according to the
		//Value of MSB
		if(data & 0b10000000)
		{
			//MSB is 1 so output high
			HC595DataHigh();
		}
		else
		{
			//MSB is 0 so output high
			HC595DataLow();
		}
		shiftPulse();  //Pulse the Clock line
		data=data<<1;  //Now bring next bit at MSB position
	}
	//Now all 8 bits have been transferred to shift register
	//Move them to output latch at once
	shiftLatch();
}

//PROGRAM LOOP
void MainLoop()
{
	while(1)
	{
		uint8_t hours, minutes, seconds;
		DS1307_GetTime(&hours,&minutes,&seconds);

		if(seconds==0x00)
		{
			Byte1=0b00000001;
			Byte2=0b10000000;
		}
		if(seconds==0x01)
		{
			Byte1=0b10000000;
			Byte2=0b00000001;
		}
		if(seconds==0x02)
		{
			Byte1=0b01000000;
			Byte2=0b00000001;
		}
		if(seconds==0x03)
		{
			Byte1=0b00100000;
			Byte2=0b00000001;
		}
		if(seconds==0x04)
		{
			Byte1=0b00010000;
			Byte2=0b00000001;
		}
		if(seconds==0x05)
		{
			Byte1=0b00001000;
			Byte2=0b00000001;
		}
		if(seconds==0x06)
		{
			Byte1=0b00000100;
			Byte2=0b00000001;
		}
		if(seconds==0x07)
		{
			Byte1=0b00000010;
			Byte2=0b00000001;
		}
		if(seconds==0x08)
		{
			Byte1=0b00000001;
			Byte2=0b00000001;
		}
		if(seconds==0x09)
		{
			Byte1=0b10000000;
			Byte2=0b00000100;
		}
		if(seconds==0x10)
		{
			Byte1=0b01000000;
			Byte2=0b00000100;
		}
		if(seconds==0x11)
		{
			Byte1=0b00100000;
			Byte2=0b00000100;
		}
		if(seconds==0x12)
		{
			Byte1=0b00010000;
			Byte2=0b00000100;
		}
		if(seconds==0x13)
		{
			Byte1=0b00001000;
			Byte2=0b00000100;
		}
		if(seconds==0x14)
		{
			Byte1=0b00000100;
			Byte2=0b00000100;
		}
		if(seconds==0x15)
		{
			Byte1=0b00000001;
			Byte2=0b00000100;
		}
		if(seconds==0x16)
		{
			Byte1=0b10000000;
			Byte2=0b00000010;
		}
		if(seconds==0x17)
		{
			Byte1=0b01000000;
			Byte2=0b00000010;
		}
		if(seconds==0x18)
		{
			Byte1=0b00100000;
			Byte2=0b00000010;
		}
		if(seconds==0x19)
		{
			Byte1=0b00010000;
			Byte2=0b00000010;
		}
		if(seconds==0x20)
		{
			Byte1=0b00001000;
			Byte2=0b00000010;
		}
		if(seconds==0x21)
		{
			Byte1=0b00000100;
			Byte2=0b00000010;
		}
		if(seconds==0x22)
		{
			Byte1=0b00000010;
			Byte2=0b00000010;
		}
		if(seconds==0x23)
		{
			Byte1=0b00000001;
			Byte2=0b00000010;
		}
		if(seconds==0x24)
		{
			Byte1=0b10000000;
			Byte2=0b00001000;
		}
		if(seconds==0x25)
		{
			Byte1=0b01000000;
			Byte2=0b00001000;
		}
		if(seconds==0x26)
		{
			Byte1=0b00100000;
			Byte2=0b00001000;
		}
		if(seconds==0x27)
		{
			Byte1=0b00010000;
			Byte2=0b00001000;
		}
		if(seconds==0x28)
		{
			Byte1=0b00001000;
			Byte2=0b00001000;
		}
		if(seconds==0x29)
		{
			Byte1=0b00000100;
			Byte2=0b00001000;
		}
		if(seconds==0x30)
		{
			Byte1=0b00000001;
			Byte2=0b00001000;
		}
		if(seconds==0x31)
		{
			Byte1=0b10000000;
			Byte2=0b00010000;
		}
		if(seconds==0x32)
		{
			Byte1=0b01000000;
			Byte2=0b00010000;
		}
		if(seconds==0x33)
		{
			Byte1=0b00100000;
			Byte2=0b00010000;
		}
		if(seconds==0x34)
		{
			Byte1=0b00010000;
			Byte2=0b00010000;
		}
		if(seconds==0x35)
		{
			Byte1=0b00001000;
			Byte2=0b00010000;
		}
		if(seconds==0x36)
		{
			Byte1=0b00000100;
			Byte2=0b00010000;
		}
		if(seconds==0x37)
		{
			Byte1=0b00000010;
			Byte2=0b00010000;
		}
		if(seconds==0x38)
		{
			Byte1=0b00000001;
			Byte2=0b00010000;
		}
		if(seconds==0x39)
		{
			Byte1=0b10000000;
			Byte2=0b00100000;
		}
		if(seconds==0x40)
		{
			Byte1=0b01000000;
			Byte2=0b00100000;
		}
		if(seconds==0x41)
		{
			Byte1=0b00100000;
			Byte2=0b00100000;
		}
		if(seconds==0x42)
		{
			Byte1=0b00010000;
			Byte2=0b00100000;
		}
		if(seconds==0x43)
		{
			Byte1=0b00001000;
			Byte2=0b00100000;
		}
		if(seconds==0x44)
		{
			Byte1=0b00000100;
			Byte2=0b00100000;
		}
		if(seconds==0x45)
		{
			Byte1=0b00000001;
			Byte2=0b00100000;
		}
		if(seconds==0x46)
		{
			Byte1=0b10000000;
			Byte2=0b01000000;
		}
		if(seconds==0x47)
		{
			Byte1=0b01000000;
			Byte2=0b01000000;
		}
		if(seconds==0x48)
		{
			Byte1=0b00100000;
			Byte2=0b01000000;
		}
		if(seconds==0x49)
		{
			Byte1=0b00010000;
			Byte2=0b01000000;
		}
		if(seconds==0x50)
		{
			Byte1=0b00001000;
			Byte2=0b01000000;
		}
		if(seconds==0x51)
		{
			Byte1=0b00000100;
			Byte2=0b01000000;
		}
		if(seconds==0x52)
		{
			Byte1=0b00000010;
			Byte2=0b01000000;
		}
		if(seconds==0x53)
		{
			Byte1=0b00000001;
			Byte2=0b01000000;
		}
		if(seconds==0x54)
		{
			Byte1=0b10000000;
			Byte2=0b10000000;
		}
		if(seconds==0x55)
		{
			Byte1=0b01000000;
			Byte2=0b10000000;
		}
		if(seconds==0x56)
		{
			Byte1=0b00100000;
			Byte2=0b10000000;
		}
		if(seconds==0x57)
		{
			Byte1=0b00010000;
			Byte2=0b10000000;
		}
		if(seconds==0x58)
		{
			Byte1=0b00001000;
			Byte2=0b10000000;
		}
		if(seconds==0x59)
		{
			Byte1=0b00000100;
			Byte2=0b10000000;
		}

		shiftWrite(Byte1);
		shiftWrite(Byte2);
		msDelay(1000); // one second between updates

	}
}

//MAIN PROGRAM
int main(void)
{
	shiftInit();
	I2C_Init(); // set I2C clock frequency
	I2C_WriteRegister(DS1307,CONTROL_REGISTER,0x00);
	//SetTimeDate();
	MainLoop(); // display time
}

ps.: the enourmous If block is not relevant here and I know it's very ugly, but I don't have any other idea to replace it.

The schematic.:

 

ps.: C9 and C10 are not soldered to the PCB and a more clear version is attached

Any help would be  highly appreciated

 

Steven

Attachment(s): 

This topic has a solution.
Last Edited: Mon. Aug 5, 2019 - 07:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

This is a bit of a random circuit. Hc595 chips are not good for sourcing/sinking the amount of current you require, but you use a tpic6b595 on the leds and pnp transistors on the displays. Looks like you got some random circuits and guessed.

Converting the bcd will make your job a bit easier.

The ds1307 has a status register. It might be able to tell you why it is unhappy.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The shift register part works good thanks god :) The Hc means high current in this chip no?
How could I access it's status register? I didnt't find anything in the datasheet about status register.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

No, HC does not stand for high current.

 

There was 74Cxxx, with the "C" referring to CMOS. Then, 74HCxxx which referred to Highspeed CMOS.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

huistbor wrote:

ps.: the enourmous If block is not relevant here and I know it's very ugly, but I don't have any other idea to replace it.

I can't see if there is an obvious pattern with the byte1 and byte2 values.

Assume there isn't any obvious pattern.

The standard way to do this kind of thing would be with lookup tables.

You have a table (array) of 60 values for byte1 and 60 values for byte2.

 

const uint8_t byte1_table[60] = { 60 values go here };

const uint8_t byte2_table[60] = { 60 values go here };

 

Then your 60 if statements can be replaced with something like

uint8_t seconds_decimal = bcd_to_decimal(seconds);

byte1 = byte1_table[seconds_decimal];

byte2 = byte2_table[seconds_decimal];

 

The conversion bcd_to_decimal (eg. 0x27 ==> 27)  is straightforward, you can figure it out I'm sure.

 

Note that as written above, the tables will be located in RAM. This is fine if you have plenty of RAM, but ususally with microcontrollers you don't so using up 120 bytes of RAM for these tables might be a problem. Fortunately, becuase the tables only need to be read-only (hence const) it is possible with the right compiler directives to have the tables stored in program memory (flash) rather than in RAM. There is plenty of information how to do this (I'm not going to mention how here because I might get it wrong!).

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for your comment! This is actually very useful, I will rewrite my code.

But the RTC erro still persists :( .
DO you have any idea for that by chance? :)

Steven

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

huistbor wrote:
But the RTC erro still persists :( .
DO you have any idea for that by chance? :)

I do not see any bypass caps on any of the chips, each vcc pin on each chip should have a 100nf cap to ground.

See data sheet for your clock chip to see what it recommends.

Jim

edit: when I have my glasses on, there are bypass caps!  sad

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
stack gold/silver https://www.onegold.com/join/713...

 

 

 

 

Last Edited: Sat. Aug 3, 2019 - 07:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If your 1307's registers are resetting to zero then your battery on the 1307 is not switching between Vcc and battery power correctly when Vcc is turned off.  

There is no 1307 circuitry on the enclosed schematic.  Please check that your design matches the various 1307 schematics found on the web, including various diodes (which may be Schottky type; with a 0.2V drop instead of signal diodes; with a 0.7V drop) and pull up/pull down resistors. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


On the bottom you can find the DS1307( it's a bit blurry but I included the pdf maybe it is more clear there.) It looks like this on the PCB except the capacitors are not soldered in. Does it cause a problem?

  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually on the PCB the caps are missing because I didn't solder them in, so you are right in this one smiley. They can cause problems like this? Anyway I will add them tomorrow and I will report back.

Thanks :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Looking at the data sheet for this, no caps are needed if the correct xtal is used, and leads should be short and a gnd guard ring is needed, see datasheet for details.

One thing to try is enable the clock out on pin 7 and see if the clock is running w/ and w/out vcc power.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
stack gold/silver https://www.onegold.com/join/713...

 

 

 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

*Update*

on breadboard it works. So it must be some problem with the grounding I think. sad

*New update*

Now it doesnt't work on breadboard either :'(

I will replace the ds1307 and the crystal too, I gave up hope 

Last Edited: Sun. Aug 4, 2019 - 06:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay thank you everyone, it was the ds1307.

Never buy anything from shady vendors! :)