Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
02/26/09 08:59
Read: times


 
#162872 - An explanation
Responding to: ???'s previous message
There are two problems with your code:

The i2c_read(char ack) function needs to force SDA high before the bits are clocked in. So that SDA is an high impedance input.

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;             /* .kbv MAKE LINE AN INPUT */
	for ( count = 0; count < 8; count++ ) {
		byte <<= 1;
		level = clock();
		byte |= level;		
	}
	SDA = status;		/* status = 1 :- NACK
				 * status = 0 :- ACK */
	clock();
	return byte;
}

 


And the bit that drove me mad:
You have *buf++ = read(NACK) followed by buf[1] = read(ACK)

You meant to have:
buf[0] = read(NACK); ... buf[1] = read(ACK); ... buf[20] = read(NACK);

You are mixing a pointer operation *buf++ with an array operation.
If you increment buf, a subsequent buf[1] is going to refer to the original buf[2].

I would suggest ONE form of syntax and stick to it. Mixing invites trouble. My personal preference would have been pointers throughout.

/* Sequential read */
unsigned int seq_read( unsigned int size, __idata unsigned char *buf, unsigned int addr)  /* .kbv */
{
	/* read sequentially 'size' bytes to buffer 'buf' starting
	 * from address 'addr' */
	unsigned int num = 1;	/* count the number of bytes read */
	unsigned char byte = 0;
	
	buf[0] = byte_read(addr);     /* .kbv THE FIRST BYTE */

	start();
	
	if ( write(EEPROM_READ_ADDR) == ACK ) {
		for (  ; size -1; size-- ) {
			buf[num] = read(ACK);
			num++;
		}
		buf[num] = read(NACK); /* transmit NACK with last byte
					* followed by a STOP */
                num++;
	}

 

Also you use a uint8_t for addr instead of a uint16_t. You won't get far on a 24C512 with a uint8_t !
Your byte_read() function takes a uint16_t addr , but you only pass a uint8_t to seq_read().

Please ask if you do not understand any of this.

David.

List of 19 messages in thread
TopicAuthorDate
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      

Back to Subject List