2018-08-01 05:31 AM
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,®ist);
Do you have any idea? Thanks!
2018-08-01 07:07 AM
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));
}