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

Routine to read DS1307

Status
Not open for further replies.

Parth86

Member
I don't understand in programming how to read DS1307. MCU 8051

This is my understanding to read DS1307
upload_2017-10-24_15-2-8.png
Basic steps
Start condition

7 Bit slave address + Read operation
After sending the 8 bits (7 address +R/W) the master generate Acknowledge
Slave ACKs indicate it got the data and the master can continue

Master Send Register address
After sending the register address master generate Acknowledge
Slave ACKs indicate it got the data and the master can continue

Master Send Data
After sending Data master generate Acknowledge
Slave NAKs indicate it wants no more data.

Stop Condition

I need routines to generate Start, Re Start, Stop conditions, read I2C, write I2C, check ACK or NAK and generate ACK or NAK.

I understand Start, stop Restart, ACK, NAK routine

C:
#define   SDA       P0_0
#define   SCL       P0_1
void I2CInit()
{
       SDA = 1;
       SCL = 1;
}
void I2CStart()
{
      SDA = 0;
      SCL = 0;
}
void I2CRestart()
{
     SDA = 1;
     SCL = 1;
     SDA = 0;
     SCL = 0;
}
void I2CStop()
{
     SCL = 0;
     SDA = 0;
     SCL = 1;
     SDA = 1;
}
void I2CAck()
{
     SDA = 0;
     SCL = 1;
     SCL = 0;
     SDA = 1;
}
void I2CNak()
{
    SDA = 1;
    SCL = 1;
    SCL = 0;
    SDA = 1;
}
Now I am looking help to make two routines

I2CSend(unsigned char Data)
Read_DS1307(void)

How to make these two routines ?
 

Attachments

Last edited:

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Just copy my routines.... They work and have been designed for that chip!!

Whoooh!!! I just remembered... I used asm within C for that tutorial..

Here are some C routines
C:
#define SDA P2_7       /* Set P2.7 = SDA */
#define SCL P2_6       /* Set P2.6 = SCL */
#define I2C_DELAY 0x0F   /* For delay i2c bus */

void I2C_delay(void)
{
   unsigned char i;

   for(i=0; i<I2C_DELAY; i++);
}

void I2C_clock(void)
{
   I2C_delay();
   SCL = 1;       
   I2C_delay();
   SCL = 0;       
}

void I2C_start(void)
{
   if(SCL)
   SCL = 0;       
   SDA = 1;      
   SCL = 1;       

   I2C_delay();
   SDA = 0;       
   I2C_delay();
   SCL = 0;        
}

void I2C_stop(void)
{
   if(SCL)
   SCL = 0;         
   SDA = 0;           
   I2C_delay();
   SCL = 1;        
   I2C_delay();
   SDA = 1;        
}

bit I2C_write(unsigned char dat)
{
   bit data_bit;
   unsigned char i;

   for(i=0;i<8;i++)               // For loop 8 times (send data 1 byte) 
   {
       data_bit = dat & 0x80;       //  Just  MSB bit  
       SDA = data_bit;               // Send data_bit to SDA 
       I2C_clock();                
       dat = dat<<1;
   }

   SDA = 1;           // Set SDA 
   I2C_delay();
   SCL = 1;           // Set SCL 
   I2C_delay();
   data_bit = SDA;       // Check acknowledge
   SCL = 0;           // Clear SCL 
   I2C_delay();
   return data_bit;   
}

unsigned char I2C_read(void)
{
   bit rd_bit;
   unsigned char i, dat;

   dat = 0x00;
   for(i=0;i<8;i++)       // For loop read data 1 byte 
   {
       I2C_delay();
       SCL = 1;         
       I2C_delay();
       rd_bit = SDA;    
       dat = dat<<1;
       dat = dat | rd_bit;  
       SCL = 0;        
   }

   return dat;
}

void I2C_ack()
{
   SDA = 0;      
   I2C_delay();
   I2C_clock();   
   SDA = 1;      
}

void I2C_noack()
{
   SDA = 1;      
   I2C_delay();
   I2C_clock();   
   SCL = 1;       
}
 

Parth86

Member
Why There is no restart routine ?
What is 0x80 ? what is purpose of this hex value ?
0x80 hex = 1000 0000 binary

I have just modified your routine. Does this make sense ?
C:
#define     SDA       P2_7       /* Set P2.7 = SDA */
#define     SCL       P2_6       /* Set P2.6 = SCL */

void I2C_Delay( unsigned long wait )
{
      unsigned i;
     for(  i  =  0 ;   i  <  wait;   i++ )
     {
        }
}

void I2C_Init(void)
{   
   // Make SDA and SCK pins input initially
   SDA  =  1;
   SCL   =  1;
}

void I2C_start(void)
{     
    SDA  =  1;     
    SCL   =  1;     

   I2C_Delay();
   SDA  =  0;     
   I2C_delay();
   SCL  =  0;       
}
void I2C_Restart(void)
{     
    SCL  =  0;
    I2C_Delay();
    SDA  =  1;
    I2C_Delay();   
    SCL  =  1;     
    I2C_Delay();
   SDA  = 0;     
   I2C_delay();         
}

void I2C_stop(void)
{
   SCL  =  0;
   I2C_delay();   
   SDA  =  0;
   I2C_delay();   
   SCL  =  1;       
   I2C_delay();
   SDA  = 1;
   I2C_delay();   
}

void I2C_ACK(void)
{
   SCL  =  0;     
   I2C_delay();   
   SDA  =  0;
   I2C_delay();   
    SCL  =  1;
    I2C_delay();   
}
void I2C_NACK(void)
{  
    SCL = 0;     
    I2C_delay();   
    SDA = 1;
    I2C_delay();   
    SCL = 1;
    I2C_delay();           
}

bit I2C_write(unsigned char dat)
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Why There is no restart routine ?
Restart is only needed at a higher level... It's used to read from the RTC... All those routines are low level..

read routine...

send rtc address
wait for ack
send internal address
wait for ack
send restart
wait for ack
send read command (RTC address + 1)
wait for ack
read data
-> a) send ack if you want more data and loop here.
->b) send nack if you are done.
send stop.

write routine...
send rtc address
wait for ack
send internal address
wait for ack
send data
wait for ack
send stop.

What is 0x80 ? what is purpose of this hex value ?
0x80 hex = 1000 0000 binary
When shifting its much easier to test the MSBit... if (your_byte & 0x80) <- test if the SDA line is high or low.. Remember you are shifting the highest bit out first, then rotating all bits out along the serial wire..
 

Parth86

Member
Can I implement with my routine ? later I will work with your routine? what do you think ?

Why there is only 0x80 ? any special reason ?
 

Parth86

Member
read routine...
send rtc address
wait for ack
send internal address
wait for ack
send restart
wait for ack
send read command (RTC address + 1)
wait for ack
read data
-> a) send ack if you want more data and loop here.
->b) send nack if you are done.
send stop.

write routine...
send rtc address
wait for ack
send internal address
wait for ack
send data
wait for ack
send stop.

.
Thanks for making table. I want to ask How to complete those two routine with your routine or mine ?. I want to use mine because I feel comfortable with it. What do you think ?
 
Last edited:

Parth86

Member
Hi
Please see below program. the last two routines are incomplete. How to implement them
C:
#include<reg51.h>

/*Data pin for i2c */
sbit SDA = P0^0; 

/*clock pin for i2c */
sbit SCL = P0^1;       

#define SDA_Low               0
#define SDA_High              1

#define SCL_Low               0
#define SCL_High              1

void I2C_Delay(unsigned long wait);

void I2C_Delay(unsigned long wait)
{
   unsigned int i;
 
   for(i = 0; i < wait; i++ )
   {
     
   }
}

void I2C_Init(void)
{
   SDA = SDA_High;
  SCL = SCL_High;
}

void I2C_start(void)
{
     SDA = SDA_High; 
    SCL = SCL_High;     
     I2C_Delay(20);
     SDA = SDA_Low; 
    I2C_Delay(20);
    SCL = SCL_Low;
}

void I2C_Restart(void)
{
     SCL = SCL_Low;
    I2C_Delay(20);
    SDA = SDA_High;
    I2C_Delay(20);
    SCL = SCL_High; 
    I2C_Delay(20);
    SDA = SDA_Low; 
    I2C_Delay(20);
}


void I2C_stop(void)
{
   SCL = SCL_Low;
   I2C_Delay(20);
   SDA = SDA_Low;
   I2C_Delay(20);
   SCL = SCL_High;   
   I2C_Delay(20);
   SDA = SDA_High;
   I2C_Delay(20);
}

void I2C_ACK(void)
{
   SCL = SCL_Low; 
   I2C_Delay(20);
   SDA = SDA_Low;
   I2C_Delay(20);
   SCL = SCL_High;
   I2C_Delay(20);
}
void I2C_NACK(void)
{
   SCL = SCL_Low; 
   I2C_Delay(20);
   SDA = SDA_High;
   I2C_Delay(20);
   SCL = SCL_High;
   I2C_Delay(20);       
}

bit I2C_write(unsigned char Byte)
{
   bit ack_bit;
   unsigned char i;

   for(i=0;i<8;i++)         
   {
       ack_bit = Byte & 0x80;       
       SDA = ack_bit;           
       SCL = SCL_High;
       SCL = SCL_Low;      
       Byte = Byte<<1;
   }

   SDA = SDA_High;       
   I2C_Delay(20);
   SCL = SCL_High;       
   I2C_Delay(20);
   ack_bit = SDA;     
   SCL = SCL_Low;       
   I2C_Delay(20);
   return ack_bit;
}

unsigned char I2C_read(void)
{
   bit rd_bit;
   unsigned char i, Byte;

   Byte = 0x00;
   for(i=0;i<8;i++)     
   {
       I2C_Delay(20);
       SCL = SCL_High;     
       I2C_Delay(20);
       rd_bit = SDA; 
       Byte = Byte<<1;
       Byte = Byte | rd_bit;
       SCL = SCL_Low;     
   }

   return Byte;
}
unsigned int Read_DS1307(void)
{
  /* program for this routine */
}
unsigned int Write_DS1307(void)
{
    /* program for this routine */
}
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top