在Linux上使用I2C读/写

时间:2009-02-02 21:29:30

标签: c linux ioctl i2c

我正在尝试读取/写入通过地址FM24CL64-GTR FRAM上的I2C总线连接的0b 1010 011芯片。

当我尝试写3个字节(数据地址2个字节,+数据1个字节)时,我得到一个内核消息([12406.360000] i2c-adapter i2c-0: sendbytes: NAK bailout.),以及写入返回!= 3.请参阅下面的代码:

#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>

int file;
char filename[20];
int addr = 0x53; // 0b1010011; /* The I2C address */
uint16_t dataAddr = 0x1234;
uint8_t val = 0x5c;
uint8_t buf[3];

sprintf(filename,"/dev/i2c-%d",0);
if ((file = open(filename,O_RDWR)) < 0)
    exit(1);

if (ioctl(file,I2C_SLAVE,addr) < 0)
    exit(2);

buf[0] = dataAddr >> 8;
buf[1] = dataAddr & 0xff;
buf[2] = val;

if (write(file, buf, 3) != 3)
    exit(3);

...

然而,当我写2个字节,然后写另一个字节时,我没有内核错误,但是当我尝试从FRAM读取时,我总是回到0.这是从FR​​AM读取的代码:

uint8_t val;

if ((file = open(filename,O_RDWR)) < 0)
    exit(1);

if (ioctl(file,I2C_SLAVE,addr) < 0)
    exit(2);

if (write(file, &dataAddr, 2) != 2) {
    exit(3);

if (read(file, &val, 1) != 1) {
    exit(3);

没有任何函数返回错误值,我也尝试过:

#include <linux/i2c.h>

struct i2c_rdwr_ioctl_data work_queue;
struct i2c_msg msg[2];
uint8_t ret;

work_queue.nmsgs = 2;
work_queue.msgs = msg;

work_queue.msgs[0].addr = addr;
work_queue.msgs[0].len = 2;
work_queue.msgs[0].flags = 0;
work_queue.msgs[0].buf = &dataAddr;

work_queue.msgs[1].addr = addr;
work_queue.msgs[1].len = 1;
work_queue.msgs[1].flags = I2C_M_RD;
work_queue.msgs[1].buf = &ret;

if (ioctl(file,I2C_RDWR,&work_queue) < 0)
    exit(3);

哪个也成功,但总是返回0.这是否表示硬件问题,或者我做错了什么?

在Linux上是否有基于I2C的FM24CL64-GTR的FRAM驱动程序,API会是什么?任何链接都会有所帮助。

4 个答案:

答案 0 :(得分:6)

我没有使用该特定设备的经验,但根据我们的经验,许多I2C设备都有“怪癖”需要解决方法,通常高于驱动程序级别。

我们也使用linux(CELinux)和Linux设备驱动程序。但是我们的应用程序代码还有一个非平凡的I2C模块,其中包含处理我们所遇到的所有各种设备的所有解决方案。

此外,在处理I2C问题时,我经常发现我需要重新熟悉源规范:

http://www.nxp.com/acrobat_download/literature/9398/39340011.pdf

以及使用体面的示波器。

祝你好运,

上面的链接已经死了,以下是其他一些链接:

http://www.nxp.com/documents/user_manual/UM10204.pdf 当然维基百科: http://en.wikipedia.org/wiki/I%C2%B2C

答案 1 :(得分:6)

NAK是一个很大的提示:WriteProtect引脚从外部上拉,并且必须被驱动到地,之后单次写入地址后跟数据字节成功(第一个代码段)。

为了读取,可以先写出地址(使用write()),然后从该地址开始读取顺序数据。

答案 2 :(得分:2)

请注意,使用struct i2c_rdwr_ioctl_datastruct i2c_msg(即您给出的最后一个代码部分)的方法比其他方法更有效,因为使用该方法执行重复启动I2c的功能。

这意味着您可以避免STA-WRITE-STO -> STA-READ-<data>...-STO转换,因为您的通信将变为STA-WRITE-RS-READ-<data>...STORS =重复启动)。因此,为您节省了多余的STO-STA瞬态。

并不是说它在很多时候都有所不同,但如果不需要,为什么会失去它......

只是我的2克拉。

最佳rgds,

答案 3 :(得分:0)

你犯了一些错误!

$elemnt['#attached']['css_inline'] = // Your css 的地址为ic十六进制,Ax可以是任何内容,但4位高位应为x !!!