Continue to Site

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.

  • 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.

RTC DS1337 Datasheet

Status
Not open for further replies.
I've done some work on it but I have a one specific question
C:
#include <reg51.h>

#define I2C_DELAY    50
#define TOGGLE_LED  20000

#define device_addrW  0xD0 //device address with write 1101 0000
#define device_addrR  0xD1  //device address with Read  1101 0001

#define ACK_BIT    0

sbit SDA_BUS = P2^0;     //Define the Pin for the I2c and lec
sbit SCL_BUS = P2^1;
sbit Led = P3^0;

void InitI2c(void);
void StartI2c(void);
void RepeatedStartI2c(void);
void StopI2c(void);
void SendAckBit(void);
void SendNackBit(void);
void delay(unsigned int);
bit write_i2c(unsigned char);
unsigned char read_i2c(void);
void write_byte_to_DS1337(unsigned int,unsigned char);
unsigned char  read_byte_from_DS1337(unsigned int);

/**This function provide the delay which is used in clock generation.
*/
void delay(unsigned int d)
{
    unsigned int i;
    for(i=0; i<d; i++);
}
/**This function  use to make the data line and clock line idle to put the both line high
*/
void InitI2c(void)
{
    SDA_BUS =1;
    SCL_BUS =1;
}
/**This function performs the start operation to initiate the communication.
*/
void StartI2c(void)
{
    SDA_BUS  = 1;
    SCL_BUS  = 1;
    delay(I2C_DELAY);
    SDA_BUS  = 0;
    delay(I2C_DELAY);
}
/**When master does not want to relaese the control from the bus then it assert the repeated
start condition on the i2c bus.
*/
void RepeatedStartI2c()
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 1;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY/2);
    SDA_BUS  = 0;
    delay(I2C_DELAY);
}
/**When master want to stop the communication then it will assert the stop condition to the i2c bus.
*/
void StopI2c(void)
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 0;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY/2);
    SDA_BUS  = 1;
    delay(I2C_DELAY);
}
/**This function use to send the acknoledgement(ACK) bit the i2c bus.
*/
void SendAckBit()
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 0;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY);
}
/**This function use to send the Non-acknoledgement(NACK) bit the i2c bus.
*/
void SendNackBit(void)
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 1;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY);
}
/**This function use to send signle byte to the I2C Data Bus*/
bit write_i2c(unsigned char byte)
{
    unsigned char i;
    for(i=0; i<8; i++)
    {
        SCL_BUS  = 0;
        delay(I2C_DELAY);
        if((byte<<i)&0x80)
            SDA_BUS  = 1;
        else
            SDA_BUS  = 0;
        delay(I2C_DELAY/2);
        SCL_BUS  = 1;
        delay(I2C_DELAY);
    }
//ack from slave //
    SCL_BUS  = 0;
    SDA_BUS  = 0;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY);
    return SDA_BUS;
}
/**This function use to read the data from the I2C data bus*/
unsigned char read_i2c(void)
{
    unsigned char i,d, rxdata=0;
    for(i=0; i<8; i++)
    {
        SCL_BUS  = 0;
        SDA_BUS  = 1;
        delay(I2C_DELAY);
        SCL_BUS  = 1;
        delay(I2C_DELAY/2);
        d=SDA_BUS;
        rxdata=rxdata|(d<<7-i);
        delay(I2C_DELAY);
    }
    return rxdata;
}
/**This function use to single byte the DS1337 at desire address
*///Write Data to DS1337
void write_byte_to_DS1337(unsigned int addr,unsigned char byte)
{
    StartI2c();
    while(write_i2c(device_addr|0)==1)
    {
        StartI2c();
    }
    write_i2c(addr>>8);
    write_i2c((unsigned char)addr);
    write_i2c(byte);
    StopI2c();
}
/**
\brief of read_byte_from_DS1337 function.
This function use to read the data byte from DS1337 at the desire the address
*/
unsigned char read_byte_from_DS1337(unsigned int addr)
{
    unsigned char rxdata =0;
    StartI2c();
    while(write_i2c(device_addr|0)==1)
    {
        StartI2c();
    }
    write_i2c(addr>>8);
    write_i2c((unsigned char)addr);
    RepeatedStartI2c();
    write_i2c(device_addr|1);
    rxdata=read_i2c();
    SendNackBit();
    StopI2c() ;
    return rxdata;
}
// Main function
void main(void)
{

    unsigned char rxbyte=0;
    unsigned char cSendByte = 0x00;
    Led  = 0;
    SDA_BUS = 0;
    SCL_BUS = 0;
    InitI2c();
    write_byte_to_DS1337(0xD0, cSendByte);  
}

Is my main function doing the right thing to send device address with write mode ?
 
I've done some work on it but I have a one specific question
/--/

