linux i2c 设备节点读写

最近需要操作24C02,封装了一下函数方便以后操作。

参考链接:

  https://my.oschina.net/handawei/blog/68526

  http://blog.csdn.net/onetwothreef/article/details/49488443

源码:
#include <stdio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

#define I2C_DEFAULT_TIMEOUT     1
#define I2C_DEFAULT_RETRY       3

/*
 * fd       : 文件描述符
 * timeout  : 发送超时时间
 * retry    : 重复发送次数
 */
//重复发送次数可以设多一点,在调试的时候,只设置了一次,导致有时候发送会失败。
int i2c_set(int fd, unsigned int timeout, unsigned int retry)
{
    if (fd == 0 )
        return -1;

    if (ioctl(fd, I2C_TIMEOUT, timeout ? timeout : I2C_DEFAULT_TIMEOUT) < 0)
        return -1;
    if (ioctl(fd, I2C_RETRIES, retry ? retry : I2C_DEFAULT_RETRY) < 0)
        return -1;

    return 0;
}
/*
 * fd   : 文件描述符
 * addr : i2c的设备地址
 * reg  : 寄存器地址
 * val  : 要写的数据
 * 描述 :从指定地址写数据
 */
int i2c_byte_write(int fd, unsigned char addr, unsigned char reg, unsigned char val)
{
    int ret = 0;
    unsigned char outbuf[2];
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages;

    packets.nmsgs = 1;
    packets.msgs = &messages;

    //发送要读取的寄存器地址
    messages.addr = addr;
    messages.flags = 0;
    messages.len = 2;       //寄存器地址加数据,共发送2个字节
    messages.buf = outbuf;
    outbuf[0] = reg;
    outbuf[1] = val;

    ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets);   //读出来
    if (ret < 0)
        ret = -1;

    return ret;
}

/*  
 * fd   : 文件描述符
 * addr : i2c的设备地址
 * reg  : 寄存器地址
 * val  : 要写的数据
 * len  : 数据长度
 * 描述 :从指定地址写数据
 *        24c02以8字节为1个page,如果在一个page里面写,写的字节长度超过这个page的末尾,
 *        就会从page的开头写,覆盖开头的内容
 */
int i2c_nbytes_write(int fd, unsigned char addr, unsigned char reg, unsigned char *val, int len)
{
    int ret = 0;
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages;
    int i;

    packets.nmsgs = 1;
    packets.msgs = &messages;

    //发送要读取的寄存器地址
    messages.addr = addr;
    messages.flags = 0;         //write
    messages.len = len + 1;     //数据长度
    //发送数据
    messages.buf = (unsigned char *)malloc(len+1);
    if (NULL == messages.buf)
    {
        ret = -1;
        goto err;
    }

    messages.buf[0] = reg;
    for (i = 0; i < len; i++)
    {
        messages.buf[1+i] = val[i];
    }

    ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets);//读出来
    if (ret < 0){
        printf("write error!\n");
        return -1;
    }

err:
    free(messages.buf);

    return ret;
}

/*  
 * fd   : 文件描述符
 * addr : i2c的设备地址
 * val  : 保存读取数据
 * 描述 :从当前地址读取一个字节数据
 */
int i2c_byte_read(int fd, unsigned char addr, unsigned char *val)
{
    int ret = 0;
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages;

    packets.nmsgs = 1;              //数据帧类型只有一种,读操作,只需要发送一个起始信号,因此是1
    packets.msgs = &messages;

    //发送要读取的寄存器地址
    messages.addr = addr;           //i2c设备地址
    messages.flags = I2C_M_RD;      //读操作
    messages.len = 1;               //数据长度
    messages.buf = val;             //读取的数据保存在val

    ret = ioctl (fd, I2C_RDWR, (unsigned long)&packets);  //发送数据帧
    if (ret < 0)
        ret = -1;

    return ret;
}

/*
 * fd   : 文件描述符
 * addr : i2c的设备地址
 * reg  : 寄存器地址
 * val  : 保存读取的数据
 * len  : 读取数据的长度
 * 描述 :读取达到eeprom的末尾时,会读取最开头的字节
 */
int i2c_nbytes_read(int fd, unsigned char addr, unsigned char reg, unsigned char *val, int len)
{
    int ret = 0;
    unsigned char outbuf;
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[2];

    /* 数据帧类型有2种
     * 写要发送起始信号,进行写寄存器操作,再发送起始信号,进行读操作,
     * 有2个起始信号,因此需要分开来操作。
     */
    packets.nmsgs = 2;           
    //发送要读取的寄存器地址
    messages[0].addr = addr;
    messages[0].flags = 0;              //write
    messages[0].len = 1;                //数据长度
    messages[0].buf = &outbuf;          //发送寄存器地址
    outbuf = reg;
    //读取数据
    messages[1].len = len;                           //读取数据长度
    messages[1].addr = addr;                         //设备地址
    messages[1].flags = I2C_M_RD;                    //read
    messages[1].buf = val;

    packets.msgs = messages;

    ret = ioctl(fd, I2C_RDWR, (unsigned long)&packets); //发送i2c,进行读取操作 
    if (ret < 0)
        ret = -1;

    return ret;
}

Tony Liu

2016-9-23, Shenzhen

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 内核的 I2C 驱动中,通常会提供设备读写节点,以便用户空间程序可以通过文件系统接口来访问 I2C 设备。这些节点一般位于 `/dev` 目录下,命名规则为 `i2c-X`,其中 X 是 I2C 控制器的编号。 例如,如果系统中有一个名为 `i2c-1` 的 I2C 控制器,那么对应的设备节点为 `/dev/i2c-1`。 在 Android 上层,可以使用 Java 的 `FileInputStream` 和 `FileOutputStream` 类来读写 I2C 设备。需要先打开对应的设备节点,然后通过文件流进行读写操作。 以下是一个简单的读写示例: ```java import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class I2CExample { private static final String I2C_DEVICE = "/dev/i2c-1"; private static final int I2C_ADDRESS = 0x50; public static void main(String[] args) { try { // 打开 I2C 设备节点 FileInputStream input = new FileInputStream(I2C_DEVICE); FileOutputStream output = new FileOutputStream(I2C_DEVICE); // 写入数据 byte[] writeBuffer = { 0x00, 0x01, 0x02 }; output.write(writeBuffer); // 读取数据 byte[] readBuffer = new byte[3]; input.read(readBuffer); // 关闭文件流 input.close(); output.close(); System.out.println("Read data: " + toHexString(readBuffer)); } catch (IOException e) { e.printStackTrace(); } } private static String toHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X ", b)); } return sb.toString(); } } ``` 以上示例中,我们打开了 `/dev/i2c-1` 设备节点,并且使用地址 `0x50` 进行了一次写操作和一次读操作。读取到的数据会以十六进制字符串的形式输出到控制台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值