Multibyte Read of EEPROM24C02 on I2C Bus

Keywords: Single-Chip Microcomputer I2C

The multi-byte reading of EEPROM under I2C bus is not difficult, basically a little change on the basis of one byte reading, so let's review the function of reading a single byte and see what he means at each step.
The read data explained here are all optional reads under EEPROM24C02: The time series is as follows


The timing analysis is as follows: the first step starts the bus, the second step addressing the device, the third step sends an answer signal, the fourth step addressing the device, the fifth step sends an answer signal, the sixth step reads the data, and the seventh step sends a stop signal.

********************************************************************************
	Function name: E2ReadByte()
	Return parameter: Returns a byte read from the machine
	Parameter List: The first parameter is the device address I2C_Add Provide an address for device addressing,
						The second parameter is the device subaddress addr Yes, the function will start reading data from this address
*********************************************************************************/
uchar E2ReadByte(uchar I2C_Add,uchar addr)
{
	uchar dat;
	
	I2C_Start();//Start Bus
	I2C_WriteByte(I2C_Add<<1);//Device Addressing, Writing
	I2C_WriteByte(addr);//Sub-device addressing tells the device where to start reading
	
	I2C_Start();//Start Bus
	I2C_WriteByte((I2C_Add<<1)|(0x01));//Sub-device addressing, read operation
	dat=I2C_ReadByte();
	SendACK(1);//Response to a NOACK
	
	I2C_Stop();//End signal
	return dat;
}

Let's first analyze what the above code means.
Each time the I2C bus writes to a data device, it needs to send an answer signal, so I encapsulate the function that receives ACK inside the I2C data write function, and then I will release the code.
This is a code function that reads EEPROM24C02 in a single byte, starting with the following steps
1. Invoke the I2C bus startup function to start the bus.
2. Call I2C bus for device addressing, assign the address of the device to a function, the direction of which is the pseudo-operation, the meaning of pseudo-writing is to facilitate the operation of the sub-devices below.
3. Call the I2C bus for addressing the sub-device, which is related to step 3. The meaning of this sub-device addressing is to tell the device that it needs to start reading from this address, which is equivalent to writing the sub-device address to the device.
4. The next step is to read the data, because the third step is a pseudo-write operation, that is, a write operation, and the direction changes when the data is read next, the bus needs to be restarted.
5. Call the I2C read data function again to tell the host the address of the sub-device and the direction is read.
6. After reading the data, the host needs to give an answer signal to the slave machine, telling the device that I do not need to read the data now, 1 is NO ACK, 0 is ACK.
7. End bus operation completed.

Okay, now on the way, multibyte read from the EEPROM of the I2C bus

Place code first:

/********************************************************************************
	Function name: E2nReadByte()
	Return parameters:
	Parameter List: The first parameter is the device address I2C_Add provides address for device addressing,
						The second parameter is the device subaddress addr, from which the function will start reading data
						The third parameter is a pointer that receives an array of Buf s to access the read data, and the fourth parameter, len, represents how many bytes to read
*********************************************************************************/
void E2nReadByte(uchar I2C_Add,uchar addr,uchar *buf,uint len)
{

	I2C_Start();//Start Bus
	I2C_WriteByte(I2C_Add<<1);//Device addressing, write operations, internal operations from machine
	I2C_WriteByte(addr);//Sub-device addressing tells the device where to start reading
	
	I2C_Start();//Start Bus
	I2C_WriteByte((I2C_Add<<1)|(0x01));//Sub-device addressing, directed toward read operation
	while(len>1)
	{
		*buf++=I2C_ReadByte();//Read a byte
		SendACK(0);//The host sends an ACK telling the slave that I still need to read data
		len--;
	}
	*buf=I2C_ReadByte();//Last byte
	SendACK(1);//Response to a NOACK
	I2C_Stop();//End signal
}

Here are just a few minor modifications, adding a while loop, and using a buf array to save data, since bytes are read continuously, remember to send an ACK answer signal to the slave after each byte read, telling it that I need to read the data again.

Below is the accompanying I2C bus code:

bit I2C_WriteByte(uchar dat)
{
	uchar temp;
	bit ack;
	for(temp=0x80;temp!=0;temp>>=1)//1010 0000
	{//0000 0000
		if( (temp&dat) ==0)//Check if current is 0 or 1
			SDA=0;
		else 
			SDA=1;
		
		I2C_delay();//Pull up the clock line after a delay of at least 4.7us
		SCL=1;
		I2C_delay();//Delay keeps pulling up at least 4us
		SCL=0;//Pull down after keeping pulling up at least 4us
		}
		ack=I2C_Ack();//Receive an ACK
		return ack;
}
bit I2C_Ack()
{
	bit ack;
	SDA=1;//Host actively releases SDA in preparation for ACK reading
	I2C_delay();//Delay at least 4.7us for SCL low level
	SCL=1;//Raise level after delay
	ack=SDA;//Read ACK
	I2C_delay();//Delay at least 4us for SCL high level
	
	SCL=0;//Lower SCL, release
	
	
	return ack;
}
//Send an ACK response to the device
void SendACK(bit ACk)
{
	SDA=ACk;//Release Bus
	I2C_delay();//Keep ACK down at least 4.7us
	SCL=1;
	I2C_delay();
	SCL=0;
	
}

Posted by costamesakid on Fri, 12 Nov 2021 14:41:34 -0800