Is my main function doing the right thing to send device address with write mode ?

So follow it through. You know that the 7-bit I2C address is binary 1101000 those 7 bits are followed by a 0 (write) or 1 (read).
Your statement:
write_byte_to_DS1337(0xD0, cSendByte);

0xD0 = 11010000

In your function, you have:
write_i2c(addr>>8);
write_i2c((unsigned char)addr);

You are declaring addr, not as an unsigned 8 bit char, but a 16 bit variable. Then you are shifting it right by 8 bits. What happens to the value 0000000011010000 shifted right 8 bits?

Answer that and you have your answer, but I am way to tired to be looking at code, so then again, maybe not.

edit: Just ignore this, I didn't look at it carefully
 
Last edited:
well, ok - so in your example addr is the eeprom address and not the i2c address. OK, I have not looked all through your code, so just forget what I said.
I have gone through many links and found one example. Could you tell me how to use that sample code for DS1337?

only prototype function may be great help for me at this point then I can try to implement the functions
 
The EEPROM code is virtually identical to what you would use for any other device, such as the DS1337, just with different device addresses.

A common difference between various types of devices is the internal (register) address range needed. The EEPROM example uses a 16 bit address (sent as two bytes), the RTC only needs 8 bit.

Pass the register address as an unsigned char and leave out the "write_i2c(addr>>8); " parts.

(The number of bytes of internal or register address you need to send depends how many registers or storage locations the specific device has - memories have a lot, peripherals like RTCs and i/o expanders generally have few.)
 
I have gone through many links and found one example. Could you tell me how to use that sample code for DS1337?

only prototype function may be great help for me at this point then I can try to implement the functions

Sorry, no, I don't think I can be of much help. I read through the thread more throughly (which I should have done before responding the first time) and, in my opinion, you are not yet at a place to "implement the functions". I am sorry if that sounds too harsh, but that is what it seems like to me.

I guess I would tell you to take a step back and perhaps start with a very simple I2C function first.

I've done some work on it but I have a one specific question

Really, you have many more than "one specific question".

It took me many, many hours of work with many sensors to understand the I2C protocol and I am, by no means, an expert. If this is for a class/homework project, state as much. Even if it is, you can not understand this by copying some code and patching it together and asking questions that strongly suggest that you don't understand the fundamentals.

You are just like everyone else, you have to build a foundation. Again sorry if this sounds too harsh or too preachy, but it is what I think.
 
Sorry, no, I don't think I can be of much help. I read through the thread more throughly (which I should have done before responding the first time) and, in my opinion, you are not yet at a place to "implement the functions". I am sorry if that sounds too harsh, but that is what it seems like to me.
Thanks for helping my friend You said right, I will learn as everyone learn.

I don't think my technique is wrong. I was assuming that I had I2C routines and I was using them to read and write DS1337

C:
void InitI2c(void);  //Initializing I2C Bus Communication
void StartI2c(void); //Start Condition for I2C Communication
void RepeatedStartI2c(void); //ReStart Condition for I2C Communication
void StopI2c(void); //Stop Condition For I2C Bus
void SendAckBit(void); //ACK for I2C Bus
void SendNackBit(void); //NAK for I2C Bus
void delay(unsigned int); // Dealy
bit write_i2c(unsigned char Data); //Sending Data to slave on I2C bus
unsigned char read_i2c(void); //Receiving Data from slave on I2C bus
void write_byte_to_DS1337(unsigned int n,unsigned char value ); //Write Data to DS1337
unsigned char  read_byte_from_DS1337(unsigned int); //Read Data from DS1337

Now I know this is my building blocks and And I have to use them to make my building.

I will do my best to write code for each block and I will ask specific questions. I hope someone will help me
 
The two routines that you copied and pasted are to write an EEPROM. They need to be modified to,
Code:
/**This function use to single byte the DS1337 at desire address
*///Write Data to DS1337
void write_byte_to_DS1337(unsigned char addr,unsigned char byte)
{
    StartI2c();
    while(write_i2c(0xD0)==1)
        StartI2c();
    write_i2c(addr);
    write_i2c(byte);
    StopI2c();
}
/**
\brief of read_byte_from_DS1337 function.
This function use to read the data byte from DS1337 at the desire the address
*/
unsigned char read_byte_from_DS1337(unsigned char addr)
{
    unsigned char rxdata =0;
    StartI2c();
    while(write_i2c(0xD0)==1)
        StartI2c();
    write_i2c(addr);
    RepeatedStartI2c();
    write_i2c(0xD1);
    rxdata=read_i2c();
    SendNackBit();
    StopI2c() ;
    return rxdata;
}
Note, the prototypes will need changing too.
Also, the passed addr is the register address - not the device address.
Although, I'm not sure you'll understand any of the above. You really should try and understand the link I posted earlier.

Mike.
Edit, BTW, you stated you wanted pseudo code and you've ended up with processor (8051) specific code.
 
When I started with PIC16Fxxx mcu in the 2000's I found I2C was really difficult to get your head round, and even more difficult to trouble shoot, my old scope and the PK2 signal data mode helped a little, examples and libraries also didn't seem to port to the other PIC devices I had very well, if at all , was only when i dabbled in " ChipKit " it runs Arduino code :( and got a "Bus pirate" did i begin to 'enjoy' the I2C methods. , Then I wrote and developed my own drivers in C for PIC 16 18 24 ds33 master / slave work well just need to abide by the 'rules' and time constraints ( Khz) plus a good understanding of the data sheets..
Probably not the best code structure in the world !
RTC is DS1337

C:
void RTC_read_time()
{
        char Minutes;
        char Hours;
        I2C_start_W(RTC_addr);   // for write
        I2C_sendB(0);
        I2C_endtx();
        
        I2C_start_R(RTC_addr);
        I2C1CONbits.RCEN = 1;
        while (!I2C1STATbits.RBF);
        Seconds = I2C1RCV;
        
        I2CAck();
        I2C1CONbits.RCEN = 1;
        while (!I2C1STATbits.RBF);
        Minutes = I2C1RCV;
        I2CAck();
        I2C1CONbits.RCEN = 1;
        while (!I2C1STATbits.RBF);
        Hours = I2C1RCV;
        I2CNak();
        I2C_endtx();
        I2C1CONbits.RCEN = 0;
       // am or pm
        BCD2ascii( Minutes );
        time[4]= bcdlow;
        time[3]= bcdhi;
        time[2]= ':';
        BCD2ascii( Hours );
        time[1]= bcdlow;
        time[0]= bcdhi;
        Text2Frame(Cur_Frame,7,80,NNV,time);
}
 
Edit, BTW, you stated you wanted pseudo code and you've ended up with processor (8051) specific code.
Hi Mike. Thanks to coming back

My purpose is just to understand the process of i2c communication. That's why i was trying to make pseudo code only

I am still assuming that this is pseudo code. I haven't compiled code yet so There may have small errors and so If i'm using 8051 then it won't hurt anything. I think once pseudo code is made, I will not have much problem to write actual code.

Although, I'm not sure you'll understand any of the above. You really should try and understand the link I posted earlie
This is my attempt for my understanding. Please Look at main function and ignore syntax error in pseudo code
C:
#include <reg51.h>

#define I2C_DELAY    50
#define TOGGLE_LED  20000

#define device_addrW  0xD0 //device address with write 1101 0000
#define device_addrR  0xD1  //device address with Read  1101 0001

#define ACK_BIT    0

sbit SDA_BUS = P2^0;     //Define the Pin for the I2c and lec
sbit SCL_BUS = P2^1;
sbit Led = P3^0;

void InitI2c(void);   //Initializing I2C Bus Communication
void StartI2c(void); //Start Condition for I2C Communication
void RepeatedStartI2c(void); ////ReStart Condition for I2C Communication
void StopI2c(void);  //Stop Condition For I2C Bus
void SendAckBit(void);  //ACK for I2C Bus
void SendNackBit(void); //NAK for I2C Bus
void delay(unsigned int); //Delay
bit write_i2c(unsigned char Data); //Sending Data to slave on I2C bus
unsigned char read_i2c(void); //Receiving Data from slave on I2C bus
void write_byte_to_DS1337(unsigned char addr,unsigned char byte) //Write Data to DS1337
unsigned char read_byte_from_DS1337(unsigned char addr) //Read Data from DS1337

/**This function provide the delay which is used in clock generation.
*/
void delay(unsigned int d)
{
    unsigned int i;
    for(i=0; i<d; i++);
}
/**This function  use to make the data line and clock line idle to put the both line high
*/
void InitI2c(void)
{
    SDA_BUS =1;
    SCL_BUS =1;
}
/**This function performs the start operation to initiate the communication.
*/
void StartI2c(void)
{
    SDA_BUS  = 1;
    SCL_BUS  = 1;
    delay(I2C_DELAY);
    SDA_BUS  = 0;
    delay(I2C_DELAY);
}
/**When master does not want to relaese the control from the bus then it assert the repeated
start condition on the i2c bus.
*/
void RepeatedStartI2c()
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 1;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY/2);
    SDA_BUS  = 0;
    delay(I2C_DELAY);
}
/**When master want to stop the communication then it will assert the stop condition to the i2c bus.
*/
void StopI2c(void)
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 0;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY/2);
    SDA_BUS  = 1;
    delay(I2C_DELAY);
}
/**This function use to send the acknoledgement(ACK) bit the i2c bus.
*/
void SendAckBit()
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 0;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY);
}
/**This function use to send the Non-acknoledgement(NACK) bit the i2c bus.
*/
void SendNackBit(void)
{
    SCL_BUS  = 0;
    delay(I2C_DELAY/2);
    SDA_BUS  = 1;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY);
}
/**This function use to send signle byte to the I2C Data Bus*/
bit write_i2c(unsigned char byte)
{
    unsigned char i;
    for(i=0; i<8; i++)
    {
        SCL_BUS  = 0;
        delay(I2C_DELAY);
        if((byte<<i)&0x80)
            SDA_BUS  = 1;
        else
            SDA_BUS  = 0;
        delay(I2C_DELAY/2);
        SCL_BUS  = 1;
        delay(I2C_DELAY);
    }
//ack from slave //
    SCL_BUS  = 0;
    SDA_BUS  = 0;
    delay(I2C_DELAY/2);
    SCL_BUS  = 1;
    delay(I2C_DELAY);
    return SDA_BUS;
}

