大佬们,在做一个MEMS芯片的驱动移植,他的i2c read时序比较奇怪,是先1 START -> 2 SLA+W 【收ACK】->3 发读取的寄存器地址【收ACK】->4 START -> 5 SLA+R 【收ACK】->接收数据 -> END 最后发STOP
我看cw32l010的用户手册
状态间没有切换的,如果我第3步发完寄存器收完ACK后,直接重新发送起始信号,会报错吗?
根据时序图写的代码这样子:
I2C_ErrorDef I2C_QMA6100P_SEQ_READ(I2C_TypeDef *I2Cx, uint8_t regAddr, uint8_t *pu8Data, uint32_t u32Len)
{
uint8_t u8i = 0, u8State;
uint32_t timeout = I2C_TIMEOUT;
I2C_ClearIrq(I2Cx);
I2C_GenerateSTART(I2Cx, ENABLE);
while (timeout--)
{
while (timeout)
{
timeout--;
if (I2C_GetIrq(I2Cx))
{
break;
}
}
u8State = I2C_GetState(I2Cx);
switch (u8State)
{
case 0x08: // 发送完START信号
case 0x10: // 已发送重复起始信号
I2C_GenerateSTART(I2Cx, DISABLE);
I2C_Send7bitAddress(I2Cx, u8SlaveAddr, I2C_Direction_Transmitter); // 发送从机地址+W字节
timeout = I2C_TIMEOUT;
break;
case 0x18: // 发送完SLA+W信号,并收到ACK
case 0x28: // 发送完1字节数据,并收到ACK
if (u8i = 0)
{
I2C_SendData(I2Cx, regAddr);
timeout = I2C_TIMEOUT;
u8i++;
break;
/* code */
}
if (u8i = 1) // ADDR已经发送
{
I2C_ClearIrq(I2Cx);
I2C_GenerateSTART(I2Cx, ENABLE);
I2C_Send7bitAddress(I2Cx, u8SlaveAddr, I2C_Direction_Receiver); // 发送从机地址+R字节
timeout = I2C_TIMEOUT;
u8i = 0;
break
}
case 0x40: // 发送完SLA+R信号,开始接收数据
I2C_AcknowledgeConfig(I2Cx, ENABLE);
if (u32Len == 1)
{
I2C_AcknowledgeConfig(I2Cx, DISABLE);
}
break;
case 0x50: // 接收完一字节数据,在接收最后1字节数据之前设置AA=0;
pu8Data[u8i = I2C_ReceiveData(I2Cx);
timeout = I2C_TIMEOUT;
if (u8i == u32Len - 1)
{
I2C_AcknowledgeConfig(I2Cx, DISABLE);
}
break;
case 0x58: // 接收到一个数据字节,且NACK已回应
pu8Data[u8i = I2C_ReceiveData(I2Cx);
if (u32Len == 1 || u8i == u32Len)
{
I2C_GenerateSTOP(I2Cx);
I2C_ClearIrq(I2Cx);
return I2C_NO_ERROR;
}
I2C_GenerateSTOP(I2Cx);
I2C_ClearIrq(I2Cx);
return I2C_MR_DATA_NACK;
case 0x38: // 主机在发送 SLA+W 阶段或者发送数据阶段丢失仲载 或者 主机在发送 SLA+R 阶段或者回应 NACK 阶段丢失仲裁
I2C_GenerateSTOP(I2Cx);
I2C_ClearIrq(I2Cx);
return I2C_MR_ARBITRATION_LOST;
case 0x48: // 发送完SLA+R后从机返回NACK
I2C_GenerateSTOP(I2Cx);
I2C_ClearIrq(I2Cx);
return I2C_MR_ADDR_NACK;
default:
break;
}
I2C_ClearIrq(I2Cx);
}
}
|