This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

I2C read/write routines

Hi,

I am looking for simple read and write routines for I2C interface between Atmel low-end 89C2051 microcontroller and 24C04 serial EEPROM.

Any help would be great .

Thanks in Advance.
Rocknmoon

Parents
  • Rockn,

    Here is some code I used to dump the contents of a 24C01 EEPROM on a PC.
    You will need to insert your own code into raise_sda(), drop_sda(), raise_scl(), drop_scl(), and read_sda().
    This was written in Borland C to run under DOS, so you may need some minor changes to work under Keil C.

    This code is not optimised, and was deliberately written to run slowly so I could easily watch each transition using a Digital Storage Oscilloscope.

    Read the data sheet for the EEPROM you want to talk to, then just do exactly what they tell you to...

    void raise_sda(void)
    {
    //code to raise(= float) the SDA pin
    }
    
    void drop_sda(void)
    {
    //code to drop(= drive low) the SDA pin
    }
    
    void raise_scl(void)
    {
    //code to raise(= float) the SCL pin
    }
    
    void drop_scl(void)
    {
    //code to drop(= drive low) the SCL pin
    }
    
    int read_sda(void)
    {
    //return 0 if SDA is low, or 1 if SDA is high
    }
    //----------------------------------------------------------------------
    void i2c_stop(void)
    {
    	delay(1);
    	raise_scl();
    	delay(1);
    	raise_sda();
    	delay(1);
    }
    
    void i2c_start(void)
    {
    	i2c_stop();	//make sure we are starting from a STOP condition
    	drop_sda();
    	delay(1);
    	drop_scl();
    	delay(1);
    }
    
    //send BYTE in data. Return 0 is slave sent an ACK, or 1 if slave did not respond
    int i2c_send(BYTE data)
    //assumes SCL is already low
    {
    	int i;
    
    	for (i=0; i<8; i++)
    	{
    		if ((data & 0x80) != 0)
    			raise_sda();
    		else
    			drop_sda();
    
    		delay(1);	//*** this delay for debugging only. remove later.
    		raise_scl();
    		delay(1);
    		drop_scl();
    		delay(1);
    		data <<= 1;
    	}
    	raise_sda();	//release SDA so slave can control it
    	delay(1);		//*** this delay for debugging only. remove later.
    	raise_scl();
    	delay(1);
    	i = read_sda();	//read ACK pulse
    	drop_scl();
    	delay(1);
    	drop_sda();
    	return i;		//return ACK value
    }
    
    int i2c_recv(void)
    //assumes SCL is low
    {
    	int i;
    	int accum=0;
    
    	raise_sda();	//release SDA so slave can control it
    	delay(1);		//*** this delay for debugging only. remove later.
    	for (i=0; i<8; i++)
    	{
    		raise_scl();
    		delay(1);
    		accum <<= 1;		//slide left one bit
    		accum |= read_sda();//and copy SDA to bit 0
    		drop_scl();
    		delay(1);
    	}
    	return accum;		//return data byte
    }
    
    void send_nak(void)
    {
    	raise_scl();
    	delay(1);
    	drop_scl();
    	delay(1);
    	drop_sda();			//prepare to send STOP
    }
    
    void send_ack(void)
    {
    	drop_sda();		//should always be floating after a read anyway
    	delay(1);		//*** this delay for debugging only. remove later.
    
    	raise_scl();
    	delay(1);
    	drop_scl();
    	delay(1);
    }
    
    #define EEP_ADDR 0xa0	//I2C address of EEPROM
    #define DUMP_END 0xff	//last address of EEPROM
    
    void main(void)
    {
    	int i,temp;
    	int result;
    
    
    	i2c_start();	//start a write cycle (just to set the address)
    	result = i2c_send(EEP_ADDR);//send write address
    	if (result != 0)
    	{
    		printf("Didn't ACK write cmmand\n",result);
    		return 1;
    	}
    
    	result = i2c_send(0x00);//to address 00
    	if (result != 0)
    	{
    		printf("Didn't ACK EEPROM address\n",result);
    		return 2;
    	}
    
    	i2c_stop();		//stop write cycle
    	i2c_start();    //and start a read cycle
    
    	result = i2c_send(EEP_ADDR | 0x01);	//send read address
    	if (result != 0)
    	{
    		printf("Didn't ACK read command\n",result);
    		return 3;
    	}
    
    	for (i=0;i < DUMP_END;i++)
    	{
    		temp = i2c_recv();		//read one byte
    		printf("%02x ",temp);
    		if ((i & 0xf) == 0xf)
    			printf("\n");
    
    		if (i != DUMP_END)
    			send_ack();
    		else
    			send_nak();
    	}
    
    	i2c_stop();
    	return 0;
    }

