Sir, I am trying to write 34 into the eeprom at address location 0x0000, but whenever I read and dislpay it on lcd, 49 is displayed. please help me.
my code
sbit SCL=P3^7; // Port pin for SCL line sbit SDA=P3^6; // Port pin for SDA line
void i2c_delay(void); // I2C Clock delay void i2c_start(void); // Generates a I2C Start condition void i2c_stop(void); // Generates a I2C Stop condition void i2c_wbyte(char i2c_wb); // Writes a single byte from I2C Slave unsigned char i2c_rbyte(void); // Reads and returns a single byte from I2C Slave char i2c_ack(void); void i2c_nack(void); void i2c_write(char id, char add,char dat); unsigned char i2c_read(char id,char add);
void i2c_delay(void) { char a; for(a=0;a<80;a++); }
void i2c_start(void) { SCL = 1; i2c_delay(); SDA = 1; i2c_delay(); SDA = 0; i2c_delay(); SCL = 0; i2c_delay(); }
void i2c_stop(void) { //SDA_Dir = 1; //SDA pin as output SDA = 0; i2c_delay(); SCL = 1; i2c_delay(); SDA = 1; i2c_delay(); SCL = 0; }
void i2c_wbyte(unsigned char i2c_wb) { char a; //DA_Dir = 1; // Set SDA pin as output for(a=0;a<8;a++) // Send 8 bits { SCL = 0; i2c_delay(); if(i2c_wb & (0x80 >> a)) { SDA = 1; } else { SDA = 0; } i2c_delay(); SCL = 1; i2c_delay(); }
}
unsigned char i2c_rbyte(void) { char a; unsigned char b; b=0; //SDA_Dir = 0; // Set SDA pin as input for(a=0;a<8;a++) { SCL = 1; i2c_delay(); if(SDA) { b |= (0x80 >> a); // Set data bit on SDA line } i2c_delay(); SCL = 0; i2c_delay(); } return(b); } char i2c_ack(void) { char a; //SDA_Dir = 1; // Set SDA pin as output i2c_delay(); SCL = 0; i2c_delay(); SDA = 1; i2c_delay(); SCL = 1; i2c_delay();
//SDA_Dir = 0; // Set SDA pin as input i2c_delay(); a = SDA; i2c_delay(); SCL = 0; i2c_delay(); return(a); }
void i2c_nack(void) { //SDA_Dir = 1; // Set SDA pin as output SDA = 1; i2c_delay(); SCL = 1; i2c_delay(); SCL = 0; i2c_delay(); } void i2c_write(unsigned char id, unsigned char add, unsigned char dat) { i2c_start(); i2c_wbyte(id); i2c_ack(); i2c_wbyte(add); i2c_ack(); i2c_wbyte(dat); i2c_ack(); i2c_stop(); }
unsigned char i2c_read(unsigned char id,unsigned char add) { unsigned char rd; i2c_start(); i2c_wbyte(id); i2c_ack(); i2c_wbyte(add); i2c_ack(); i2c_start(); i2c_wbyte((id|0x01)); i2c_ack(); rd = i2c_rbyte(); i2c_nack(); i2c_stop(); return(rd); } main() { unsigned char v=34; unsigned char dat=0; i2c_write(0xA0,0x0000,v); dat=i2c_read(0xA0,0x0000); send2lcd(dat); } the delay between read and write correct? the delay between scl and sda line, is ok? please help me
thanks in advance
The I2C protocol is well defined by Philips/NXP, and every datasheet of a device like the 24C04 mentioned earlier describes the established method to access, read and write.
The START condition might look like this in a single master system
// If you decide to check for errors on I2C protocol, some changes are neccessary // either by return value or by set/clear bits on a global variable void i2c_start(void) { SCL = 0; // Hold the bus i2c_delay(); SDA = 1; // Release SDA, SDA changes when SCL=0 (otherwise is a START or STOP condition) i2c_delay(); // if (SDA==0) // return (I2C_START_ERR1); SCL = 1; // Release SCL line i2c_delay(); // if (SCL==0) // return (I2C_START_ERR2); SDA = 0; // Create START contition SDA 1->0 while SCL=1 i2c_delay(); SCL = 0; // Hold the I2C bus i2c_delay(); // return (I2C_START_OK); }
The i2c_delay is too much, but that depends on system XTAL and cocking 1, 6, 12. Better to be formed using some NOP suited for the speed of the mcu. If you construct a similar i2c_stop then you have a chance to do more.
I want to write 34 into eeprom 24c04 at location 0x0000,read it and display it on lcd. but it is displaying 49 on lcd. I dont know what is the mistake? please check the following
1)i2c_delay() 2)i2c_start and stop 3)i2c_read and write or any other step. . .
void i2c_stop(void) { SDA = 0; i2c_delay(); SCL = 1; i2c_delay(); SDA = 1; i2c_delay(); SCL = 0; }
void i2c_wbyte(unsigned char i2c_wb) { char a; for(a=0;a<8;a++) // Send 8 bits { SCL = 0; i2c_delay(); if(i2c_wb & (0x80 >> a)) { SDA = 1; } else { SDA = 0; } i2c_delay(); SCL = 1; i2c_delay(); } }
unsigned char i2c_rbyte(void) { char a; unsigned char b; b=0; //SDA_Dir = 0; // Set SDA pin as input for(a=0;a<8;a++) { SCL = 1; i2c_delay(); if(SDA) { b|= (0x80 >> a); // Set data bit on SDA line } i2c_delay(); SCL = 0; i2c_delay(); } return(b); }
char i2c_ack(void) { char a; //SDA_Dir = 1; // Set SDA pin as output i2c_delay(); SCL = 0; i2c_delay(); SDA = 1; i2c_delay(); SCL = 1; i2c_delay(); //SDA_Dir = 0; // Set SDA pin as input i2c_delay(); a = SDA; i2c_delay(); SCL = 0; i2c_delay(); return(a); }
void i2c_nack(void) { //SDA_Dir = 1; // Set SDA pin as output SDA = 1; i2c_delay(); SCL = 1; i2c_delay(); SCL = 0; i2c_delay(); }
void i2c_write(unsigned char id, unsigned char add, unsigned char dat) { i2c_start(); i2c_wbyte(id); i2c_ack(); i2c_wbyte(add); i2c_ack(); i2c_wbyte(dat); i2c_ack(); i2c_stop(); }
unsigned char i2c_read(unsigned char id,unsigned char add) { unsigned char rd; i2c_start(); i2c_wbyte(id); i2c_ack(); i2c_wbyte(add); i2c_ack(); i2c_start(); i2c_wbyte((id|0x01)); i2c_ack(); rd = i2c_rbyte(); i2c_nack(); i2c_stop(); return(rd); }
main() { unsigned char v=34; unsigned char dat=0; i2c_write(0xA0,0x0000,v); dat=i2c_read(0xA0,0x0000); send2lcd(dat); } the delay between read and write correct? the delay between scl and sda line, is ok? please help me
Code must be posted in <_pre_> and <_/pre> (without underscore) like this
...
Try to post correct your code. It is to difficult to reformat so anyone can read this
I want to write 34 into eeprom 24c04 at location 0x0000,read it and display it on lcd. but it is displaying 49 on lcd. mcu I am using is 89V51RD2.I dont know what is the mistake? please check the following
#include<reg51.h> sbit SCL=P3^7; // Port pin for SCL line sbit SDA=P3^6; // Port pin for SDA line void i2c_delay(void); // I2C Clock delay void i2c_start(void); // Generates a I2C Start condition void i2c_stop(void); // Generates a I2C Stop condition void i2c_wbyte(char i2c_wb); // Writes a single byte from I2C Slave unsigned char i2c_rbyte(void); // Reads and returns a single byte from I2C Slave char i2c_ack(void); void i2c_nack(void); void i2c_write(char id, char add,char dat); unsigned char i2c_read(char id,char add); void i2c_delay(void) { char a; for(a=0;a<80;a++); } void i2c_start(void) { SCL = 1; i2c_delay(); SDA = 1; i2c_delay(); SDA = 0; i2c_delay(); SCL = 0; i2c_delay(); }<_/pre> void i2c_stop(void) { SDA = 0; i2c_delay(); SCL = 1; i2c_delay(); SDA = 1; i2c_delay(); SCL = 0; } void i2c_wbyte(unsigned char i2c_wb) { char a; for(a=0;a<8;a++) // Send 8 bits { SCL = 0; i2c_delay(); if(i2c_wb & (0x80 >> a)) { SDA = 1; } else { SDA = 0; } i2c_delay(); SCL = 1; i2c_delay(); } } unsigned char i2c_rbyte(void) { char a; unsigned char b; b=0; //SDA_Dir = 0; // Set SDA pin as input for(a=0;a<8;a++) { SCL = 1; i2c_delay(); if(SDA) { b|= (0x80 >> a); // Set data bit on SDA line } i2c_delay(); SCL = 0; i2c_delay(); } return(b); } char i2c_ack(void) { char a; //SDA_Dir = 1; // Set SDA pin as output i2c_delay(); SCL = 0; i2c_delay(); SDA = 1; i2c_delay(); SCL = 1; i2c_delay(); //SDA_Dir = 0; // Set SDA pin as input i2c_delay(); a = SDA; i2c_delay(); SCL = 0; i2c_delay(); return(a); } void i2c_nack(void) { //SDA_Dir = 1; // Set SDA pin as output SDA = 1; i2c_delay(); SCL = 1; i2c_delay(); SCL = 0; i2c_delay(); } void i2c_write(unsigned char id, unsigned char add, unsigned char dat) { i2c_start(); i2c_wbyte(id); i2c_ack(); i2c_wbyte(add); i2c_ack(); i2c_wbyte(dat); i2c_ack(); i2c_stop(); } unsigned char i2c_read(unsigned char id,unsigned char add) { unsigned char rd; i2c_start(); i2c_wbyte(id); i2c_ack(); i2c_wbyte(add); i2c_ack(); i2c_start(); i2c_wbyte((id|0x01)); i2c_ack(); rd = i2c_rbyte(); i2c_nack(); i2c_stop(); return(rd); } main() { unsigned char v=34; unsigned char dat=0; i2c_write(0xA0,0x0000,v); dat=i2c_read(0xA0,0x0000); send2lcd(dat); }
the delay between read and write correct? the delay between scl and sda line, is ok? please help me
The START operation in I2C specifies the begin of a transaction, wich ends with a STOP. While the transaction takes place there is a good practice to keep SCL low (0) between function calls, meaning the application is holding the bus for the time of the transaction. The STOP condition of course MUST leave setting the bus free (SCL=1, SDA=1)
The SDA can change only when SCL is low(0), otherwise this is a START or STOP contition.
Have you noticed that 24C04 requires 9 bit address because it has 4Kbits as 512byte x8 bits to represent a range of 0 (hex=0x00) to 511 (hex=0x1FF) a 9bit number is needed. So, there must be a function i2c_waddr(unsigned int adr) defined, declared and used for the 9bit address of the device.
Use the mentioned posted paradigm for the START step, begins holding the bus, creates the START condition, and leaves with the bus on hold because the transaction has not ended yet.
The i2c_delay has to provide for a delay of 3-5 us (microseconds), so the XTAL used and the clocking 1, 6, 12 of the microcontroller play role. Even a few __NOP__ are enough.
Keep these in mind and restrucure your program code.
Once more we see someone who posts the code without proper tags.
Then when asked to use the tags copies the already broken code from the previous post, and repost it again. All the time without noticing that the result is broken this time too.
What have happened to society? Own thinking?
Spenting too much time on forums, in front of a computer screen makes life boring. The are other fields to spend energy.
#include <reg51.h> #include "_LCD_R8C.c" #define INPUT_LENGTH 11 int main() { char input[INPUT_LENGTH]; /* The input from the serial port */ int input_pos = 0; /* Current position to write in the input buffer */ lcd_init(); lcd_clear(); SCON = 0x50; TMOD = 0x20; /* timer 1, mode 2, 8-bit reload */ TH1 = 0xFD; /* reload value for 2400 baud */ TR1 = 1; TI = 1; RI = 1; while(1) { /* read the next character from the serial port */ if(input_pos < INPUT_LENGTH) /* check for buffer overflow */ { input[input_pos] = getCharacter(); lcd_print_b(input[input_pos]); /* only makes sense to print each character once */ input_pos++; } } char getCharacter (void) { char chr /* variable to hold the new character */ while (RI != 1) ; chr = SBUF; RI = 0; return(chr); }
i am getting display as 255... help me out... here while(1) making any problem
So why did you jump into your old thread about i2c suddenly?
And why do you continue to #include a C file despite having been told not to?
The i2c_delay is too much, can't be. by the standard if your delay is even years, the bus will still work.
Erik
So why did you jump into your old thread about i2c suddenly? and why did you not see what happened using your? (intentional question mark) LCD routines to display a constant to DIVIDE AND CONQUER.
I am getting a suspicion that you threw some code collected from the internet together and have no idea how to make it work.
More of an FYI and not so much a "I wouldn't do". I have seen too many times where people just don't pay attention to when the posts were created. I agree the information is useful. Could just be me as well, As a Mod on another unrelated board thread res there is an issue.
In this case, the thread is about I2C and the recent poster have completely different problems. And already have ongoing threads.
What are you trying to say?
Hi, is there a I2C robust library? similar as the RL_FlashFS/RL_USB, etc... If the answer is NO, then is it possible to write such a library?
is there a I2C robust library? probably; however, most users of such do not take into consderation the differences between the "I2C robust library" and their application (pins/clock speed/...) and then complain that it is not 'robust'.
WHY ON EARTH do people still do bit-banging I²C when there are legio derivatives with I²C hardware?
is it possible to write such a library? sure, with the above caveats.