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

Writing a Byte over I2C for Slaves without Register Addresses

I have this function defined for writing a byte to either the LCD 1602 (using the PCF8574 I/O expander), or the SHT21 humidity sensor.  In both cases, it seems like after I write the slave address, I should start transmitting data.  The only issue is, is that the microcontroller gets stuck in an infinite loop, as the interrupt flag IICIF does not set.

Below is my code, using the KL25Z controller from Freescale:

int i2c_write_byte(unsigned char addr, unsigned char data) {
	int retry = 1000;
	while (I2C1->S & 0x20) {	// Wait until bus is not busy (busy: D5 = 1)
		if (-retry <= 0) {
			return ERR_BUS_BUSY;
		}
		delayUs(100);
	}
	// Send start
	I2C1->C1 |= 0x10; // Set TX (D4) to 1 (transmit)
	I2C1->C1 |= 0x20; // Set MST (D5) to 1 (master mode)
	
	// Send slave address and write flag
	I2C1->D = addr;						// Bit shift leaves R/W = 0, so master will write next byte
	while(!(I2C1->S & 0x02)); // Wait for TX to complete (i.e. till IICIF = 0)
	I2C1->S |= 0x02; 					// clear IICIF
	if (I2C1->S & 0x10) { 		// If arbitration is lost (i.e. D4, ARBL = 1)
		I2C1->S |= 0x10; 				// clear IICIF
		return ERR_ARB_LOST;
	}
	if (I2C1->S & 0x01) { 			// Slave NACK'ed (i.e. D0, RXAK = 1)
		return ERR_NO_ACK;
	}
		
	// Send data
	I2C1->D = data;
	while(!(I2C1->S & 0x02)); // Wait for TX to complete (i.e. till IICIF = 0)
	I2C1->S |= 0x02;					// clear IICIF
	if (I2C1->S & 0x01) { 			// Slave NACK'ed (i.e. D0, RXAK = 1)
		return ERR_NO_ACK;
	}
	
	// Stop
	I2C1->C1 &= ~0x30;				// Unset MST (D5) and TX (D4)
	return ERR_NONE;
}

It gets stuck at 

while(!(I2C1->S & 0x02)); // Wait for TX to complete (i.e. till IICIF = 0)

And I can't understand why.  From the KL25Z datasheet, IICIF sets when there is a one-byte transfer, match of slave address, arbitration lost, etc.  How would I be able to tell that my data isn't being transmitted to the slave (despite previously ACK'ing the slave address)?

For the slave devices, I concluded this from their datasheets:

https://www.nxp.com/docs/en/data-sheet/PCF8574_PCF8574A.pdf (page 8)

https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT21_Datasheet.pdf (page 8).

As an example, i2c_write_byte(I2C_ADR_W, 0xFE) for soft-resetting the SHT21 gets stuck at that line.  I am using pins C10 and C11 on FRDM KL25Z (clock enabled using SCGC5, PCR = ALT2 | PS | PE)

I would be grateful for any help that you can offer me.

Thank you.