I2c bit banging, AT89C55WD, EEPROM BL24C04 interfacing - Page 1
Forum section: electronics / beginners

author: Vindhyachal.takniki
author_rank: Frequent Contributor
timestamp: April 16, 2016, 03:53:03 pm
content: 1. I am using AT89C55WD(40 pin DIP), with 12Mhz crystal.Have to interface BL24C04 with it.2. System is +5V powered & I have made bit banging code in C for it.I have kept 50kbps speed. Took refereence from here while making code (http://saeedsolutions.blogspot.in/2012/10/pic16f84a-i2c-bit-banging-code-proteus.html)3. I have simualted code in proteus & seems to be working as values shown in its I2c debugger.4. One issue I think may be its very small delay. At 50kbps , 1 bit delay is 20us, half bit delay is 10us & quarter bit delay is 5us. In codeI have used nop statements for 10us & 5us.5. In link above, blogger has used quarter(5us)/half(10us) but delay at many places. I dont know why quarter(5us) bit delay is used. Below is code. Is it ok?Code: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_();void all_tasks_manager(void){uint8_t temp;i2c_init();/* write to eeprom */i2c_start();while( 1U == i2c_write_byte(0xa0U) ){i2c_start();}/* address */i2c_write_byte(0x00U);/* value */i2c_write_byte(0x05U);/* stop */i2c_stop();wait_delay_us(50000);/* write to eeprom */i2c_start();while( 1U == i2c_write_byte(0xa0U) ){i2c_start();}/* address */i2c_write_byte(0x00U);i2c_restart();i2c_write_byte(0xa1U);temp = i2c_read_byte();i2c_send_nack();i2c_stop();while(1);} /* function ends here */void i2c_init(void){sda = 1U;scl = 1U;}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();}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();}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();}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();}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();}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;}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;}

author: Vindhyachal.takniki
author_rank: Frequent Contributor
timestamp: April 18, 2016, 06:24:17 am
content: I have checked on hardware, MCU: AT89C55WD, 12Mhz crsytal & BL24C04.It is working.For me exact performance of 50kbps is not required, because I have to read it only once on startup & write only once.

author: Vindhyachal.takniki
author_rank: Frequent Contributor
timestamp: April 22, 2016, 08:23:33 am
content: 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.Code:/* 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);}/* 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 = i2c_read_byte();for(cnt = 1U ; cnt < no_bytes ; cnt++){i2c_send_ack();byte = 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;}

author: Vindhyachal.takniki
author_rank: Frequent Contributor
timestamp: April 22, 2016, 04:35:37 pm
content: yes got it. It has 2 pages of 256 bytes each. pages are selected in device address register bit.