[SOLVED] => Using SRAM of DS1307 I2C-RTC - SRAM Data Loss

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

Greetings,

I am using a DS1307 twi-connected to an ATMega-16. A Vbat is also connected. I have successfully implemented the date/time setting and reading. After switching off the main supply and switching on again without setting the date/time again the clock is running correctly. I have added code for storing data in the SRAM area and to read back the same. If SRAM data is written and without switching off "mains" the SRAM data which is read back is correct. But if the "mains" is switched off (Vbat is still working) and if we run the code to only read back from the same location, the SRAM data is lost. However the Date/Time data is still correctly read. The Maxim-Dallas DS1307 Datasheet-"I2C Real-Time Clock" clearly states "56-Byte, Battery-Backed, Nonvolatile (NV) RAM for Data Storage". This exercise was only to study a possibility to use the small non-volatile RAM if ever required in future.

If anyone could guide to overcome this strange behaviour, I would be most grateful.

India_AVR

-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------

Last Edited: Tue. Aug 5, 2008 - 09:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Search on AVRFreaks : DS1307 AND sram gave 7 results
The only person who has reported having used battery-backed SRAM of DS1307 is Mr Lee Theusch on May 10, 2005 - 03:28 PM at
https://www.avrfreaks.net/index.p...

Quote:
"The DS1305/1306 (and DS1307) has more features than just the bare-bones RTC. We've applied them in a number of apps to use the available battery-backed SRAM (that is faster than serial EEPROM for writes and has no write-cycle limitation) as well as using the alarm and interrupt features. "

Possibly Mr Theusch could guide ? Many thanks in advance.

India_AVR

PS : Incidently I had also googled for such a situation but was unsuccessful in the required results.

-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------

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

The SRAM in a DS1307 is non-volatile.

All you have to do is, set the RAM address, write some data there. Read the data back to verify it.

Remove power. Set the RAM address. Read the data.

If your DS1307 is keeping the time correctly via the backup battery, it will keep the SRAM correctly too.

Are you setting the address register correctly ?

David.

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

Dear Mr David Prentice :

Thanks for your kind reply.

Quote:
If SRAM data is written and without switching off "mains" the SRAM data which is read back is correct. But if the "mains" is switched off (Vbat is still working) and if we run the code to only read back from the same location, the SRAM data is lost.
I missed writing the "mains" is switched on again and then read is performed ("mains" => Vcc power to ATmega16 & DS1307). As this seemed odd, hence this post, in case someone had come across this situation. Before I run back to the market and possibly pickup another DS1307 which may be from same "lot" (of strange defect if it really is a defect).

India_AVR

-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------

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

Please post your code.

I fully understand your question. It is always possible that you have a duff DS1307. But it is far more likely that you are reading back a different memory location.

I assume that you are using a 3V battery as backup.

David.

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

Are you sure you are reading back from the same location that you have just written to?
After a write, the address pointer is incremented so you would need to decrement it to read back what you have just written.

Just a thought!

Mark

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

Dear Mr David Prentice
Yes 3V battery. The ReadAndPrintSRAMData() is last 20 lines. I posted the full code, just in case. And the code as per your request:-

/*     RTCMain_SRAM.c     */

/*
	This is a modified version from Copyright (C) 2006 by Donald 
	R. Blake's Utility (stripped down version) + SRAM added, and
	display on LCD instead of PC-Term via UART.

Controller : ATmega16
F_CPU : Internal 1 MHz (Fuse bits confirmed maintained)
Compiler : winavr-20071221
 
	PD0...PD3 => LCD data 4-lines
	PD4 = RS => LCD Control
	PD5 = RW => LCD Control
	PD6 = E  => LCD Control
	
	PC0 => SCL (DS_1307) => RTC via I2C/TWI
	PC1 => SDA (DS_1307) => RTC via I2C/TWI
	
	Please see comments near SetSRAMData()

	TWPS = 0  ( no prescalar )
	TWBR = 47 (forced between 10 and 255)
	SCL_FREQ = 100,000 (as recommended)
	
	=======================================================
	Since RTC is working correctly, I2C/TWI must be correct.
	=======================================================

	TWI Libraries by Donald R. Blake
*/

#include 
#include 
#include 
#include "lcd.h"

#include "twi.h"

#define DS1307_SLA 0x68  // Slave Address


