??? 02/26/09 12:48 Read: times |
#162884 - code update Responding to: ???'s previous message |
Here is the program. I have implemented byte/sequential read/write operations and current read operation. Now it is reading the first two bytes of the test string.
#define SCL P1_6 #define SDA P1_7 #define EEPROM_READ_ADDR 0XA1 #define EEPROM_WRITE_ADDR 0XA0 #define HIGH 1 #define LOW 0 #define ACK LOW #define NACK HIGH #define SUCCESS HIGH #define ERROR LOW #define TEST_NUM 0x81 __sbit __at (0x96) P1_6 ; __sbit __at (0x97) P1_7 ; /* I2C functions */ void start() { /* I2C START condition */ SCL = SDA = HIGH; NOP; SDA = LOW; NOP; SCL = LOW; } void stop() { /* I2C STOP condition */ SDA = LOW; SCL = HIGH; NOP; SDA = HIGH; NOP; SCL = LOW; } unsigned char clock() { /* A subroutine to generate a clock pulse and return the * status of the data bus during the clock period */ unsigned char status = 0; SCL = HIGH; NOP; while(!SCL); /* eliminate ripples */ status = SDA; SCL = LOW; return (status); } unsigned char write(unsigned char byte) { /* I2C WRITE operation, Write a byte on SDA and return the * acknowledgement */ unsigned char mask = 0x80; unsigned char status= ACK; for ( ; mask > 0 ; ) { SDA = (byte & mask) ? ( SET ):( CLEAR ) ; mask >>= 1; clock(); } return (clock()); /* return the status of SDA line on * the 9th pulse */ } unsigned char read(unsigned char status) { /* I2C READ operation, read one byte from the transmitter and * give ack/nack to it */ unsigned char byte = 0; unsigned char count, level = 0; SDA = HIGH; /* configure SDA as input */ for ( count = 0; count < 8; count++ ) { byte <<= 1; level = clock(); byte |= level; } SDA = status; /* status = 1 :- NACK * status = 0 :- ACK */ clock(); return byte; } /* EEPROM functions */ unsigned char byte_write( unsigned int addr, unsigned char val ) { /* A write operation requires two 8-bit data word addresses * following the device address word and acknowledgment. Upon * receipt of this address, the EEPROM will again respond * with and then clock in the first 8-bit data * word. Following receipt of the 8-bit data word, the EEPROM * will output . The addressing device, such as a * microcontroller, then must terminate the write sequence * with a stop condition. At this time the EEPROM enters an * internally-timed write cycle, tWR, to the nonvolatile * memory. All inputs are disabled during this write cycle * and the EEPROM will not respond until the write is * complete */ unsigned char status = ERROR; start(); if ( write(EEPROM_WRITE_ADDR) == ACK ) { if ( write( (addr & 0xFF00) >> 8 ) == ACK ) { if ( write( (addr & 0x00FF) ) == ACK ) { if ( write(val) == ACK ) { status = SUCCESS; } else print_on_lcd("write val failed!!"); } else print_on_lcd("write low byte failed!!"); } else print_on_lcd("write high byte failed!!"); } else print_on_lcd("write device id failed!!"); stop(); delay_millisec(10); /* Twr = 10ms max */ return status; } unsigned char page_write(unsigned int addr, const unsigned char *str ) { /* A page write sequence. A maximum of 128 bits are * permissable beyond which a page over write occurs */ unsigned char status = ERROR; unsigned char bytes; start(); if ( write(EEPROM_WRITE_ADDR) == ACK ) { if ( write( (addr & 0xFF00) >> 8 ) == ACK ) { if ( write( (addr & 0x00FF) ) == ACK ) { for ( bytes = 0; str[bytes]; bytes++ ) { if (bytes <= 127) { /* check for page overflow*/ if ( write(str[bytes]) != ACK ) { print_on_lcd("page write to EEPROM failed!!"); status = ERROR; goto STOP; } } else { /* This byte needs to be * written to the next * page*/ stop(); /* stop the * operation */ delay_millisec(10); status = page_write( addr+1, str); /* perform a page * write again */ return status; } } write(' '); /* write nul character at * at the end of the string */ status = SUCCESS; } else print_on_lcd("write low byte failed!!"); } else print_on_lcd("write high byte failed!!"); } else print_on_lcd("write device id failed!!"); STOP: stop(); delay_millisec(10); return status; } unsigned char byte_read( unsigned int addr ) { /* A random read requires byte write sequence to load in the * data word address. Once the device address word and data * word address are clocked in and acknowledged by the EEPROM, * the microcontroller must generate another start * condition. The microcontroller now initiates a current * address read by sending a device address with the * Read/Write select bit high. The EEPROM acknowledges the * device address and serially clocks out the data word. The * microcontroller does not respond with but does generate a * following stop condition */ unsigned char val = ERROR; start(); if ( write(EEPROM_WRITE_ADDR) == ACK ) { if ( write( (addr & 0xFF00) >> 8 ) == ACK ) { if ( write( (addr & 0x00FF) ) == ACK ) { /* Dummy write successful */ start(); if ( write(EEPROM_READ_ADDR) == ACK) { val = read(NACK); } else print_on_lcd("write device Read id failed!!!"); } else print_on_lcd("write addr low byte failed!!!"); } else print_on_lcd("write addr high byte failed!!!"); } else print_on_lcd("write device_write id failed!!!"); stop(); return val; } /* Current address Read */ unsigned char current_read() { /* read a byte from the last address read/written + 1 */ unsigned char byte = ERROR; start(); if ( write(EEPROM_READ_ADDR) == ACK ) { byte = read(NACK); } else print_on_lcd("write(read id) failed!! "); stop(); return byte; } /* Sequential read */ unsigned int seq_read( unsigned int size, __idata unsigned char *buf, unsigned int addr) { /* read sequentially 'size' bytes to buffer 'buf' starting * from address 'addr' */ unsigned int num = 0; /* count the number of bytes read */ unsigned char byte = 0; buf[num] = byte_read(addr); num++; start(); if ( write(EEPROM_READ_ADDR) == ACK ) { for ( ; size -1 ; size--, num++ ) { buf[num] = read(ACK); num++; } buf[num] = read(NACK); /* for last byte to be read */ num++; } else print_on_lcd("Device not selected!"); stop(); return (num); } /* main program */ main() { unsigned char addr = 0; unsigned int i = 0; __idata unsigned char buf[128] = ""; /* A null string */ init_lcd(); print_on_lcd("EEPROM test"); if ( page_write( 0x00, "testing byte read operation") != SUCCESS ) /* writing a test string to memory */ print_on_lcd("page_write() failed!!!"); print_on_lcd("seq_read()"); display_word( seq_read( 30, buf, 0x00) ); print_on_lcd(buf); print_on_lcd("byte_read()"); for ( i = 0; i < 30 ; i++){ buf[i] = byte_read(i); } print_on_lcd(buf); while (1); } |
Topic | Author | Date |
AT24C512 Sequential Read failed!! | 01/01/70 00:00 | |
the IIC engine is identical ... | 01/01/70 00:00 | |
Sample code | 01/01/70 00:00 | |
what are the symptoms? | 01/01/70 00:00 | |
symptoms | 01/01/70 00:00 | |
A common mistake... | 01/01/70 00:00 | |
Your code looks fine | 01/01/70 00:00 | |
It took me ages ! | 01/01/70 00:00 | |
uint8_t range | 01/01/70 00:00 | |
confusion | 01/01/70 00:00 | |
you use uint8_t in your read_seq () | 01/01/70 00:00 | |
Do you want the full corrected source code ? | 01/01/70 00:00 | |
my own code | 01/01/70 00:00 | |
An explanation | 01/01/70 00:00 | |
code update | 01/01/70 00:00 | |
diff is your friend | 01/01/70 00:00 | |
size -1 | 01/01/70 00:00 | |
write program, rather than code... | 01/01/70 00:00 | |
It's Working![]() | 01/01/70 00:00 |