I2c bit banging, AT89C55WD, EEPROM BL24C04 interfacing

Papabravo

Joined Feb 24, 2006
21,159
@Vindhyachal Takniki It depends on what your notion of correct is. Yours will be different than mine. If you're satisfied with it, then what difference does it make what I think. You don't need my seal of approval to go forth and be prosperous.
 

Thread Starter

Vindhyachal Takniki

Joined Nov 3, 2014
594
How byte addressing is done in 24C04 eeprom.
24C04 has 4K of eeprom, so byte address range 0 to 4095 i.e 0 to 0x0FFFH. So byte address require two bytes.
But here in Maxim app note, it only sends one byte to address the byte ( https://www.maximintegrated.com/en/app-notes/index.mvp/id/4649 ).
Foe example, if I have to write at address location 0x00, I should send two 0's.
Similarly for 4095 adress, I should send 0xff & 0xff.

But here codes works by sending one bytes only.

1. I have tested the code by sending one byte adress, & it is workign on hardware. I haven't tested by sending two byte address.
2. This is below codes for writing multiple bytes & reading back. Any comments/suggestions on it.
Performance wise I dont require to be exact 50kbps. Since I have to read/write only once at startup.

C:
/* AT89C55WD, 12Mhz crystal, 1us inst time */
sbit sda = P1^7;
sbit scl = P1^6;

#define i2c_speed_kbps     50
#define half_bit_delay_us  10     /* ( (1*1000000) / (i2c_speed_kbps*1000) )/ 2  */

#define delay_10us()       _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
#define delay_5us()        _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

#include "regx55.h"
#include "i2c.h"




static uint8_t eeprom_write_mutiple_bytes(uint8_t address , uint8_t byte[] , uint8_t no_bytes)
{
    uint8_t cnt;
    uint8_t cnt2;
    uint8_t err = 0U;
  
    cnt = 10U;
  
/* write to eeprom */
    i2c_start();
    while( (1U == i2c_write_byte(0xa0U)) && (--cnt) )
    {
    /* stop */  
        i2c_stop();       
    /* delay 100ms */  
        for(cnt2 = 0U ; cnt2 < 20U ; cnt2++)
        {
            wait_delay_us_complete(DELAY_10000_US_TH , DELAY_10000_US_TL);
        }      
      
        i2c_start();
    }
    if(0U == cnt)
    {
        err = 1U;
    }

/* if no error */  
    if(0U == err)
    {
    /* address */
        i2c_write_byte(address);
             
        for(cnt = 0U ; cnt < no_bytes ; cnt++)
        {
            (void)i2c_write_byte(byte[cnt]);
        }
      
    /* stop */  
        i2c_stop();      
      
    }

/* delay 100ms */  
    for(cnt = 0U ; cnt < 15U ; cnt++)
    {
        wait_delay_us_complete(DELAY_10000_US_TH , DELAY_10000_US_TL);
    }
  
    return err;
  
}





static uint8_t eeprom_read_mutiple_bytes(uint8_t address , uint8_t byte[] , uint8_t no_bytes)
{
    uint8_t cnt;
    uint8_t cnt2;
    uint8_t err = 0U;
  
    cnt = 10U;
  
/* write to eeprom */
    i2c_start();
    while( (1U == i2c_write_byte(0xa0U)) && (--cnt) )
    {
    /* stop */  
        i2c_stop();       
    /* delay 100ms */  
        for(cnt2 = 0U ; cnt2 < 20U ; cnt2++)
        {
            wait_delay_us_complete(DELAY_10000_US_TH , DELAY_10000_US_TL);
        }      
      
        i2c_start();
    }
    if(0U == cnt)
    {
        err = 1U;
    }

/* if no error */  
    if(0U == err)
    {
    /* address */
        i2c_write_byte(address);
      
    /* restart */
        i2c_restart();
      
        i2c_write_byte(0xa1U);
      
    /* address */  
        byte[0] = i2c_read_byte();
     
        for(cnt = 1U ; cnt < no_bytes ; cnt++)
        {
            i2c_send_ack();
            byte[cnt] = i2c_read_byte();
        }
      
    /* nack */
        i2c_send_nack();
      
    /* stop */  
        i2c_stop();      
      
    }

/* delay 100ms */  
    for(cnt = 0U ; cnt < 15U ; cnt++)
    {
        wait_delay_us_complete(DELAY_10000_US_TH , DELAY_10000_US_TL);
    }
  
    return err;
  
}


static void i2c_start(void)
{
    scl = 1U;
    sda = 1U;

/* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
    delay_10us();
  
    sda = 0U;
  
/* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
    delay_10us();

}




static void i2c_restart(void)
{
    scl = 0U;              
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
    sda = 1U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
    scl = 1U;

/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();

    sda = 0U;

/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();

}




static void i2c_stop(void)
{
    scl = 0U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();

    sda = 0U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
    scl = 1U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
    sda = 1U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
}




static void i2c_send_ack(void)
{
    scl = 0U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
    sda = 0U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
    scl = 1U;
  
/* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
    delay_10us();
  
}




static void i2c_send_nack(void)
{
    scl = 0U;

/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();  
  
    sda = 1U;
  
/* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
    delay_5us();
  
    scl = 1U;
  
/* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
    delay_10us();
  
}




static uint8_t i2c_write_byte(uint8_t byte)
{
    uint8_t cnt;
      
    for(cnt = 0U ; cnt < 8U ; cnt++)
    {
        scl = 0U;
    /* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
        delay_5us();
      
      
        if( (byte << cnt) & 0x80U )
        {
            sda = 1U;
        }
        else
        {
            sda = 0U;
        }  

    /* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
        delay_5us();
      
        scl = 1U;
      
    /* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
        delay_10us();
    }
      
/* get ack from slave */
    scl = 0U;
    sda = 1U;
  
/* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
    delay_10us();
  
    scl = 1U;
  
/* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
    delay_10us();

    return sda;

}




static uint8_t i2c_read_byte(void)
{
    uint8_t cnt;
    uint8_t rxdata = 0U;
    uint8_t temp;
  
    for(cnt = 0U ; cnt < 8U ; cnt++)
    {
        scl = 0U;
        sda = 1U;
      
    /* half bit delay for 50kbps which is 10us for 12Mhz it is 10 nops */  
        delay_10us();    
      
        scl = 1U;
      
    /* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
        delay_5us();
      
        temp = sda;
        rxdata = rxdata | (temp << (7U - cnt));  
      
    /* half bit delay/2 for 50kbps which is 5us for 12Mhz it is 5 nops */  
        delay_5us();
      
    }
    return rxdata;                      

}
Moderators note : please use code tags for the used language
 
Last edited by a moderator:

Papabravo

Joined Feb 24, 2006
21,159
You did not read your datasheet carefully. The 4K of 24C04 refers to the number of bits. So 4K bits divided by 8 gives 512 bytes. One of the bits in the device address byte is the page selector (one of 2, 256 byte pages). You need to spend more time with datasheets to develop your skills. It is one thing that does not come quick and easy. The next time you have a question like this I suggest you start with the default assumption that the chip makers really really know what they are doing and you just have to keep looking until you find the answer. Trust me it will make you a much better engineer.
 
Top