/**This function use to single byte the DS1337 at desire address
*///Write Data to DS1337
void write_byte_to_DS1337(unsigned char addr,unsigned char byte)
{
    StartI2c();
    while(write_i2c(0xD0)==1)
        StartI2c();
    write_i2c(addr);
    write_i2c(byte);
    StopI2c();
}
/**
\brief of read_byte_from_DS1337 function.
This function use to read the data byte from DS1337 at the desire the address
*/
unsigned char read_byte_from_DS1337(unsigned char addr)
{
    unsigned char rxdata =0;
    StartI2c();
    while(write_i2c(0xD0)==1)
        StartI2c();
    write_i2c(addr);
    RepeatedStartI2c();
    write_i2c(0xD1);
    rxdata=read_i2c();
    SendNackBit();
    StopI2c() ;
    return rxdata;
}

// Main function
void main(void)
{

    unsigned char rxbyte=0;

    unsigned char seconds = 0x00;
    unsigned char minutes = 0x00;
    unsigned char hours = 0x00;

    unsigned char addr_ seconds = 0x00;
    unsigned char addr_minutes = 0x01;
    unsigned char addr_hours = 0x01;

    Led  = 0;
    SDA_BUS = 0;
    SCL_BUS = 0;
 
  /* Init i2c ports first */
    InitI2c();

/* Send slave address and byte  */
    write_byte_to_DS1337(0x00,  seconds); //pass address of register and data   ie address of second register is 0x00 and seconds value is 0x00;
    write_byte_to_DS1337(0x01,  minutes); //pass address of register and data   ie address of minute register is 0x01 and minutes value is 0x00;
    write_byte_to_DS1337(0x02,  hours); //pass address of register and data   ie address of minute register is 0x01 and minutes value is 0x00;

/*read data from address registers*/
    read_byte_from_DS1337(unsigned char addr_ seconds)// pass address of register ie. address of seconds register is 0x00. we are reading data stored at address 0x00
    read_byte_from_DS1337(unsigned char addr_ minutes)// pass address of register ie. address of minutes register is 0x01. we are reading data stored at address 0x01
    read_byte_from_DS1337(unsigned char addr_ hours)// pass address of register ie. address of hours register is 0x02. we are reading data stored at address 0x02

}
 
Last edited:
This is my attempt for my understanding. Please Look at main function and ignore syntax error in pseudo code
Calling it pseudo code does not make it pseudo code - it's C and specifically for the 8051 - it's not even portable. And you will not learn anything from randomly changing copied code. Read the page I posted a link to and you may start to understand IIC.

Mike.
 
Calling it pseudo code does not make it pseudo code - it's C and specifically for the 8051 - it's not even portable. And you will not learn anything from randomly changing copied code. Read the page I posted a link to and you may start to understand IIC.

Mike.

I agree with you, Sample code can not help in writing real code, but it can give me an idea to understand communication process.

I started thread with a datasheet, then came to the pseudo code and now I will try to write real code.

But before that I have only two questions

Does main function make any sense ?

Am i setting register value correctly ?

Code:
    unsigned char seconds = 0x00;
    unsigned char minutes = 0x00;
    unsigned char hours = 0x00;

Register zero contains the seconds and can only contain values between 0 and 59. It means it can only store decimal number from 0 to 59
 
There's no need to store constants in memory, instead use #define addr_seconds 0x00 - note, no semicolon or equals sigh.
When you call the read function it returns a value which you should use in some way - maybe print it print(read_byte_from_DS1337(addr_ seconds));
All the registers in the chip are in BCD format - I suggest you read up on BCD.

Mike.
Edit, maybe I should follow DrG example and take a step back.
 
Status
Not open for further replies.

Latest threads

Back
Top