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 discussion

Hi,

I am trying to use the I2C bus with a 89LV55 MCU. I have 2 devices : a 24LC16B serial eeprom and a digital pot DS1844. The MCU has no built-in facilities for the I2C bus so I created the low level routines for the communications. I believed, from the I2C bus specifications, that these functions should be adequate, but not the way I use them to access the devices. A first question would be how do you put them together ? or how to construct a program... I know I am in trouble ! I have two files : I2C.c with the I2C functions and a definition file I2C.h. The I2C functions are :

void I2C_Start(void) // start I2C communication
void I2C_Write(unsigned char data_out) // write a byte
unsigned char I2C_Read(void) // read a byte
bit I2C_Ack (void) // read acknowledge
void I2C_NoAck (void) // no acknowledge
void I2C_Delay(void) // 5 us delay for low speed (100kHz)
void I2C_Stop(void) // stop I2C communication

-----------------------------------------------------------------------------------------------------------------------
void I2C_Start(void)
{
SDA = HIGH;			/* Bus idle when SDA and SCK at level HIGH */
SCK = HIGH;
I2C_Delay();
SDA = LOW;			/* Start condition */
I2C_Delay();
//SCK = LOW;		/* I2C_READ and I2C_WRITE */
}

-----------------------------------------------------------------------------------------------------------------------
void I2C_Write(unsigned char data_out)
{
unsigned char position;
for (position = 0; position < 8; position++)
	{
	SCK = LOW;
	SDA = ((data_out & 0x80) ? 1 : 0); /* Mask to check the MSB and send 0 or 1 */
	SCK = HIGH;
	I2C_Delay();
	data_out <<= 1; /* Shift data */
	}
}

-----------------------------------------------------------------------------------------------------------------------

unsigned char I2C_Read(void)
{
unsigned char data_in, position;
SCK = LOW;
SDA = HIGH;			/* Set data pin in read mode  */
data_in = 0x00;
for (position = 0; position < 8; position++)
	{
	I2C_Delay();
	data_in <<=1;
	SCK = HIGH;
	I2C_Delay();
	data_in |= SDA;	/* Read pin state */
	SCK = LOW;
	}
return (data_in);
}
-----------------------------------------------------------------------------------------------------------------------

bit I2C_Ack (void)
{
bit ack_bit;
SCK = LOW;			/* Wait for high state of SCK for the 9th clock cycle */
I2C_Delay();
SCK = HIGH;
ack_bit = SDA; 	/* Read the acknowledge bit */
I2C_Delay();
return (ack_bit);
}
-----------------------------------------------------------------------------------------------------------------------

void I2C_NoAck (void)
{
SCK = LOW;			/* Wait for high state of SCK for the 9th clock cycle */
SDA = HIGH; 		/* Set the acknowledge bit */
I2C_Delay();
SCK = HIGH;
I2C_Delay();
}

-----------------------------------------------------------------------------------------------------------------------

void I2C_Delay(void)	// 5 us delay
{
_nop_();
}
-----------------------------------------------------------------------------------------------------------------------

void I2C_Stop(void)
{
SCK = LOW;
SDA = LOW;
SCK = HIGH;			/* Generate stop condition */
I2C_Delay();
SDA = HIGH;			/* Generate stop condition */
I2C_Delay();
}
-----------------------------------------------------------------------------------------------------------------------

Parents
  • "With a high-level language like 'C' you have absolutely no guarantee whatsoever that any particular source construct will generate any specific sequence of machine instructions!"

    Unless you use Keil's language extension _nop_(), which is guaranteed to translate to a single nop. For the delay required in this case this would seem ideal, but do inline them (possibly by encapsulating them in a macro) rather than using a function.

    Stefan

Reply
  • "With a high-level language like 'C' you have absolutely no guarantee whatsoever that any particular source construct will generate any specific sequence of machine instructions!"

    Unless you use Keil's language extension _nop_(), which is guaranteed to translate to a single nop. For the delay required in this case this would seem ideal, but do inline them (possibly by encapsulating them in a macro) rather than using a function.

    Stefan

Children
No data