[分享]使用RT-Thread的I2C总线读写EEPROM或铁电(FRAM)

发布于 2014-04-02 11:05:25

上周刚好调I2C的驱动,所以写了一段测试小程序,分享一下。

#include <rtthread.h>
#include <rtdevice.h>

static const char * i2c_bus_device_name = "i2c1";
static const rt_uint8_t eeprom_addr = 0x50; /* 1010A2A1A0 - R/W */

rt_err_t i2c_test(void)
{
    struct rt_i2c_bus_device * i2c_device;
    struct rt_i2c_msg msgs[2];
    rt_uint8_t buffer1[2];
    rt_uint8_t buffer2[2];
    rt_size_t i;

    i2c_device = rt_i2c_bus_device_find(i2c_bus_device_name);
    if(i2c_device == RT_NULL)
    {
        rt_kprintf("i2c bus device %s not found!
", i2c_bus_device_name);
        return -RT_ENOSYS;
    }

    //step 1: read out.
    buffer1[0] = 0;

    msgs[0].addr = eeprom_addr;
    msgs[0].flags = RT_I2C_WR; /* Write to slave */
    msgs[0].buf = buffer1; /* eeprom offset. */
    msgs[0].len = 1;

    msgs[1].addr  = eeprom_addr;
    msgs[1].flags = RT_I2C_RD; /* Read from slave */
    msgs[1].buf   = buffer2;
    msgs[1].len   = sizeof(buffer2);

    if( rt_i2c_transfer(i2c_device, msgs, 2) != 2 )
    {
        rt_kprintf("read EEPROM fail!
");
    }

    rt_kprintf("read EEPROM at I2C address: 0x%02X
", eeprom_addr);
    rt_kprintf("0x0000: ");
    for(i=0; i<sizeof(buffer2); i++)
    {
        rt_kprintf("%02X ", buffer2*);
    }
    rt_kprintf("
");

    //step 2: write back.
    for(i=0; i<sizeof(buffer2); i++)
    {
        buffer2* = ~buffer2*;
    }

    msgs[0].addr = eeprom_addr;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf = buffer1; /* eeprom offset. */
    msgs[0].len = 1;

    msgs[1].addr  = eeprom_addr;
    msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
    msgs[1].buf   = buffer2;
    msgs[1].len   = sizeof(buffer2);

    if( rt_i2c_transfer(i2c_device, msgs, 2) != 2 )
    {
        rt_kprintf("write EEPROM fail!
");
    }
    rt_thread_delay(rt_tick_from_millisecond(50)); // FRAM no need.

    //step 3: re-read out.
    buffer1[0] = 0;

    msgs[0].addr = eeprom_addr;
    msgs[0].flags = RT_I2C_WR; /* Write to slave */
    msgs[0].buf = buffer1; /* eeprom offset. */
    msgs[0].len = 1;

    msgs[1].addr  = eeprom_addr;
    msgs[1].flags = RT_I2C_RD; /* Read from slave */
    msgs[1].buf   = buffer2;
    msgs[1].len   = sizeof(buffer2);

    if( rt_i2c_transfer(i2c_device, msgs, 2) != 2 )
    {
        rt_kprintf("re-read EEPROM fail!
");
    }

    rt_kprintf("re-read EEPROM at I2C address: 0x%02X
", eeprom_addr);
    rt_kprintf("0x0000: ");
    for(i=0; i<sizeof(buffer2); i++)
    {
        rt_kprintf("%02X ", buffer2*);
    }
    rt_kprintf("
");

    return RT_EOK;
}

#ifdef RT_USING_FINSH
#include <finsh.h>
FINSH_FUNCTION_EXPORT(i2c_test, i2c_test);
#endif // RT_USING_FINSH

查看更多

关注者
0
被浏览
8.9k
16 个回答
rockleerocklee
rockleerocklee 2014-04-02
好,厉害呀,正好需要。
rockleerocklee
rockleerocklee 2014-04-20
为什么没注册设备而直接寻找设备。
石头
石头 2014-04-29
你好。看了你的这个模块,感觉和RT-Thread的驱动有点不同;驱动里面用到的读写应该是i2c_bus_device_read和i2c_bus_device_write,而你用的是更加底层的模块。你为什么不直接用封装好的驱动模块进行读写?在rt_i2c_transfer上面应该还有两层封装啊。而rt_i2c_transfer里面调用的master_xfer则是要用户实现的最底层的部份。这样理解对吗?
aozima
aozima 2014-04-29
拒绝白嫖,拒绝键盘侠!
master_xfer是硬件驱动,跟具体硬件相关,每个硬件要单独编写。
rt_i2c_transfer是I2C的基本操作接口。
i2c_bus_device_read/write是基于rt_i2c_transfer封装的更易用的API。
根据实际需要合理选择。
石头
石头 2014-04-29
你的这种使用方法没有用到RT-Thread的设备管理吧。相当于裸机的形式咯?
bernard
bernard 2014-04-29
RT-Thread的设备接口并不是说一定要使用device_read/write等啊,IIC、SPI都采用了另外一种形式,要具备灵活性
石头
石头 2014-04-29
RT-Thread的设备接口并不是说一定要使用device_read/write等啊,IIC、SPI都采用了另外一种形式,要具备灵活性

这样做确实是具备了灵活性,但是同样带来的是不一致性,为什么不将各个接口统一起来呢。这样使用就更加方便了。从的这段代码我看到了查找设备;但是并未看到通过设备调用接口的部份,这样的话注册设备的意义在哪里?我参加工作也就两年,以前也就移植UcCos玩了下,并没有深入,这次有机会接触了下RT-Thread,没有深入的接触过其他操作系统,不好对RT-Thread做深入评价;但是就我目前来说,这款操作系统用起来还是很忙好用的,其中的Finsh简直就是调试神器啊。目前能简单的应用,我目前想把驱动好好的琢磨下;这样以后使用起来会更加的方便。很感谢各位大牛的解答。
bernard
bernard 2014-04-29
不明白为啥现在论坛上老是希望点名呢,大家一起交流交流下即可 [s:170]
石头
石头 2014-04-29
不明白为啥现在论坛上老是希望点名呢,大家一起交流交流下即可 [s:170]

对不起。我全部删掉了。很希望和你们交流下。对你们的操作系统很是感兴趣。能帮我解释下上面的问题吗?
bernard
bernard 2014-04-29
RT-Thread本身初期提供的是rt_device_read/write/open/close/control的API,但是显然,这些API并不可能代表所有的设备操作,特别是一些设备可能是基于另外一些外设(例如基于SPI Flash的块设备,块设备依然是read/write等接口,但是SPI设备则完全不需要)

所以这中间还有一类设备,它的接口也相对统一、固定,但是是由上层固定的组件或其他逻辑层的设备驱动来使用,所以这个时候依然使用device_read/write已经失去意义了。但设备注册依然有好处,注册设备后,可以根据设备名称来查找到相应的设备,然后进行访问。
pangwei
pangwei 2014-06-11
mark eeprom 地址设置的时候需要去掉最低位
fengye
fengye 2018-10-21
我的怎么显示没有注册i2c bus

i2c.png
xb-w
xb-w 2019-08-13
fengye 发表于 2018-10-21 00:37
我的怎么显示没有注册i2c bus


我现在跟你一样,是怎么解决的?

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览