typedef struct {

  uint8_t seconds1  : 4;
  uint8_t seconds10 : 3;
  uint8_t ch        : 1;  // clock hold

  uint8_t minutes1  : 4;
  uint8_t minutes10 : 3;
  uint8_t           : 1;

  uint8_t hours1    : 4; 
  uint8_t hours10   : 2;
  uint8_t mode12    : 1;  // 12-hour mode (1) or 24-hour mode (0)
  uint8_t           : 1;

  uint8_t day       : 3;
  uint8_t           : 5;

  uint8_t date1     : 4;
  uint8_t date10    : 2;
  uint8_t           : 2;

  uint8_t month1    : 4;
  uint8_t month10   : 1;
  uint8_t           : 3;

  uint8_t year1     : 4;
  uint8_t year10    : 4;

  uint8_t rs        : 2;  // rate select
  uint8_t           : 2;
  uint8_t sqwe      : 1;  // square wave enable
  uint8_t           : 2;
  uint8_t out       : 1;  // output control
  
  uint8_t           : 8;  // unused SRAM 08h   +ded these three 
  
  uint8_t aa1       : 4;  // SRAM 09h = aa1 units-aa
  uint8_t aa10      : 4;  // SRAM 09h = aa10 tens-aa
  
  uint8_t bb1       : 4;  // SRAM 0Ah = bb1 units-bb
  uint8_t bb10      : 4;  // SRAM 0Ah = bb10 tens-bb

} ds1307Reg_t;


void SetTime(uint8_t hh, uint8_t mm);
void SetDate(uint8_t dd, uint8_t mm, uint8_t yy);
void ReadAndPrintDateTime(void);

void SetSRAMData(uint8_t aa, uint8_t bb);
void ReadAndPrintSRAMData(void);

int main(void)
{
	//TWI Init
	twiInit( 10 );
	lcd_init(LCD_DISP_ON);
	
	/*
	SetTime(), SetDate() was set only once and continues running 
        with Vbat when no Vcc
	Always shows correct current date and time whenever code is run.
	This means Vbat to DS1307 is properly connected.
	SetTime(20,20); //hh,mm
	SetDate(22,7,8);//dd,mm,yyyy
	*/

	/* If SetSRAMData() is unmasked, and code is run, ReadAndPrintSRAMData() 
	   is same as in SetSRAMData(). This means ReadAndPrintSRAMData() is
	   correctly working.
	   
	   If SetSRAMData() is masked, and Vcc is switched "off" and later "on" and
	   ReadAndPrintSRAMData() is totally different to SetSRAMData(). As there
	   is no change in rest of the code this was not expected. What is seen
	   is (08,00) two values in decimal.
	   
	// SRAM_Data
	SetSRAMData(12, 34);	// SRAMData two decimal values save
	*/

	while(1)
	{
		ReadAndPrintDateTime();
		
		ReadAndPrintSRAMData();		// SRAMData two values recall
						// here does not matter it is
						// recalled over-&-over-again
						// only for testing SRAM usage
		_delay_ms(200);
		_delay_ms(200);
		_delay_ms(200);
		_delay_ms(200);
		_delay_ms(200);
	}
}


void SetTime(uint8_t hh, uint8_t mm) //this fn is used for testing RTC
{
	uint8_t ioBuffer[ 4 ];
	uint8_t rc;	
	
	uint8_t minutes;
	uint8_t hours24;
	
	minutes= ((mm / 10)<<4) | (mm %10);
	hours24= ((hh / 10)<<4) | (hh %10);	
	
	ioBuffer[ 0 ] = 0; 		//Timekeeper Address 00h
	ioBuffer[ 1 ] = 0; 		//seconds
	ioBuffer[ 2 ] = minutes;
	ioBuffer[ 3 ] = hours24;	
	
	
	rc = twiWrite( DS1307_SLA, ioBuffer, 4 );
	
	_delay_ms(10);
}


void SetDate(uint8_t dd, uint8_t mm, uint8_t yy)
{
	uint8_t ioBuffer[ 4 ];
	uint8_t rc;		
	uint8_t date, month, year;
	
	date= ((dd/10)<<4) | (dd%10);
	month= ((mm/10)<<4) | (mm%10);
	year= ((yy/10)<<4) | (yy%10);

	ioBuffer[ 0 ] = 4; 		//Timekeeper Address 04h
	ioBuffer[ 1 ] = date;//dd
	ioBuffer[ 2 ] = month; //mm
	ioBuffer[ 3 ] = year;//yy
	
	rc = twiWrite( DS1307_SLA, ioBuffer, 4 );

	_delay_ms(10);

}

