cancel
Showing results for 
Search instead for 
Did you mean: 

Busy bus after I2C reading?

DMako
Associate

Hello, I try to interface with mlx90640 sensor via I2C. The MCU is STM32F401RE

After reading the bus stays busy. I use LL functions:

int MLX90640_I2CRead(uint8_t slave_address, uint16_t start_address,
		uint16_t numb_words, uint16_t *data) {
 
	uint16_t puff = 0x0000;
	uint8_t reg[2] = { 0, 0 };
	reg[0] = start_address >> 8;					//Address MSB
	reg[1] = (uint8_t) (start_address & 0x00FF); 	//Address LSB
 
// For testing write the exact bytes
	reg[0] = 0x80;
	reg[1] = 0x0D;
 
	uint8_t dat[2] = {0,0};
 
	while (LL_I2C_IsActiveFlag_BUSY(I2C1)) {
	}
 
	//LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
	LL_I2C_GenerateStartCondition(I2C1);
	while (!LL_I2C_IsActiveFlag_SB(I2C1)) {
	}
 
	//Send  device address
	LL_I2C_TransmitData8(I2C1, slave_address);
	while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
	}
	LL_I2C_ClearFlag_ADDR(I2C1);
 
	while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
	}
 
	//Send start address MSB
	LL_I2C_TransmitData8(I2C1, reg[0]);
	while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
	}
 
	//Send start address LSB
	LL_I2C_TransmitData8(I2C1, reg[1]);
	while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
	}
 
	//Repeat start condition
	LL_I2C_GenerateStartCondition(I2C1);
	while (!LL_I2C_IsActiveFlag_SB(I2C1)) {
	}
 
	//Send device address again + read
	LL_I2C_TransmitData8(I2C1, slave_address | 0x01);
	while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
	}
 
	//Read out data MSB, send ACK
	LL_I2C_ClearFlag_ADDR(I2C1);
	LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
	while (!LL_I2C_IsActiveFlag_RXNE(I2C1)) {
	}
	dat[0] = LL_I2C_ReceiveData8(I2C1);
 
	//Read out data LSB, send NACK
	LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
	LL_I2C_GenerateStopCondition(I2C1);
	while (!LL_I2C_IsActiveFlag_RXNE(I2C1)) {
		}
	dat[1] = LL_I2C_ReceiveData8(I2C1);
 
	puff = (uint16_t) (dat[0] << 8) | ((dat[1] << 8) & 0x00FF);
	*data = puff;
	return 0;
}

The function calling:

MLX90640_I2CRead(MLX90640_ADDR,0x800D,1,&regist);0690X0000060QKZQA2.png

Do you have any idea? Thanks!

1 REPLY 1
DMako
Associate

I solved the problem:

put NACK and STOP generating after reading.

uint16_t MLX90640_I2CReadWord(uint8_t slave_address, uint16_t start_address) {
 
	uint16_t puff;
	volatile uint8_t reg_m,reg_l,dat_m,dat_l;
 
	reg_m = (uint8_t) ((start_address & 0xFF00) >> 8);	//Address MSB
	reg_l = (uint8_t) (start_address & 0x00FF); 	    //Address LSB
 
 
	while (LL_I2C_IsActiveFlag_BUSY(I2C1)) {
	}
 
	//LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
	LL_I2C_GenerateStartCondition(I2C1);
	while (!LL_I2C_IsActiveFlag_SB(I2C1)) {
	}
 
	//Send  device address
	LL_I2C_TransmitData8(I2C1, slave_address);
	while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
	}
	LL_I2C_ClearFlag_ADDR(I2C1);
 
	while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
	}
 
	//Send start address MSB
	LL_I2C_TransmitData8(I2C1, reg_m);
	while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
	}
 
	//Send start address LSB
	LL_I2C_TransmitData8(I2C1, reg_l);
	while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
	}
 
	//Repeat start condition
	LL_I2C_GenerateStartCondition(I2C1);
	while (!LL_I2C_IsActiveFlag_SB(I2C1)) {
	}
 
	//Send device address again + read
	LL_I2C_TransmitData8(I2C1, slave_address | 0x01);
	while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
	}
 
	//Read out data MSB, send ACK
	LL_I2C_ClearFlag_ADDR(I2C1);
	LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
	while (!LL_I2C_IsActiveFlag_RXNE(I2C1)) {
	}
	dat_m = LL_I2C_ReceiveData8(I2C1);
 
	//Read out data LSB, send NACK
	while (!LL_I2C_IsActiveFlag_RXNE(I2C1)) {
	}
	dat_l = LL_I2C_ReceiveData8(I2C1);
	LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
	LL_I2C_GenerateStopCondition(I2C1);
 
	return ((uint16_t) (dat_m << 8)) | ((uint16_t)((dat_l) & 0x00FF));
 
}