设为首页收藏本站
查看: 13296|回复: 0

用户空间读写I2C EEPROM

[复制链接]

25

主题

9

回帖

280

积分

中级会员

积分
280
Willian.Mo 发表于 2015-7-28 15:28:40 | 显示全部楼层 |阅读模式
本帖最后由 Willian.Mo 于 2015-7-28 17:18 编辑

准备

对于内核注册的i2c适配器,用户空间可以通过open、ioctl、write、read等函数与i2c设备交互。在Linux内核代码文件/include/linux/i2c-dev.c中针对每个适配器生成一个主设备号为89的设备节点,实现了文件操作接口,用户空间可以通过i2c设备节点访问i2c适配器。
(1)打开适配器

[mw_shl_code=c,true]if ((fd = open("/dev/i2c-1",O_RDWR)) <  0) {
    /* 错误处理 */
    exit(1);
}[/mw_shl_code]

打开适配器对应的设备节点,i2c-dev为打开的线程建立一个i2c_client,但是这个i2c_client并不加到i2c_adapter的client链表当中。当用户关闭设备节点时,它自动被释放。


(2)设置地址模式[mw_shl_code=c,true]if (ioctl(fd, I2C_TENBIT, 0)  <  0) {
/* 错误处理 */
    exit(1);
}[/mw_shl_code]
0表示7比特模式,非0表示10比特模式,默认是7比特模式。

(3)设置从机地址
[mw_shl_code=c,true]if (ioctl(fd, I2C_SLAVE_FORCE, slave_addr) < 0) {
/* 错误处理 */
    exit(1);
}[/mw_shl_code]
在调用read()和write()函数之前必须设置从机地址。


(4)读写操作
对I2C的读写操作可以参考内核源码中相关文档介绍,这里不再介绍
文档:Documentation/i2c/dev-interface

用户空间读写I2C EEPROM例子
1.twi.c文件:[mw_shl_code=c,true]#include "twi.h"
#include "i2c-dev.h"
#include <linux/types.h>
#define PAGE_SIZE 128
/* I2C file description */
static int fd;
/* I2C initialize flag */
static RET_STATUS init_flag = FAILD;
/* Send buffer */
static char buffer[PAGE_SIZE + 2];

RET_STATUS i2c_init(const char *dev_pathname,  long slave_addr)
{
        if (!dev_pathname) {
                return FAILD;
        }

        /* Open i2c device */
        fd = open(dev_pathname, O_RDWR);
        if (fd < 0) {
                perror("[info] Open i2c device error");
                return FAILD;
        }

        /* Set i2c addresses with normal 7 bit */
        if (ioctl(fd, I2C_TENBIT, 0) < 0) {
                perror("[info] Ioctl i2c TENBIT error");
                return FAILD;
        }

        /* Set slave device address */
        if (ioctl(fd, I2C_SLAVE_FORCE, slave_addr) < 0) {
                perror("[info] Ioctl i2c slave error");
                return FAILD;
        }
        init_flag = SUCCESS;

        return SUCCESS;
}

RET_STATUS i2c_write(const char *send_buf, int addr, int *num)
{
        int send_bytes = 0;
        int count      = 0;
        int res;
        int i;
        char buf[3];

        if (init_flag == FAILD) {
                printf("[info] I2C hasn't initialized.\n");
                return FAILD;
        }

        if (!send_buf) {
                return FAILD;
        }

        if (*num > strlen(send_buf)) {
                *num = strlen(send_buf);
        }


        for (i = 0; i < *num; ++i,++addr) {
                buf[0] = addr >> 8;
                buf[1] = addr;
                buf[2] = *(send_buf + i);
                /*
                 * 根据at24c512b写字节时序
                 * 设备地址,2个8位数据地址,1个8位数据
                 */
                res = i2c_smbus_write_word_data(fd, buf[0], buf[2] << 8 | buf[1]);
                usleep(5000);

                if (res < 0) {
                        perror("[info] Writing occur error");
                        return FAILD;
                }
                count += res;
        }   
        *num = count;

        return SUCCESS;
}

RET_STATUS i2c_read(char *recv_buf, int addr, const int buf_size, int *num)
{
        char buf[2];
        int res;
        int i;
        int count = 0;

        if ((recv_buf == NULL) ||
                (buf_size < 0) ||
                (*num < 0)) {
                return FAILD;
        }
        
        buf[0] = addr >> 8;
        buf[1] = addr;
        /*
         * 设置读数据的起始地址
         */
        res = i2c_smbus_write_byte_data(fd, buf[0], buf[1]);
        if (res < 0) {
                perror("[info] Writing address occur error");
                return FAILD;
        }
        
        for (i = 0; i < *num; ++i) {
                *(recv_buf + i) = i2c_smbus_read_byte(fd);
                if (*(recv_buf + i) < 0) {
                        perror("[info] Reading occur error");
                        break;
                }

                ++count;
        }

        *(recv_buf + count) = '\0';
        
        *num = count;
        if (*num > count) {
                return FAILD;
        }

        return SUCCESS;
}

void i2c_deinit(void)
{
        close(fd);
}
[/mw_shl_code]
2.main.c文件:
[mw_shl_code=c,true]#include "twi.h"
#define I2C_DEV     "/dev/i2c-0"
#define SLAVE_ADDR  0x51
#define BUF_SIZE    128

int main(int argc, char *argv[])
{
        char send_data[BUF_SIZE] = "This is test data, If reading this string, Testing is successful";
        char recv_data[BUF_SIZE] = { 0 };
        int  len = 0;
        int  addr = 0x10;

        printf("Initialize i2c device\n");
        if (i2c_init(I2C_DEV, SLAVE_ADDR) == FAILD) {
                printf("[info] Initialize i2c faild\n");
                return 1;
        }

        printf("Write data to eeprom 0x%x via I2C\n", addr);
        len = strlen(send_data);
        if (i2c_write(send_data, addr, &len) == FAILD) {
                printf("[info] Write data to eeprom faild\n");
                return 2;
        }

        sleep(1);
        printf("Read data from eeprom 0x%x via I2C\n", addr);
        len = BUF_SIZE - 1;
        if (i2c_read(recv_data, addr, BUF_SIZE, &len) == FAILD) {
                printf("[info] Read data from eeprom faild\n");
                return 3;
        }
        printf("Read content: %s\n", recv_data);
        
        return 0;
}
[/mw_shl_code]

3.完整程序见附件

twi-eeprom.rar

12.09 KB, 下载次数: 10907

回复

使用道具 举报

您需要登录后才可以回帖 登录

本版积分规则

Archiver|手机版|小黑屋|米尔科技论坛   

GMT+8, 2024-11-24 07:14 , Processed in 0.049151 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表