码迷,mamicode.com
首页 > 其他好文 > 详细

关于RT—Thread at24cxx驱动包中读操作中有错误

时间:2020-06-04 14:06:59      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:bytes   ops   got   停止   reg   发送   res   restart   count   

关于at24cxx驱动包中读操作中有错误

问题说明

最近在研究RT—Thread studio(附上链接RT—Thread Studio),因为其包的管理很方便。

可在我使用官方收录的at24cxx的软件包时,却发现了以下问题:

首先让我们看下驱动包里读一个字节的源代码

uint8_t at24cxx_read_one_byte(struct rt_i2c_bus_device *bus, uint16_t readAddr)
{
    rt_uint8_t buf[2];
    rt_uint8_t temp;
#if        (EE_TYPE > AT24C16)  
    buf[0] = (uint8_t)(readAddr>>8);        
    buf[1] = (uint8_t)readAddr;
    if (rt_i2c_master_send(bus, AT24CXX_ADDR, 0, buf, 2) == 0)
#else
    buf[0] = readAddr;
    if (rt_i2c_master_send(bus, AT24CXX_ADDR, 0, buf, 1) == 0)
#endif        
    {
        return -RT_ERROR;
    }
    read_regs(bus, 1, &temp);
    return temp;
}

程序调用rt_i2c_master_send对I2C从机写寄存器地址,调用read_regsI2C从机读一个字节(两个子函数源代码如下)
rt_i2c_master_send源代码

rt_size_t rt_i2c_master_send(struct rt_i2c_bus_device *bus,
                             rt_uint16_t               addr,
                             rt_uint16_t               flags,
                             const rt_uint8_t         *buf,
                             rt_uint32_t               count)
{
    rt_err_t ret;
    struct rt_i2c_msg msg;

    msg.addr  = addr;
    msg.flags = flags & RT_I2C_ADDR_10BIT;
    msg.len   = count;
    msg.buf   = (rt_uint8_t *)buf;

    ret = rt_i2c_transfer(bus, &msg, 1);

    return (ret > 0) ? count : ret;
}

read_regs源代码

static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf)
{
    struct rt_i2c_msg msgs;

    msgs.addr = AT24CXX_ADDR;
    msgs.flags = RT_I2C_RD;
    msgs.buf = buf;
    msgs.len = len;

    if (rt_i2c_transfer(bus, &msgs, 1) == 1)
    {
        return RT_EOK;
    }
    else
    {
        return -RT_ERROR;
    }
}

这里我们看到rt_i2c_master_sendread_regs最终都是调用rt_i2c_transfer这个函数进行的数据传输,我们在看下rt_i2c_transfer的源代码

static rt_size_t i2c_bit_xfer(struct rt_i2c_bus_device *bus,
                              struct rt_i2c_msg         msgs[],
                              rt_uint32_t               num)
{
    struct rt_i2c_msg *msg;
    struct rt_i2c_bit_ops *ops = bus->priv;
    rt_int32_t i, ret;
    rt_uint16_t ignore_nack;

    bit_dbg("send start condition\n");
    i2c_start(ops);
    for (i = 0; i < num; i++)
    {
        msg = &msgs[i];
        ignore_nack = msg->flags & RT_I2C_IGNORE_NACK;
        if (!(msg->flags & RT_I2C_NO_START))
        {
            if (i)
            {
                i2c_restart(ops);
            }
            ret = i2c_bit_send_address(bus, msg);
            if ((ret != RT_EOK) && !ignore_nack)
            {
                bit_dbg("receive NACK from device addr 0x%02x msg %d\n",
                        msgs[i].addr, i);
                goto out;
            }
        }
        if (msg->flags & RT_I2C_RD)
        {
            ret = i2c_recv_bytes(bus, msg);
            if (ret >= 1)
                bit_dbg("read %d byte%s\n", ret, ret == 1 ? "" : "s");
            if (ret < msg->len)
            {
                if (ret >= 0)
                    ret = -RT_EIO;
                goto out;
            }
        }
        else
        {
            ret = i2c_send_bytes(bus, msg);
            if (ret >= 1)
                bit_dbg("write %d byte%s\n", ret, ret == 1 ? "" : "s");
            if (ret < msg->len)
            {
                if (ret >= 0)
                    ret = -RT_ERROR;
                goto out;
            }
        }
    }
    ret = i;

out:
    bit_dbg("send stop condition\n");
    i2c_stop(ops);

    return ret;
}

rt_i2c_transfer源代码的最后我们可以看到 该函数在最后对I2C总线发送了停止信号(i2c_stop(ops))那么问题来了 at24cxx的驱动包读一个字节调用了两次rt_i2c_transfer,相当于每次调用就发送一个停止信号,这明显与I2C通讯机制不一致。

我们都知道I2C读一个字节数据的的流程是(大概流程 没写ACK NACK):

起始信号--> 器件地址+写-->寄存器地址-->起始信号-->器件地址+读-->从机发送数据-->停止信号 

at24cxx的驱动包读一个字节的流程变成了

起始信号--> 器件地址+写-->寄存器地址-->停止信号-->起始信号-->器件地址+读-->从机发送数据-->停止信号 

这里就是问题的关键。

关于RT—Thread at24cxx驱动包中读操作中有错误

标签:bytes   ops   got   停止   reg   发送   res   restart   count   

原文地址:https://www.cnblogs.com/xqyjlj/p/13042680.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!