14

我正在尝试读取/写入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。这是从 FRAM 读取的代码:

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 上是否有任何用于 FM24CL64-GTR over I2C 的 FRAM 驱动程序,API 是什么?任何链接都会有所帮助。

4

4 回答 4

7

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

我们也在 Linux 中使用 linux (CELinux) 和 I2C 设备驱动程序。但我们的应用程序代码也有一个重要的 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

于 2009-02-02T21:56:53.200 回答
6

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

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

于 2009-02-04T22:35:01.607 回答
2

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

这意味着您避免了STA-WRITE-STO -> STA-READ-<data>...-STO过渡,因为您的沟通将变成STA-WRITE-RS-READ-<data>...STORS=重复开始)。因此,为您节省了多余的STO-STA瞬态。

并不是说它在时间上有很大的不同,但是如果不需要它,为什么会失去它……

只是我的 2 克拉。

最好的rgds,

于 2013-12-30T18:53:00.207 回答
0

你犯了一些错误!

的地址icAx十六进制的,x可以是除了高 4 位之外的任何东西A=1010 !!!

于 2016-01-17T10:32:56.377 回答