1. 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.
    Dismiss Notice

Routine to read DS1307

Discussion in 'Microcontrollers' started by Parth86, Oct 24, 2017.

  1. Parth86

    Parth86 Member

    Joined:
    Dec 25, 2011
    Messages:
    538
    Likes:
    5
    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

    Code (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 ?
     

    Attached Files:

    Last edited: Oct 24, 2017
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,251
    Likes:
    911
    Location:
    Rochdale UK
    Are you using a chip with I2C on?... If you are using software routines... My tutorials already do I2C..
     
  3. Parth86

    Parth86 Member

    Joined:
    Dec 25, 2011
    Messages:
    538
    Likes:
    5
    I am planning to interface ds1307 with 8051. I have seen your tutorial but still having problem to implement these two routines ?
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,251
    Likes:
    911
    Location:
    Rochdale UK

    Let me explain.... Hardware I2C or Software I2C... What chip are you using?
     
  6. Parth86

    Parth86 Member

    Joined:
    Dec 25, 2011
    Messages:
    538
    Likes:
    5
    I think 8051 doesn't have inbuilt i2c chip so I will use software I2C. let suppose I will have 8051 , Ds1307 , crystal ,caps resistors .. then how to do it?
     
  7. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,251
    Likes:
    911
    Location:
    Rochdale UK
    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
    Code (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;      
    }
     
     
  8. Parth86

    Parth86 Member

    Joined:
    Dec 25, 2011
    Messages:
    538
    Likes:
    5
    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 ?
    Code (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)
     
     
  9. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,251
    Likes:
    911
    Location:
    Rochdale UK
    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.

    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..
     
  10. Parth86

    Parth86 Member

    Joined:
    Dec 25, 2011
    Messages:
    538
    Likes:
    5
    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 ?
     
  11. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,251
    Likes:
    911
    Location:
    Rochdale UK
    upload_2017-10-25_15-59-46.png
    Its a mask to determine what gets transmitted..
     
    • Like Like x 1
  12. Parth86

    Parth86 Member

    Joined:
    Dec 25, 2011
    Messages:
    538
    Likes:
    5
    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: Oct 25, 2017
  13. Parth86

    Parth86 Member

    Joined:
    Dec 25, 2011
    Messages:
    538
    Likes:
    5
    Hi
    Please see below program. the last two routines are incomplete. How to implement them
    Code (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 */
    }

     
     

Share This Page