STM32的I2C老是卡住.
目前發現是因為 I2C_CheckEvent(I2C1, I2C_EVENT_xxxxxxxxxxx)
因為未知的原因, 某些flag是會跳起來的, 並不是完全按照範例所想的每個bit不差.
而這個function只要有一個bit不一樣他就判斷錯誤.
因此我把I2C_CheckEvent換成了I2C_GetStatus.
順便在發送過程中加入了Times counting機制. 讓他不容易卡死在迴圈內.
原本的I2C_CheckEvent是直接比對狀態, 回覆正確或是錯誤.
I2C_GetStatus的差異在於他會回傳SR1+SR2的內容, 以方便程式彈性使用.
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
以上的原始code由下面的do-while取代
LoopFlag1 = 0x7F; //作127次都沒成功就放棄.
do{
LoopFlag2 = 0x30;
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);
/* Send EEPROM address for write */
I2C_Send7bitAddress(I2C1, iDEVICE_ADDRESS, I2C_Direction_Transmitter);
do{
I2CStatus = I2C_GetStatus(I2C1);
// pData[LoopFlag2] = I2CStatus;
if((I2CStatus & I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)
{
LoopFlag2 = 0;
LoopFlag1 = 0;
}
else
{
LoopFlag2--;
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
}
}while(LoopFlag2);
}while(LoopFlag1);
u32 I2C_GetStatus(I2C_TypeDef* I2Cx)
{
vu32 Status, bflag1, bflag2;
/* Read the I2Cx status register */
bflag1 = I2Cx->SR1;
bflag2 = I2Cx->SR2;
bflag2 <<= 16;
/* Get the last event value from I2C status register */
Status = (bflag1 | bflag2) & 0x00FFFFFF;
/* Return status */
return Status;
}