打印
[AT32F415]

关于F415硬件I2C

[复制链接]
3464|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ccxzjz|  楼主 | 2021-11-9 09:03 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 ccxzjz 于 2021-11-9 09:37 编辑

AT32F415使用I2C与另一个芯片通信,主要实现读寄存器和写寄存器功能,代码参考的是下面这个例子


刚开始读取数据通信是正常,但是一旦有一次传输不正常(比如人为断开i2c的线再接回去),后面一直读取失败,一直陷入到这个,  只有复位芯片i2c才能读取成功。请教大家,怎么处理  ,完整代码如下

static I2C_StatusType I2C_WaitOnFlagUntilTimeout(I2C_Type *I2Cx, uint32_t Flag, FlagStatus Status, uint32_t EventCheck, uint32_t Timeout)
{
    /* delay 10 us = ms * 100 */
    Timeout *= 100;
    while (I2C_GetFlagStatus(I2Cx, Flag) == Status)
    {
        if (EventCheck & I2C_EVT_CHECK_ACKFAIL)
        {
            if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ACKFAIL) == SET)
            {
                I2C_GenerateSTOP(I2Cx, ENABLE);
                I2C_ClearFlag(I2Cx, I2C_FLAG_ACKFAIL);
                return I2C_ERROR;
            }
        }
        if (EventCheck & I2C_EVT_CHECK_STOP)
        {
            if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF) == SET)
            {
                I2C_ClearSTOPFlag(I2Cx);
                return I2C_ERROR;
            }
        }
        I2C_Delay(10);
        if ((Timeout--) == 0)
        {
            return I2C_TIMEOUT;
        }
    }
    return I2C_OK;
}

I2C_StatusType hw_i2c_read_reg(I2C_Type *I2Cx, uint8_t slave_addr, uint8_t reg, uint8_t *rd_value, uint32_t Timeout)
{
    /* Wait until BUSY flag is reset */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BUSYF, SET, I2C_EVT_CHECK_NONE, I2C_TIMEOUT_BUSY_FLAG) != I2C_OK)
    {
        return I2C_ERROR_STEP_1;
    }

    /* Disable Pos */
    I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);

    /* Enable Acknowledge */
    I2C_AcknowledgeConfig(I2Cx, ENABLE);

    /* Send START condition */
    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Wait until SB flag is set */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
    {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return I2C_ERROR_STEP_2;
    }

    /* Send slave address for write */
    I2C_Send7bitAddress(I2Cx, slave_addr, I2C_Direction_Transmit);

    /* Wait until ADDR flag is set */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
    {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return I2C_ERROR_STEP_3;
    }

    /* Clear ADDR flag */
    I2C_ClearADDRFlag(I2Cx);

    /* Wait until TDE flag is set */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
    {
        /* Send STOP Condition  */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return I2C_ERROR_STEP_4;
    }

    /* Send Memory Address */
    I2C_SendData(I2Cx, reg);

    /* Wait until TDE flag is set */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
    {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return I2C_ERROR_STEP_5;
    }

    /* Send START condition */
    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Wait until SB flag is set */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
    {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return I2C_ERROR_STEP_6;
    }

    /* Send slave address for read */
    I2C_Send7bitAddress(I2Cx, slave_addr, I2C_Direction_Receive);

    /* Wait until ADDR flag is set */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
    {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return I2C_ERROR_STEP_7;
    }

    /* Disable Acknowledge */
    I2C_AcknowledgeConfig(I2Cx, DISABLE);

    /* Clear ADDR flag */
    I2C_ClearADDRFlag(I2Cx);

    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

    /* Wait until RXNE flag is set */
    if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
    {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        return I2C_ERROR_STEP_8;
    }

    /* Read data from DR */
    (*rd_value) = I2C_ReceiveData(I2Cx);

    return I2C_OK;
}



使用特权

评论回复
沙发
cehuafan| | 2021-11-10 22:06 | 只看该作者
不太喜欢硬件iic。        

使用特权

评论回复
板凳
wengh2016| | 2021-11-10 22:06 | 只看该作者
推荐模拟iic吧。         

使用特权

评论回复
地板
qiufengsd| | 2021-11-10 22:07 | 只看该作者
F415硬件I2C有坑吗?     

使用特权

评论回复
5
kmzuaz| | 2021-11-10 22:07 | 只看该作者
F415硬件I2C读写速度怎么样?   

使用特权

评论回复
6
plsbackup| | 2021-11-10 22:07 | 只看该作者
就是读取超时了吧。         

使用特权

评论回复
7
mnynt121| | 2021-11-10 22:07 | 只看该作者
硬件I2C不好调试。              

使用特权

评论回复
8
aspoke| | 2021-11-10 22:07 | 只看该作者
为什么不使用IO模拟呢?         

使用特权

评论回复
9
232321122| | 2021-11-10 22:07 | 只看该作者
这个是官网的代码吗?      

使用特权

评论回复
10
ghuca| | 2021-11-10 22:08 | 只看该作者
可能读写速度太快了。         

使用特权

评论回复
11
soodesyt| | 2021-11-10 22:08 | 只看该作者
芯片没有响应吗?        

使用特权

评论回复
12
yangxiaor520| | 2021-11-11 07:44 | 只看该作者
这算是bug吗?

使用特权

评论回复
13
ccxzjz|  楼主 | 2021-11-12 15:20 | 只看该作者
改用模拟的了,硬件确实繁琐

使用特权

评论回复
14
muyichuan2012| | 2021-11-12 15:34 | 只看该作者
本帖最后由 muyichuan2012 于 2021-11-12 15:39 编辑

官方代码都是测试通过的,不会有问题的。
不过,官方的代码一般不会去考虑 “一旦有一次传输不正常(比如人为断开i2c的线再接回去)”这种应用情形,所以需要使用者根据自己的应用去调整,毕竟官方提供的仅仅是demo。



使用特权

评论回复
15
vt2017| | 2021-11-14 10:50 | 只看该作者
“传输不正常”有很多种情况,硬件I2C是有提供一部分的错误处理的,比如应答失败、欠载/过载、仲裁丢失等,但你提到的人为断开I2C线再接回去不是硬件I2C所能处理的错误。遇到此类的错误很可能会导致I2C内部的状态标志出现异常,你可以做下面几个尝试:
1、设定函数的超时时间,如果长时间无法通讯就退出函数,并返回相应的你自己定义的标志位
2、根据你自己定义的标志位来选择是否要复位硬件I2C
3、调用I2C_DeInit函数,将时钟复位,清除所有的I2C状态
4、重新初始化I2C配置

使用特权

评论回复
16
骑着蜗牛狂奔O| | 2021-11-14 17:50 | 只看该作者
SCL SDA总线任意一根拉低就会出现此标志,在收到Stop时,硬件会自动清除,出现这种情况一般是你整个通信流程未完成,此时软件复位I2C就行,不用芯片复位

使用特权

评论回复
17
6552918| | 2021-11-15 09:41 | 只看该作者
需要人为判断异常处理,原厂例程一般不会考虑这些,只有产品及的代码才会处理异常

使用特权

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

本版积分规则

14

主题

37

帖子

1

粉丝