RT-Thread在正点原子apllo上使用IIC读取AT24C02

https://blog.csdn.net/yang1111111112/article/details/83276512

这篇文章有详细的简介,

问题是,关于RT-Thread中IIC地址的设置,在Apollo中,原理图如图,A0、A1、A2是接地,则IIC读地址是0xA0,写地址是0xA1,但是这样读取是错误的

 在RT-Thread的IIC底层驱动中,

 rt_i2c_master_send函数调用了rt_i2c_transfer函数,rt_i2c_transfer函数take了对应IIC设备对应的互斥量,此例是i2c2的,随后调用了i2c的 ops->master_xfer函数,在master_xfer函数中调用i2c_bit_send_address函数,问题是在i2c_bit_send_address函数中,代码如下

static rt_err_t i2c_bit_send_address(struct rt_i2c_bus_device *bus,
                                     struct rt_i2c_msg        *msg)
{
    rt_uint16_t flags = msg->flags;
    rt_uint16_t ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
    struct rt_i2c_bit_ops *ops = (struct rt_i2c_bit_ops *)bus->priv;

    rt_uint8_t addr1, addr2;
    rt_int32_t retries;
    rt_err_t ret;

    retries = ignore_nack ? 0 : bus->retries;

    if (flags & RT_I2C_ADDR_10BIT)
    {
        addr1 = 0xf0 | ((msg->addr >> 7) & 0x06);
        addr2 = msg->addr & 0xff;

        LOG_D("addr1: %d, addr2: %d", addr1, addr2);

        ret = i2c_send_address(bus, addr1, retries);
        if ((ret != 1) && !ignore_nack)
        {
            LOG_W("NACK: sending first addr");

            return -RT_EIO;
        }

        ret = i2c_writeb(bus, addr2);
        if ((ret != 1) && !ignore_nack)
        {
            LOG_W("NACK: sending second addr");

            return -RT_EIO;
        }
        if (flags & RT_I2C_RD)
        {
            LOG_D("send repeated start condition");
            i2c_restart(ops);
            addr1 |= 0x01;
            ret = i2c_send_address(bus, addr1, retries);
            if ((ret != 1) && !ignore_nack)
            {
                LOG_E("NACK: sending repeated addr");

                return -RT_EIO;
            }
        }
    }
    else
    {
        /* 7-bit addr */
        addr1 = msg->addr << 1;
        if (flags & RT_I2C_RD)
            addr1 |= 1;
        ret = i2c_send_address(bus, addr1, retries);
        if ((ret != 1) && !ignore_nack)
            return -RT_EIO;
    }

    return RT_EOK;
}

在RT-Thread中,对IIC设备的地址设置一共有两种设置模式,分别是十位和七位,在七位地址发送的代码这种,对地址进行了一位左移,addr1 = msg->addr<<1;所以,AT24C02原先是0xA0和0xA1,那么在代码中1010 0000(0xA0)应该是0101 0000(0x50),其实根据这行代码:

if (flags & RT_I2C_RD)

       addr1 |= 1;

可以看出,对于读信号,RT-Thread会自动在对地位置1,操作是addr1 = msg->addr<<1; addr1 |= 1;所以对AT24C02的读操作给的地址依然是0x50。

发布了4 篇原创文章 · 获赞 6 · 访问量 540

猜你喜欢

转载自blog.csdn.net/qq_38784061/article/details/104227202