void ReadAndPrintDateTime(void)
{
	//RTC variables
	uint8_t     regAddress;
	ds1307Reg_t timeAndDate;
	uint8_t     rc;	
	
	// write DS1307 register address
	regAddress = 0;
	rc = twiWrite( DS1307_SLA, ®Address, 1 );	

	// read DS1307 registers
	rc = twiRead( DS1307_SLA, (uint8_t *) &timeAndDate, 8 );
	lcd_gotoxy(0,1);
	
	lcd_putc((timeAndDate.hours10) + 48);
	lcd_putc(timeAndDate.hours1 + 48);
	lcd_putc(':');
	lcd_putc((timeAndDate.minutes10)+ 48);
	lcd_putc((timeAndDate.minutes1 ) + 48);
	lcd_putc(':');
	lcd_putc(timeAndDate.seconds10 + 48);
	lcd_putc(timeAndDate.seconds1 + 48);
	
	lcd_gotoxy(0,0);
	lcd_putc((timeAndDate.date10)+ 48);
	lcd_putc(timeAndDate.date1+ 48);
	lcd_putc('/');
	lcd_putc((timeAndDate.month10 )+ 48);
	lcd_putc(timeAndDate.month1+ 48);
	lcd_putc('/');
	lcd_putc('2');
	lcd_putc('0');
	lcd_putc((timeAndDate.year10 )+ 48);
	lcd_putc(timeAndDate.year1+ 48);
	//lcd_putc('*');
	//lcd_putc(timeAndDate.day+ 48);
	lcd_command(LCD_DISP_ON);	
}

void SetSRAMData(uint8_t aa, uint8_t bb)	// +ded for SRAM
{
	uint8_t ioBuffer[ 3 ];
	uint8_t rc;		
	uint8_t var_aa, var_bb;
	
	var_aa= ((aa/10)<<4) | (aa%10);// incase some processing is done
	var_bb= ((bb/10)<<4) | (bb%10);// e.g. Dec2BCD for easy LCD display

	ioBuffer[ 0 ] = 9;		// SRAM Register 0x09h
	ioBuffer[ 1 ] = var_aa;		//aa1+aa10
	ioBuffer[ 2 ] = var_bb;		//bb1+bb10
		
	rc = twiWrite( DS1307_SLA, ioBuffer, 3 );

	_delay_ms(10);

}

void ReadAndPrintSRAMData(void)	// +ded for SRAM
{
	//SRAM variables
	uint8_t     regAddress;
	ds1307Reg_t SRAMData;
	uint8_t     rc;	
	
	// write DS1307 register address
	regAddress = 9;			// SRAM Register 0x09h
	rc = twiWrite( DS1307_SLA, ®Address, 1 );	

	// read DS1307 registers
	rc = twiRead( DS1307_SLA, (uint8_t *) &SRAMData, 3 );

	lcd_gotoxy(14,0);	// make absolute position (x,y)
	lcd_putc((SRAMData.aa10) + 48);
	lcd_putc((SRAMData.aa1) + 48);

	lcd_gotoxy(14,1);
	lcd_putc((SRAMData.bb10)+ 48);
	lcd_putc((SRAMData.bb1)+ 48);
	lcd_command(LCD_DISP_ON);	
}

Dear Mr Mark Storr :
The "Read" has a re-initialised "regAddress" everytime.

===============================

Possibly something may be going wrong with address pointer. If it works with the RTC portion it should work for the SRAM potion as the code philosophy is same.

Thanks to all in advance.

India_AVR

PS : Wanted to highlight important comments within the "Code" but these commands are not invoked hence reproducing that portion in a later post of 05-Aug-2008 10:44 AM.

-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------

Last Edited: Tue. Aug 5, 2008 - 11:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've only used it with DS1305/06. It worked fine there to save a few critical parameters when racing at power loss.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   // write DS1307 register address
   regAddress = 9;         // SRAM Register 0x09h
   rc = twiWrite( DS1307_SLA, ®Address, 1 );   

   // read DS1307 registers
   rc = twiRead( DS1307_SLA, (uint8_t *) &SRAMData, 3 );

The code above will read locations 9,10,11 from the DS1307 into the first few fields of the bitfield structure.

You then display the end of your structure that just contains garbage.

Your bitfield methods are really complicated. The DS1307 stores everything in BCD so all you have to do is printf("%02x", hour) etc...

David.

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

Dear Mr David Prentice and all AVRFreaks
Reproduced comments from last code posted :

Quote:

/*
SetTime(), SetDate() was set only once and continues running with Vbat when no Vcc. Always shows correct current date and time whenever code is run. This means Vbat to DS1307 is properly connected.
........SetTime(20,20); //hh,mm
........SetDate(22,7,8 );//dd,mm,yyyy
*/

/* If SetSRAMData() is unmasked, and code is run, ReadAndPrintSRAMData() is same as in SetSRAMData(). This means ReadAndPrintSRAMData() is correctly working.

If SetSRAMData() is masked, and Vcc is switched "off" and later "on" and ReadAndPrintSRAMData() is totally different to SetSRAMData(). As there is no change in rest of the code this was not expected. What is seen is (08,00) two values in decimal.

..........// SRAM_Data
........SetSRAMData(12, 34);
..........// SRAMData two decimal values save
*/


Below is the twiRead() portion from twi.c of Mr Blake's Library which I am using:-
/********************************************************************************

                            twiRead - Master Receive

********************************************************************************/

uint8_t
twiRead(
  uint8_t  sla,
  uint8_t* data,
  uint8_t  count
)
{

  uint8_t rc;

  // send SLA+R
  rc = sendSla( sla, TW_READ );
  if ( rc != 0 ) return rc;

  // read data byte(s)

  do
  {

    // set up to receive next data byte
    TWCR = _BV( TWINT ) | _BV( TWEN) | ( ( count != 1 ) ? _BV( TWEA ) : 0 );

    // wait for data byte
    WAIT_FOR_TWINT;

    // check for timeout and check status
    if ( !TWI_READY ) return 9;
    if ( TW_STATUS !=
         ( ( count != 1 ) ? TW_MR_DATA_ACK : TW_MR_DATA_NACK ) )
    {
      generateStop( );
      return 10;
    } // end if

Based on above reading registers 9,10,11 but assigning values of Reg-9 and Reg-10 to 4-bits (1-nibble) as each BCD (2-digit BCD each register)

SRAMData.aa10
SRAMData.aa1

SRAMData.bb10
SRAMData.bb1

because originally at twiWrite this was how it was done. Or am I making a mistake ?

Sorry about the bitfield method used as this is the same being followed from Mr Blakes original code of RTC portion which is working under all circumstances here (trying not to re-invent the wheel here). With due respects to all - no offence meant.

Many thanks in advance.

India_AVR.

-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------

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

dear India,

Did you read my reply ?

You read back a part ds1307reg_t structure from registers 0 .. 7 when you are reading the time.

You then read a part ds1307reg_t structure from registers 9 .. .
Having not even filled the whole structure, you expect to read structure fields that have not been filled.

I have no idea who Mr Blake is, but if you do not post the complete functions or at least the function signatures, it is very difficult.

David.

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

Dear Mr David Prentice and Mr Mark Storr,

While reading SRAM data, I was guided by another kind person (who explained what you said in your posts), to read the FULL structure DS1307Reg_t. Namely 12 locations in my case, which included the registers of interest (SRAMData.aa10), (SRAMData.aa1), (SRAMData.bb10), (SRAMData.bb1). Hence all got correctly allocated and displayed every time. And even when "writing to SRAM" is masked, the reading is now consistantly correct from the non volatile SRAM. Earlier I was mistakenly reading only 4 locations of DS1307. The assignment of "ioBuffer[ 0 ] = 9;" in Write was correct for the DS1307, but "regAddress = 9;" in Read caused the "&SRAMData" pointing in the ATMega16, which was wrong. Ofcourse, as also rightly pointed out by your kind self, I could have made a seperate array or set of variables for the SRAM area and it could have been easier to work with. I again, whole heartedly, thank you all for sparing your valuable time and for your kind guidance. [SOLVED]

India_AVR

PS : I just extended the BCD coding as anyway I was using the LCD and wanted to maintain the same philosopy.

-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------

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

Quote:
I have no idea who Mr Blake is,
:shock: He is one of our dear freak who has contributed a DS1307 project. Don was a lot more active in the past but life happens.

He seems to be getting back to posting a little now.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I made an inspired guess as to his TWI function signatures. Then called my own routines.

I will have a search for his projects.

David.

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

Maybe you would like to "see" Mr Don Blake :
https://www.avrfreaks.net/index.p...
You will have to go to page 2. But do read his all postings. We really are very lucky to the easy of working nowadays to when "the pioneers" started and still help us. Tools may change but knowledge is supreme. Long Live AVRFreaks ! We Salute you !

India_AVR

PS : I also suggest a visit to his website mentioned in his profile

-----------------------------------------
Wonderful world of "0"s & "1"s
-----------------------------------------