Hello everyone I have some strange issue with i2c on KL25Z freedom board. I'm using CW with processor expert and using bean I2C_LDD. The problem is that when I want to send several blocks of data on the bus I have to use some delay after sending each block - otherwise I will get ERR_BUSY error and some of blocks will not appear on the bus. See the code of my function:
void MyI2C_SendBlock(uint8_t devAddr, uint8_t *dataBlock, uint8_t dataSize) { uint8_t res; |
//selecting slave
I2C_SelectSlaveDevice(I2C_DeviceData, LDD_I2C_ADDRTYPE_7BITS, devAddr);
//sending data
res = I2C_MasterSendBlock(I2C_DeviceData, dataBlock, dataSize, LDD_I2C_SEND_STOP);/*
//wait until data sent
while (!MyI2C_DataState.dataTransmittedFlag);
MyI2C_DataState.dataTransmittedFlag = 0;
//THIS STRANGE DELAY
int i;
for(i = 0; i < 100; ++i);
}
How to omit using delay?
Hello,
If you need to add some magic delays to your code to 'fix' it, then this is typically a reentrancy (or stack) problem in your code, because you change the timing.
But it could be that your problem is a defect in the silicon. Can you check that your clock prescaler for the I2C is set to one (and not to something else)?
See
KL25Z and I2C: Missing Repeated Start Condition | MCU on Eclipse
and errata here:
At least with the prescaler set to one, all my application on the KL25Z with I2C are working properly.
Hope this helps.
(Un)fortunately I've already read this article and prescaler is set to one. What's more the whole program is very simply it uses only i2c, so it can't be problem with reentrancy (no other interrupts apart from these from i2c).
It looks like this is waiting for the bus idle state.
Code from AN4610:
bool WriteAccRegs(LDD_TDeviceData *I2CPtr, TDataState *DataState, uint8_t Address, uint8_t RegCount, uint8_t *Data)
{
LDD_I2C_TBusState BusState;
const uint8_t MAX_REG_COUNT = 16;
uint8_t SendBuffer[MAX_REG_COUNT];
SendBuffer[0] = Address;
memcpy(&SendBuffer[1], Data, RegCount);
DataState->Sent = FALSE;
I2C_MasterSendBlock(I2CPtr, &SendBuffer, RegCount + 1, LDD_I2C_SEND_STOP);
while (!DataState->Sent) {}
do {I2C_CheckBus(I2CPtr, &BusState);}
while(BusState != LDD_I2C_IDLE);
if (!DataState->Sent) {
return FALSE;
}
return TRUE;
}
Erich