Reply
  • Rockn,

    Here is some code I used to dump the contents of a 24C01 EEPROM on a PC.
    You will need to insert your own code into raise_sda(), drop_sda(), raise_scl(), drop_scl(), and read_sda().
    This was written in Borland C to run under DOS, so you may need some minor changes to work under Keil C.

    This code is not optimised, and was deliberately written to run slowly so I could easily watch each transition using a Digital Storage Oscilloscope.

    Read the data sheet for the EEPROM you want to talk to, then just do exactly what they tell you to...

    void raise_sda(void)
    {
    //code to raise(= float) the SDA pin
    }
    
    void drop_sda(void)
    {
    //code to drop(= drive low) the SDA pin
    }
    
    void raise_scl(void)
    {
    //code to raise(= float) the SCL pin
    }
    
    void drop_scl(void)
    {
    //code to drop(= drive low) the SCL pin
    }
    
    int read_sda(void)
    {
    //return 0 if SDA is low, or 1 if SDA is high
    }
    //----------------------------------------------------------------------
    void i2c_stop(void)
    {
    	delay(1);
    	raise_scl();
    	delay(1);
    	raise_sda();
    	delay(1);
    }
    
    void i2c_start(void)
    {
    	i2c_stop();	//make sure we are starting from a STOP condition
    	drop_sda();
    	delay(1);
    	drop_scl();
    	delay(1);
    }
    
    //send BYTE in data. Return 0 is slave sent an ACK, or 1 if slave did not respond
    int i2c_send(BYTE data)
    //assumes SCL is already low
    {
    	int i;
    
    	for (i=0; i<8; i++)
    	{
    		if ((data & 0x80) != 0)
    			raise_sda();
    		else
    			drop_sda();
    
    		delay(1);	//*** this delay for debugging only. remove later.
    		raise_scl();
    		delay(1);
    		drop_scl();
    		delay(1);
    		data <<= 1;
    	}
    	raise_sda();	//release SDA so slave can control it
    	delay(1);		//*** this delay for debugging only. remove later.
    	raise_scl();
    	delay(1);
    	i = read_sda();	//read ACK pulse
    	drop_scl();
    	delay(1);
    	drop_sda();
    	return i;		//return ACK value
    }
    
    int i2c_recv(void)
    //assumes SCL is low
    {
    	int i;
    	int accum=0;
    
    	raise_sda();	//release SDA so slave can control it
    	delay(1);		//*** this delay for debugging only. remove later.
    	for (i=0; i<8; i++)
    	{
    		raise_scl();
    		delay(1);
    		accum <<= 1;		//slide left one bit
    		accum |= read_sda();//and copy SDA to bit 0
    		drop_scl();
    		delay(1);
    	}
    	return accum;		//return data byte
    }
    
    void send_nak(void)
    {
    	raise_scl();
    	delay(1);
    	drop_scl();
    	delay(1);
    	drop_sda();			//prepare to send STOP
    }
    
    void send_ack(void)
    {
    	drop_sda();		//should always be floating after a read anyway
    	delay(1);		//*** this delay for debugging only. remove later.
    
    	raise_scl();
    	delay(1);
    	drop_scl();
    	delay(1);
    }
    
    #define EEP_ADDR 0xa0	//I2C address of EEPROM
    #define DUMP_END 0xff	//last address of EEPROM
    
    void main(void)
    {
    	int i,temp;
    	int result;
    
    
    	i2c_start();	//start a write cycle (just to set the address)
    	result = i2c_send(EEP_ADDR);//send write address
    	if (result != 0)
    	{
    		printf("Didn't ACK write cmmand\n",result);
    		return 1;
    	}
    
    	result = i2c_send(0x00);//to address 00
    	if (result != 0)
    	{
    		printf("Didn't ACK EEPROM address\n",result);
    		return 2;
    	}
    
    	i2c_stop();		//stop write cycle
    	i2c_start();    //and start a read cycle
    
    	result = i2c_send(EEP_ADDR | 0x01);	//send read address
    	if (result != 0)
    	{
    		printf("Didn't ACK read command\n",result);
    		return 3;
    	}
    
    	for (i=0;i < DUMP_END;i++)
    	{
    		temp = i2c_recv();		//read one byte
    		printf("%02x ",temp);
    		if ((i & 0xf) == 0xf)
    			printf("\n");
    
    		if (i != DUMP_END)
    			send_ack();
    		else
    			send_nak();
    	}
    
    	i2c_stop();
    	return 0;
    }

Children
No data