打印
[产品应用]

cw32l010 I2C的状态切换要清除状态吗?

[复制链接]
46|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
fox1|  楼主 | 2024-12-2 17:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大佬们,在做一个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);
    }
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

12

帖子

0

粉丝