1. 程式人生 > >linux下I2C的讀寫

linux下I2C的讀寫

1.在linux下提供另種I2C讀寫方式:

 a.  一種是帶暫存器讀寫的方式。(因為很多I2C裝置的操作都是讀寫暫存器,所以Linux提供了這樣一種介面)

 b.一種是純粹的資料傳送。(a實際上呼叫的是b來實現)

a.方式的實現:

以下這個結構體,定義在#include <linux/i2c-dev.h> 中, 裡邊有command引數,也就是暫存器地址。

//定義結構體

struct i2c_smbus_ioctl_data args;

//填充資料

args.read_write = read_write;
args.command = command;
args.size = size;
args.data = data;

//寫資料

ioctl(file,I2C_SMBUS,&args)

b.方式的實現

// 定義結構體

struct i2c_rdwr_ioctl_data  bh1200_data; 

// 填充資料

bh1200_data.nmsgs = 1;
bh1200_data.msgs = (struct i2c_msg *)malloc(bh1200_data.nmsgs * sizeof(struct i2c_msg));
bh1200_data.msgs[0].len = len;
bh1200_data.msgs[0].addr = BH1200_DEV_ADDR;
bh1200_data.msgs[0].flags = 0;
bh1200_data.msgs[0].buf = (unsigned char*)malloc(len);
memcpy((void *)bh1200_data.msgs[0].buf, value, len);

//寫資料

ioctl (g_bh1200fd, I2C_RDWR, (unsigned long)&bh1200_data);

以下內容轉自別的地方:

drivers/i2c/i2c-dev.c中的ioctl驅動介面,其實兩個介面本質差不多,特別是寫,關鍵是你把command當成暫存器還是資料,只是I2C_SMBUS這個你需要傳送的一組的資料的第1個位元組當成暫存器,即command,其餘的作為資料;而I2C_RDWR則更通用,沒有暫存器這個說法,都看成資料,所以I2c_transfer是最通用的介面。

所謂的smbus,只是對傳送的資料格式增加的限定而已,基於內容的特定協議,它最終還是要呼叫i2c_transfer

的。

以下內容來自實際測試:

1.如果向一個從機發送一串資料,而從機沒有響應,則後續資料好像不會發送,如下圖,後邊資料不再發送


2. 我想忽略應答,設定以下命令

  struct i2c_msg {

    __u16 addr;    /* slave address          */
    __u16 flags;
#define I2C_M_TEN      0x0010  /* this is a ten bit chip address */
#define I2C_M_RD       0x0001  /* read data, from slave to master */
#define I2C_M_STOP     0x8000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART      0x4000  /* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR 0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK   0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK        0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN     0x0400  /* length will be first received byte */
    __u16 len;     /* msg length             */
    __u8 *buf;     /* pointer to msg data          */
};

  但是需要I2C_FUNC_PROTOCOL_MANGLING這個功能支援。

  我去xilinx的I2C 驅動看了下,發現它不支援這個功能。

  static u32 xiic_func(struct i2c_adapter *adap)
 {
    return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;    // 沒有I2C_FUNC_PROTOCOL_MANGLING 這個功能。
 }