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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM